From c696171ff15f0ee60dea4abfd99a135473c95656 Mon Sep 17 00:00:00 2001 From: dim Date: Thu, 15 Jan 2015 22:31:35 +0000 Subject: Vendor import of clang RELEASE_351/final tag r225668 (effectively, 3.5.1 release): https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_351/final@225668 --- docs/ReleaseNotes.rst | 58 +--------- include/clang/Basic/DiagnosticSemaKinds.td | 3 + lib/CodeGen/CGExprScalar.cpp | 12 +- lib/CodeGen/TargetInfo.cpp | 47 +++++--- lib/Sema/SemaDecl.cpp | 29 ++++- lib/Sema/SemaTemplate.cpp | 39 ++----- test/CodeGen/atomics-inlining.c | 8 +- test/CodeGen/mips-byval-arg.c | 4 +- test/CodeGen/mips-varargs.c | 176 +++++++++++++++++++++++++++++ test/CodeGen/mips-vector-arg.c | 16 +-- test/CodeGen/mips-vector-return.c | 6 +- test/CodeGen/mips-zero-sized-struct.c | 16 +++ test/CodeGen/mips64-class-return.cpp | 8 +- test/CodeGen/mips64-padding-arg.c | 18 +-- test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp | 12 +- test/Driver/cl-x86-flags.c | 34 +++--- test/Driver/mips-cs.cpp | 18 +++ test/Driver/mips-fsf.cpp | 94 +++++++++++++++ test/Makefile | 1 + test/Misc/backend-optimization-failure.cpp | 4 +- test/Sema/dllexport.c | 12 ++ test/Sema/dllimport.c | 21 +++- test/Sema/types.c | 1 + test/SemaCXX/dllexport.cpp | 20 +++- test/SemaCXX/dllimport.cpp | 20 +++- test/SemaTemplate/deduction.cpp | 32 +++++- test/lit.cfg | 7 ++ 27 files changed, 542 insertions(+), 174 deletions(-) create mode 100644 test/CodeGen/mips-varargs.c create mode 100644 test/CodeGen/mips-zero-sized-struct.c diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index dc1c88b..5ff136e 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -===================================== -Clang 3.5 (In-Progress) Release Notes -===================================== +======================= +Clang 3.5 Release Notes +======================= .. contents:: :local: @@ -8,12 +8,6 @@ Clang 3.5 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Clang 3.5 release. You may - prefer the `Clang 3.4 Release Notes - `_. - Introduction ============ @@ -188,16 +182,6 @@ directive just prior to the desired loop. The directive allows vectorization and interleaving to be enabled or disabled. Vector width as well as interleave count can be manually specified. See :ref:`langext-pragma-loop` for details. -C Language Changes in Clang ---------------------------- - -... - -C11 Feature Support -^^^^^^^^^^^^^^^^^^^ - -... - C++ Language Changes in Clang ----------------------------- @@ -207,8 +191,6 @@ C++ Language Changes in Clang references, and `-fsanitize=null` can be used to detect null references being formed at runtime. -- ... - C++17 Feature Support ^^^^^^^^^^^^^^^^^^^^^ @@ -227,16 +209,6 @@ Additionally, trigraphs are not recognized by default in this mode. Note that these features may be changed or removed in future Clang releases without notice. -Objective-C Language Changes in Clang -------------------------------------- - -... - -OpenCL C Language Changes in Clang ----------------------------------- - -... - OpenMP C/C++ Language Changes in Clang -------------------------------------- @@ -254,11 +226,6 @@ this section should help get you past the largest hurdles of upgrading. - Clang uses `std::unique_ptr` in many places where it used to use raw `T *` pointers. -libclang --------- - -... - Static Analyzer --------------- @@ -282,25 +249,6 @@ instead of `report-XXXXXX.html`, scan-build/clang analyzer generate List the function/method name in the index page of scan-build. -... - -Core Analysis Improvements -========================== - -- ... - -New Issues Found -================ - -- ... - -Python Binding Changes ----------------------- - -The following methods have been added: - -- ... - Significant Known Problems ========================== diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 89749ed..1665a45 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -2115,6 +2115,9 @@ def warn_attribute_invalid_on_definition : Warning< InGroup; def err_attribute_dll_redeclaration : Error< "redeclaration of %q0 cannot add %q1 attribute">; +def warn_attribute_dll_redeclaration : Warning< + "redeclaration of %q0 should not add %q1 attribute">, + InGroup>; def err_attribute_dllimport_function_definition : Error< "dllimport cannot be applied to non-inline function definition">; def err_attribute_dll_deleted : Error< diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 9e0fbcf..140e9aa 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -3216,18 +3216,26 @@ Value *ScalarExprEmitter::VisitChooseExpr(ChooseExpr *E) { Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) { QualType Ty = VE->getType(); + if (Ty->isVariablyModifiedType()) CGF.EmitVariablyModifiedType(Ty); llvm::Value *ArgValue = CGF.EmitVAListRef(VE->getSubExpr()); llvm::Value *ArgPtr = CGF.EmitVAArg(ArgValue, VE->getType()); + llvm::Type *ArgTy = ConvertType(VE->getType()); // If EmitVAArg fails, we fall back to the LLVM instruction. if (!ArgPtr) - return Builder.CreateVAArg(ArgValue, ConvertType(VE->getType())); + return Builder.CreateVAArg(ArgValue, ArgTy); // FIXME Volatility. - return Builder.CreateLoad(ArgPtr); + llvm::Value *Val = Builder.CreateLoad(ArgPtr); + + // If EmitVAArg promoted the type, we must truncate it. + if (ArgTy != Val->getType()) + Val = Builder.CreateTrunc(Val, ArgTy); + + return Val; } Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *block) { diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 5da22c3..f75e59d 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -5446,15 +5446,19 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t &Offset) const { // If we have reached here, aggregates are passed directly by coercing to // another structure type. Padding is inserted if the offset of the // aggregate is unaligned. - return ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0, - getPaddingType(OrigOffset, CurrOffset)); + ABIArgInfo ArgInfo = + ABIArgInfo::getDirect(HandleAggregates(Ty, TySize), 0, + getPaddingType(OrigOffset, CurrOffset)); + ArgInfo.setInReg(true); + return ArgInfo; } // Treat an enum type as its underlying type. if (const EnumType *EnumTy = Ty->getAs()) Ty = EnumTy->getDecl()->getIntegerType(); - if (Ty->isPromotableIntegerType()) + // All integral types are promoted to the GPR width. + if (Ty->isIntegralOrEnumerationType()) return ABIArgInfo::getExtend(); return ABIArgInfo::getDirect( @@ -5506,7 +5510,12 @@ MipsABIInfo::returnAggregateInRegs(QualType RetTy, uint64_t Size) const { ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { uint64_t Size = getContext().getTypeSize(RetTy); - if (RetTy->isVoidType() || Size == 0) + if (RetTy->isVoidType()) + return ABIArgInfo::getIgnore(); + + // O32 doesn't treat zero-sized structs differently from other structs. + // However, N32/N64 ignores zero sized return values. + if (!IsO32 && Size == 0) return ABIArgInfo::getIgnore(); if (isAggregateTypeForABI(RetTy) || RetTy->isVectorType()) { @@ -5514,12 +5523,15 @@ ABIArgInfo MipsABIInfo::classifyReturnType(QualType RetTy) const { if (RetTy->isAnyComplexType()) return ABIArgInfo::getDirect(); - // O32 returns integer vectors in registers. - if (IsO32 && RetTy->isVectorType() && !RetTy->hasFloatingRepresentation()) - return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); - - if (!IsO32) - return ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); + // O32 returns integer vectors in registers and N32/N64 returns all small + // aggregates in registers.. + if (!IsO32 || + (RetTy->isVectorType() && !RetTy->hasFloatingRepresentation())) { + ABIArgInfo ArgInfo = + ABIArgInfo::getDirect(returnAggregateInRegs(RetTy, Size)); + ArgInfo.setInReg(true); + return ArgInfo; + } } return ABIArgInfo::getIndirect(0); @@ -5549,11 +5561,20 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, CodeGenFunction &CGF) const { llvm::Type *BP = CGF.Int8PtrTy; llvm::Type *BPP = CGF.Int8PtrPtrTy; + + // Integer arguments are promoted 32-bit on O32 and 64-bit on N32/N64. + unsigned SlotSizeInBits = IsO32 ? 32 : 64; + if (Ty->isIntegerType() && + CGF.getContext().getIntWidth(Ty) < SlotSizeInBits) { + Ty = CGF.getContext().getIntTypeForBitwidth(SlotSizeInBits, + Ty->isSignedIntegerType()); + } CGBuilderTy &Builder = CGF.Builder; llvm::Value *VAListAddrAsBPP = Builder.CreateBitCast(VAListAddr, BPP, "ap"); llvm::Value *Addr = Builder.CreateLoad(VAListAddrAsBPP, "ap.cur"); - int64_t TypeAlign = getContext().getTypeAlign(Ty) / 8; + int64_t TypeAlign = + std::min(getContext().getTypeAlign(Ty) / 8, StackAlignInBytes); llvm::Type *PTy = llvm::PointerType::getUnqual(CGF.ConvertType(Ty)); llvm::Value *AddrTyped; unsigned PtrWidth = getTarget().getPointerWidth(0); @@ -5572,8 +5593,8 @@ llvm::Value* MipsABIInfo::EmitVAArg(llvm::Value *VAListAddr, QualType Ty, llvm::Value *AlignedAddr = Builder.CreateBitCast(AddrTyped, BP); TypeAlign = std::max((unsigned)TypeAlign, MinABIStackAlignInBytes); - uint64_t Offset = - llvm::RoundUpToAlignment(CGF.getContext().getTypeSize(Ty) / 8, TypeAlign); + unsigned ArgSizeInBits = CGF.getContext().getTypeSize(Ty); + uint64_t Offset = llvm::RoundUpToAlignment(ArgSizeInBits / 8, TypeAlign); llvm::Value *NextAddr = Builder.CreateGEP(AlignedAddr, llvm::ConstantInt::get(IntTy, Offset), "ap.next"); diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index bbe6930..8716227 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -5020,7 +5020,7 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, NewDecl = NewTD->getTemplatedDecl(); if (!OldDecl || !NewDecl) - return; + return; const DLLImportAttr *OldImportAttr = OldDecl->getAttr(); const DLLExportAttr *OldExportAttr = OldDecl->getAttr(); @@ -5037,13 +5037,30 @@ static void checkDLLAttributeRedeclaration(Sema &S, NamedDecl *OldDecl, // Implicitly generated declarations are also excluded for now because there // is no other way to switch these to use dllimport or dllexport. bool AddsAttr = !(OldImportAttr || OldExportAttr) && HasNewAttr; + if (AddsAttr && !IsSpecialization && !OldDecl->isImplicit()) { - S.Diag(NewDecl->getLocation(), diag::err_attribute_dll_redeclaration) - << NewDecl - << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr); + // If the declaration hasn't been used yet, allow with a warning for + // free functions and global variables. + bool JustWarn = false; + if (!OldDecl->isUsed() && !OldDecl->isCXXClassMember()) { + auto *VD = dyn_cast(OldDecl); + if (VD && !VD->getDescribedVarTemplate()) + JustWarn = true; + auto *FD = dyn_cast(OldDecl); + if (FD && FD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) + JustWarn = true; + } + + unsigned DiagID = JustWarn ? diag::warn_attribute_dll_redeclaration + : diag::err_attribute_dll_redeclaration; + S.Diag(NewDecl->getLocation(), DiagID) + << NewDecl + << (NewImportAttr ? (const Attr *)NewImportAttr : NewExportAttr); S.Diag(OldDecl->getLocation(), diag::note_previous_declaration); - NewDecl->setInvalidDecl(); - return; + if (!JustWarn) { + NewDecl->setInvalidDecl(); + return; + } } // A redeclaration is not allowed to drop a dllimport attribute, the only diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 63581a4..7e8f0b7 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3692,12 +3692,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgumentPack.size(), Converted)) return true; - if (TemplateArgs[ArgIdx].getArgument().isPackExpansion() && - isa(Template) && - !(Param + 1 == ParamEnd && (*Param)->isTemplateParameterPack() && - !getExpandedPackSize(*Param))) { + bool PackExpansionIntoNonPack = + TemplateArgs[ArgIdx].getArgument().isPackExpansion() && + (!(*Param)->isTemplateParameterPack() || getExpandedPackSize(*Param)); + if (PackExpansionIntoNonPack && isa(Template)) { // Core issue 1430: we have a pack expansion as an argument to an - // alias template, and it's not part of a final parameter pack. This + // alias template, and it's not part of a parameter pack. This // can't be canonicalized, so reject it now. Diag(TemplateArgs[ArgIdx].getLocation(), diag::err_alias_template_expansion_into_fixed_list) @@ -3720,16 +3720,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ++Param; } - // If we just saw a pack expansion, then directly convert the remaining - // arguments, because we don't know what parameters they'll match up - // with. - if (TemplateArgs[ArgIdx-1].getArgument().isPackExpansion()) { - bool InFinalParameterPack = Param != ParamEnd && - Param + 1 == ParamEnd && - (*Param)->isTemplateParameterPack() && - !getExpandedPackSize(*Param); - - if (!InFinalParameterPack && !ArgumentPack.empty()) { + // If we just saw a pack expansion into a non-pack, then directly convert + // the remaining arguments, because we don't know what parameters they'll + // match up with. + if (PackExpansionIntoNonPack) { + if (!ArgumentPack.empty()) { // If we were part way through filling in an expanded parameter pack, // fall back to just producing individual arguments. Converted.insert(Converted.end(), @@ -3738,22 +3733,10 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, } while (ArgIdx < NumArgs) { - if (InFinalParameterPack) - ArgumentPack.push_back(TemplateArgs[ArgIdx].getArgument()); - else - Converted.push_back(TemplateArgs[ArgIdx].getArgument()); + Converted.push_back(TemplateArgs[ArgIdx].getArgument()); ++ArgIdx; } - // Push the argument pack onto the list of converted arguments. - if (InFinalParameterPack) { - Converted.push_back( - TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); - ArgumentPack.clear(); - } - return false; } diff --git a/test/CodeGen/atomics-inlining.c b/test/CodeGen/atomics-inlining.c index 6456e74..ec916e1 100644 --- a/test/CodeGen/atomics-inlining.c +++ b/test/CodeGen/atomics-inlining.c @@ -76,8 +76,8 @@ void test1(void) { // MIPS32: store atomic i32 {{.*}}, i32* @i1 seq_cst // MIPS32: call i64 @__atomic_load_8(i8* bitcast (i64* @ll1 to i8*) // MIPS32: call void @__atomic_store_8(i8* bitcast (i64* @ll1 to i8*), i64 -// MIPS32: call void @__atomic_load(i32 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) -// MIPS32: call void @__atomic_store(i32 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) +// MIPS32: call void @__atomic_load(i32 zeroext 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) +// MIPS32: call void @__atomic_store(i32 zeroext 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) // MIPS64-LABEL: define void @test1 // MIPS64: = load atomic i8* @c1 seq_cst @@ -88,6 +88,6 @@ void test1(void) { // MIPS64: store atomic i32 {{.*}}, i32* @i1 seq_cst // MIPS64: = load atomic i64* @ll1 seq_cst // MIPS64: store atomic i64 {{.*}}, i64* @ll1 seq_cst -// MIPS64: call void @__atomic_load(i64 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0) -// MIPS64: call void @__atomic_store(i64 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) +// MIPS64: call void @__atomic_load(i64 zeroext 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0) +// MIPS64: call void @__atomic_store(i64 zeroext 100, i8* getelementptr inbounds ([100 x i8]* @a1, i32 0, i32 0), i8* getelementptr inbounds ([100 x i8]* @a2, i32 0, i32 0) } diff --git a/test/CodeGen/mips-byval-arg.c b/test/CodeGen/mips-byval-arg.c index 589e85e..0e3d334 100644 --- a/test/CodeGen/mips-byval-arg.c +++ b/test/CodeGen/mips-byval-arg.c @@ -7,8 +7,8 @@ typedef struct { extern void foo2(S0); -// O32-LABEL: define void @foo1(i32 %a0.coerce0, i32 %a0.coerce1, i32 %a0.coerce2) -// N64-LABEL: define void @foo1(i64 %a0.coerce0, i32 %a0.coerce1) +// O32-LABEL: define void @foo1(i32 inreg %a0.coerce0, i32 inreg %a0.coerce1, i32 inreg %a0.coerce2) +// N64-LABEL: define void @foo1(i64 inreg %a0.coerce0, i32 inreg %a0.coerce1) void foo1(S0 a0) { foo2(a0); diff --git a/test/CodeGen/mips-varargs.c b/test/CodeGen/mips-varargs.c new file mode 100644 index 0000000..ad202ff --- /dev/null +++ b/test/CodeGen/mips-varargs.c @@ -0,0 +1,176 @@ +// RUN: %clang_cc1 -triple mips-unknown-linux -o - -O1 -emit-llvm %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 +// RUN: %clang_cc1 -triple mipsel-unknown-linux -o - -O1 -emit-llvm %s | FileCheck %s -check-prefix=ALL -check-prefix=O32 +// RUN: %clang_cc1 -triple mips64-unknown-linux -o - -O1 -emit-llvm -target-abi n32 %s | FileCheck %s -check-prefix=ALL -check-prefix=N32 -check-prefix=NEW +// RUN: %clang_cc1 -triple mips64-unknown-linux -o - -O1 -emit-llvm -target-abi n32 %s | FileCheck %s -check-prefix=ALL -check-prefix=N32 -check-prefix=NEW +// RUN: %clang_cc1 -triple mips64-unknown-linux -o - -O1 -emit-llvm %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NEW +// RUN: %clang_cc1 -triple mips64el-unknown-linux -o - -O1 -emit-llvm %s | FileCheck %s -check-prefix=ALL -check-prefix=N64 -check-prefix=NEW + +#include + +typedef int v4i32 __attribute__ ((__vector_size__ (16))); + +int test_i32(char *fmt, ...) { + va_list va; + + va_start(va, fmt); + int v = va_arg(va, int); + va_end(va); + + return v; +} + +// ALL-LABEL: define i32 @test_i32(i8*{{.*}} %fmt, ...) +// +// O32: %va = alloca i8*, align [[PTRALIGN:4]] +// N32: %va = alloca i8*, align [[PTRALIGN:4]] +// N64: %va = alloca i8*, align [[PTRALIGN:8]] +// +// ALL: [[VA1:%.+]] = bitcast i8** %va to i8* +// ALL: call void @llvm.va_start(i8* [[VA1]]) +// +// ALL: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] +// +// O32: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i32* +// NEW: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i64* +// +// O32: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], i32 4 +// NEW: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], {{i32|i64}} 8 +// +// ALL: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// +// O32: [[ARG1:%.+]] = load i32* [[TMP0]], align 4 +// NEW: [[TMP2:%.+]] = load i64* [[TMP0]], align 8 +// NEW: [[ARG1:%.+]] = trunc i64 [[TMP2]] to i32 +// +// ALL: call void @llvm.va_end(i8* [[VA1]]) +// ALL: ret i32 [[ARG1]] +// ALL: } + +int test_i32_2args(char *fmt, ...) { + va_list va; + + va_start(va, fmt); + int v1 = va_arg(va, int); + int v2 = va_arg(va, int); + va_end(va); + + return v1 + v2; +} + +// ALL-LABEL: define i32 @test_i32_2args(i8*{{.*}} %fmt, ...) +// +// ALL: %va = alloca i8*, align [[PTRALIGN]] +// ALL: [[VA1:%.+]] = bitcast i8** %va to i8* +// ALL: call void @llvm.va_start(i8* [[VA1]]) +// +// ALL: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] +// +// O32: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i32* +// NEW: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i64* +// +// O32: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], i32 4 +// NEW: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], [[INTPTR_T:i32|i64]] 8 +// +// O32: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// FIXME: N32 optimised this store out. Why only for this ABI? +// N64: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// +// O32: [[ARG1:%.+]] = load i32* [[TMP0]], align 4 +// NEW: [[TMP3:%.+]] = load i64* [[TMP0]], align 8 +// NEW: [[ARG1:%.+]] = trunc i64 [[TMP3]] to i32 +// +// O32: [[TMP1:%.+]] = bitcast i8* [[AP_NEXT]] to i32* +// NEW: [[TMP1:%.+]] = bitcast i8* [[AP_NEXT]] to i64* +// +// O32: [[AP_NEXT3:%.+]] = getelementptr i8* [[AP_CUR]], i32 8 +// NEW: [[AP_NEXT3:%.+]] = getelementptr i8* [[AP_CUR]], [[INTPTR_T]] 16 +// +// ALL: store i8* [[AP_NEXT3]], i8** %va, align [[PTRALIGN]] +// +// O32: [[ARG2:%.+]] = load i32* [[TMP1]], align 4 +// NEW: [[TMP4:%.+]] = load i64* [[TMP1]], align 8 +// NEW: [[ARG2:%.+]] = trunc i64 [[TMP4]] to i32 +// +// ALL: call void @llvm.va_end(i8* [[VA1]]) +// ALL: [[ADD:%.+]] = add nsw i32 [[ARG2]], [[ARG1]] +// ALL: ret i32 [[ADD]] +// ALL: } + +long long test_i64(char *fmt, ...) { + va_list va; + + va_start(va, fmt); + long long v = va_arg(va, long long); + va_end(va); + + return v; +} + +// ALL-LABEL: define i64 @test_i64(i8*{{.*}} %fmt, ...) +// +// ALL: %va = alloca i8*, align [[PTRALIGN]] +// ALL: [[VA1:%.+]] = bitcast i8** %va to i8* +// ALL: call void @llvm.va_start(i8* [[VA1]]) +// +// ALL: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] +// +// NEW: [[TMP0:%.+]] = bitcast i8* [[AP_CUR]] to i64* +// +// i64 is 8-byte aligned, while this is within O32's stack alignment there's no +// guarantee that the offset is still 8-byte aligned after earlier reads. +// O32: [[PTR0:%.+]] = ptrtoint i8* [[AP_CUR]] to [[INTPTR_T:i32]] +// O32: [[PTR1:%.+]] = add i32 [[PTR0]], 7 +// O32: [[PTR2:%.+]] = and i32 [[PTR1]], -8 +// O32: [[PTR3:%.+]] = inttoptr [[INTPTR_T]] [[PTR2]] to i64* +// O32: [[PTR4:%.+]] = inttoptr [[INTPTR_T]] [[PTR2]] to i8* +// +// O32: [[AP_NEXT:%.+]] = getelementptr i8* [[PTR4]], [[INTPTR_T]] 8 +// NEW: [[AP_NEXT:%.+]] = getelementptr i8* [[AP_CUR]], [[INTPTR_T]] 8 +// +// ALL: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// +// O32: [[ARG1:%.+]] = load i64* [[PTR3]], align 8 +// NEW: [[ARG1:%.+]] = load i64* [[TMP0]], align 8 +// +// ALL: call void @llvm.va_end(i8* [[VA1]]) +// ALL: ret i64 [[ARG1]] +// ALL: } + +int test_v4i32(char *fmt, ...) { + va_list va; + + va_start(va, fmt); + v4i32 v = va_arg(va, v4i32); + va_end(va); + + return v[0]; +} + +// ALL-LABEL: define i32 @test_v4i32(i8*{{.*}} %fmt, ...) +// +// ALL: %va = alloca i8*, align [[PTRALIGN]] +// ALL: [[VA1:%.+]] = bitcast i8** %va to i8* +// ALL: call void @llvm.va_start(i8* [[VA1]]) +// ALL: [[AP_CUR:%.+]] = load i8** %va, align [[PTRALIGN]] +// +// O32: [[PTR0:%.+]] = ptrtoint i8* [[AP_CUR]] to [[INTPTR_T:i32]] +// N32: [[PTR0:%.+]] = ptrtoint i8* [[AP_CUR]] to [[INTPTR_T:i32]] +// N64: [[PTR0:%.+]] = ptrtoint i8* [[AP_CUR]] to [[INTPTR_T:i64]] +// +// Vectors are 16-byte aligned, however the O32 ABI has a maximum alignment of +// 8-bytes since the base of the stack is 8-byte aligned. +// O32: [[PTR1:%.+]] = add i32 [[PTR0]], 7 +// O32: [[PTR2:%.+]] = and i32 [[PTR1]], -8 +// +// NEW: [[PTR1:%.+]] = add [[INTPTR_T]] [[PTR0]], 15 +// NEW: [[PTR2:%.+]] = and [[INTPTR_T]] [[PTR1]], -16 +// +// ALL: [[PTR3:%.+]] = inttoptr [[INTPTR_T]] [[PTR2]] to <4 x i32>* +// ALL: [[PTR4:%.+]] = inttoptr [[INTPTR_T]] [[PTR2]] to i8* +// ALL: [[AP_NEXT:%.+]] = getelementptr i8* [[PTR4]], [[INTPTR_T]] 16 +// ALL: store i8* [[AP_NEXT]], i8** %va, align [[PTRALIGN]] +// ALL: [[PTR5:%.+]] = load <4 x i32>* [[PTR3]], align 16 +// ALL: call void @llvm.va_end(i8* [[VA1]]) +// ALL: [[VECEXT:%.+]] = extractelement <4 x i32> [[PTR5]], i32 0 +// ALL: ret i32 [[VECEXT]] +// ALL: } diff --git a/test/CodeGen/mips-vector-arg.c b/test/CodeGen/mips-vector-arg.c index 6ffb043..f8c89df 100644 --- a/test/CodeGen/mips-vector-arg.c +++ b/test/CodeGen/mips-vector-arg.c @@ -8,19 +8,19 @@ typedef float v4sf __attribute__ ((__vector_size__ (16))); typedef int v4i32 __attribute__ ((__vector_size__ (16))); -// O32: define void @test_v4sf(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) [[NUW:#[0-9]+]] -// O32: declare i32 @test_v4sf_2(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) -// N64: define void @test_v4sf(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) [[NUW:#[0-9]+]] -// N64: declare i32 @test_v4sf_2(i64, i64, i32, i64, i64, i64) +// O32: define void @test_v4sf(i32 inreg %a1.coerce0, i32 inreg %a1.coerce1, i32 inreg %a1.coerce2, i32 inreg %a1.coerce3, i32 signext %a2, i32, i32 inreg %a3.coerce0, i32 inreg %a3.coerce1, i32 inreg %a3.coerce2, i32 inreg %a3.coerce3) [[NUW:#[0-9]+]] +// O32: declare i32 @test_v4sf_2(i32 inreg, i32 inreg, i32 inreg, i32 inreg, i32 signext, i32, i32 inreg, i32 inreg, i32 inreg, i32 inreg) +// N64: define void @test_v4sf(i64 inreg %a1.coerce0, i64 inreg %a1.coerce1, i32 signext %a2, i64, i64 inreg %a3.coerce0, i64 inreg %a3.coerce1) [[NUW:#[0-9]+]] +// N64: declare i32 @test_v4sf_2(i64 inreg, i64 inreg, i32 signext, i64, i64 inreg, i64 inreg) extern test_v4sf_2(v4sf, int, v4sf); void test_v4sf(v4sf a1, int a2, v4sf a3) { test_v4sf_2(a3, a2, a1); } -// O32: define void @test_v4i32(i32 %a1.coerce0, i32 %a1.coerce1, i32 %a1.coerce2, i32 %a1.coerce3, i32 %a2, i32, i32 %a3.coerce0, i32 %a3.coerce1, i32 %a3.coerce2, i32 %a3.coerce3) [[NUW]] -// O32: declare i32 @test_v4i32_2(i32, i32, i32, i32, i32, i32, i32, i32, i32, i32) -// N64: define void @test_v4i32(i64 %a1.coerce0, i64 %a1.coerce1, i32 %a2, i64, i64 %a3.coerce0, i64 %a3.coerce1) [[NUW]] -// N64: declare i32 @test_v4i32_2(i64, i64, i32, i64, i64, i64) +// O32: define void @test_v4i32(i32 inreg %a1.coerce0, i32 inreg %a1.coerce1, i32 inreg %a1.coerce2, i32 inreg %a1.coerce3, i32 signext %a2, i32, i32 inreg %a3.coerce0, i32 inreg %a3.coerce1, i32 inreg %a3.coerce2, i32 inreg %a3.coerce3) [[NUW]] +// O32: declare i32 @test_v4i32_2(i32 inreg, i32 inreg, i32 inreg, i32 inreg, i32 signext, i32, i32 inreg, i32 inreg, i32 inreg, i32 inreg) +// N64: define void @test_v4i32(i64 inreg %a1.coerce0, i64 inreg %a1.coerce1, i32 signext %a2, i64, i64 inreg %a3.coerce0, i64 inreg %a3.coerce1) [[NUW]] +// N64: declare i32 @test_v4i32_2(i64 inreg, i64 inreg, i32 signext, i64, i64 inreg, i64 inreg) extern test_v4i32_2(v4i32, int, v4i32); void test_v4i32(v4i32 a1, int a2, v4i32 a3) { test_v4i32_2(a3, a2, a1); diff --git a/test/CodeGen/mips-vector-return.c b/test/CodeGen/mips-vector-return.c index a7c8ce1..8af4998 100644 --- a/test/CodeGen/mips-vector-return.c +++ b/test/CodeGen/mips-vector-return.c @@ -9,7 +9,7 @@ typedef double v4df __attribute__ ((__vector_size__ (32))); typedef int v4i32 __attribute__ ((__vector_size__ (16))); // O32-LABEL: define void @test_v4sf(<4 x float>* noalias nocapture sret -// N64: define { i64, i64 } @test_v4sf +// N64: define inreg { i64, i64 } @test_v4sf v4sf test_v4sf(float a) { return (v4sf){0.0f, a, 0.0f, 0.0f}; } @@ -23,8 +23,8 @@ v4df test_v4df(double a) { // O32 returns integer vectors whose size is equal to or smaller than 16-bytes // in integer registers. // -// O32: define { i32, i32, i32, i32 } @test_v4i32 -// N64: define { i64, i64 } @test_v4i32 +// O32: define inreg { i32, i32, i32, i32 } @test_v4i32 +// N64: define inreg { i64, i64 } @test_v4i32 v4i32 test_v4i32(int a) { return (v4i32){0, a, 0, 0}; } diff --git a/test/CodeGen/mips-zero-sized-struct.c b/test/CodeGen/mips-zero-sized-struct.c new file mode 100644 index 0000000..afff3b4 --- /dev/null +++ b/test/CodeGen/mips-zero-sized-struct.c @@ -0,0 +1,16 @@ +// RUN: %clang -target mips-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=O32 %s +// RUN: %clang -target mipsel-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=O32 %s +// RUN: %clang -target mips64-unknown-linux-gnu -S -emit-llvm -o - %s -mabi=n32 | FileCheck -check-prefix=N32 %s +// RUN: %clang -target mips64el-unknown-linux-gnu -S -emit-llvm -o - %s -mabi=n32 | FileCheck -check-prefix=N32 %s +// RUN: %clang -target mips64-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s +// RUN: %clang -target mips64el-unknown-linux-gnu -S -emit-llvm -o - %s | FileCheck -check-prefix=N64 %s + +// O32: define void @fn28(%struct.T2* noalias sret %agg.result, i8 signext %arg0) +// N32: define void @fn28(i8 signext %arg0) +// N64: define void @fn28(i8 signext %arg0) + +typedef struct T2 { } T2; +T2 T2_retval; +T2 fn28(char arg0) { + return T2_retval; +} diff --git a/test/CodeGen/mips64-class-return.cpp b/test/CodeGen/mips64-class-return.cpp index a473c13..57fa8ef 100644 --- a/test/CodeGen/mips64-class-return.cpp +++ b/test/CodeGen/mips64-class-return.cpp @@ -24,22 +24,22 @@ extern D0 gd0; extern D1 gd1; extern D2 gd2; -// CHECK: define { i64, i64 } @_Z4foo1v() +// CHECK: define inreg { i64, i64 } @_Z4foo1v() D0 foo1(void) { return gd0; } -// CHECK: define { double, float } @_Z4foo2v() +// CHECK: define inreg { double, float } @_Z4foo2v() D1 foo2(void) { return gd1; } -// CHECK-LABEL: define void @_Z4foo32D2(i64 %a0.coerce0, double %a0.coerce1) +// CHECK-LABEL: define void @_Z4foo32D2(i64 inreg %a0.coerce0, double inreg %a0.coerce1) void foo3(D2 a0) { gd2 = a0; } -// CHECK-LABEL: define void @_Z4foo42D0(i64 %a0.coerce0, i64 %a0.coerce1) +// CHECK-LABEL: define void @_Z4foo42D0(i64 inreg %a0.coerce0, i64 inreg %a0.coerce1) void foo4(D0 a0) { gd0 = a0; } diff --git a/test/CodeGen/mips64-padding-arg.c b/test/CodeGen/mips64-padding-arg.c index 49a29c1..b92098f 100644 --- a/test/CodeGen/mips64-padding-arg.c +++ b/test/CodeGen/mips64-padding-arg.c @@ -9,9 +9,9 @@ typedef struct { // Insert padding to ensure arguments of type S0 are aligned to 16-byte boundaries. -// N64-LABEL: define void @foo1(i32 %a0, i64, double %a1.coerce0, i64 %a1.coerce1, i64 %a1.coerce2, i64 %a1.coerce3, double %a2.coerce0, i64 %a2.coerce1, i64 %a2.coerce2, i64 %a2.coerce3, i32 %b, i64, double %a3.coerce0, i64 %a3.coerce1, i64 %a3.coerce2, i64 %a3.coerce3) -// N64: tail call void @foo2(i32 1, i32 2, i32 %a0, i64 undef, double %a1.coerce0, i64 %a1.coerce1, i64 %a1.coerce2, i64 %a1.coerce3, double %a2.coerce0, i64 %a2.coerce1, i64 %a2.coerce2, i64 %a2.coerce3, i32 3, i64 undef, double %a3.coerce0, i64 %a3.coerce1, i64 %a3.coerce2, i64 %a3.coerce3) -// N64: declare void @foo2(i32, i32, i32, i64, double, i64, i64, i64, double, i64, i64, i64, i32, i64, double, i64, i64, i64) +// N64-LABEL: define void @foo1(i32 signext %a0, i64, double inreg %a1.coerce0, i64 inreg %a1.coerce1, i64 inreg %a1.coerce2, i64 inreg %a1.coerce3, double inreg %a2.coerce0, i64 inreg %a2.coerce1, i64 inreg %a2.coerce2, i64 inreg %a2.coerce3, i32 signext %b, i64, double inreg %a3.coerce0, i64 inreg %a3.coerce1, i64 inreg %a3.coerce2, i64 inreg %a3.coerce3) +// N64: tail call void @foo2(i32 signext 1, i32 signext 2, i32 signext %a0, i64 undef, double inreg %a1.coerce0, i64 inreg %a1.coerce1, i64 inreg %a1.coerce2, i64 inreg %a1.coerce3, double inreg %a2.coerce0, i64 inreg %a2.coerce1, i64 inreg %a2.coerce2, i64 inreg %a2.coerce3, i32 signext 3, i64 undef, double inreg %a3.coerce0, i64 inreg %a3.coerce1, i64 inreg %a3.coerce2, i64 inreg %a3.coerce3) +// N64: declare void @foo2(i32 signext, i32 signext, i32 signext, i64, double inreg, i64 inreg, i64 inreg, i64 inreg, double inreg, i64 inreg, i64 inreg, i64 inreg, i32 signext, i64, double inreg, i64 inreg, i64 inreg, i64 inreg) extern void foo2(int, int, int, S0, S0, int, S0); @@ -21,9 +21,9 @@ void foo1(int a0, S0 a1, S0 a2, int b, S0 a3) { // Insert padding before long double argument. // -// N64-LABEL: define void @foo3(i32 %a0, i64, fp128 %a1) -// N64: tail call void @foo4(i32 1, i32 2, i32 %a0, i64 undef, fp128 %a1) -// N64: declare void @foo4(i32, i32, i32, i64, fp128) +// N64-LABEL: define void @foo3(i32 signext %a0, i64, fp128 %a1) +// N64: tail call void @foo4(i32 signext 1, i32 signext 2, i32 signext %a0, i64 undef, fp128 %a1) +// N64: declare void @foo4(i32 signext, i32 signext, i32 signext, i64, fp128) extern void foo4(int, int, int, long double); @@ -34,8 +34,8 @@ void foo3(int a0, long double a1) { // Insert padding after hidden argument. // // N64-LABEL: define void @foo5(%struct.S0* noalias sret %agg.result, i64, fp128 %a0) -// N64: call void @foo6(%struct.S0* sret %agg.result, i32 1, i32 2, i64 undef, fp128 %a0) -// N64: declare void @foo6(%struct.S0* sret, i32, i32, i64, fp128) +// N64: call void @foo6(%struct.S0* sret %agg.result, i32 signext 1, i32 signext 2, i64 undef, fp128 %a0) +// N64: declare void @foo6(%struct.S0* sret, i32 signext, i32 signext, i64, fp128) extern S0 foo6(int, int, long double); @@ -55,7 +55,7 @@ void foo7(float a0, double a1) { } // O32-LABEL: define void @foo9() -// O32: declare void @foo10(i32, i32 +// O32: declare void @foo10(i32 signext, i32 typedef struct __attribute__((aligned(16))) { int a; diff --git a/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp index 92e704a..869fded 100644 --- a/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp +++ b/test/CodeGenCXX/mips-size_t-ptrdiff_t.cpp @@ -10,13 +10,13 @@ long *alloc_long() { return rv; } // O32-LABEL: define i32* @_Z10alloc_longv() -// O32: call noalias i8* @_Znwj(i32 4) +// O32: call noalias i8* @_Znwj(i32 zeroext 4) // N32-LABEL: define i32* @_Z10alloc_longv() -// N32: call noalias i8* @_Znwj(i32 4) +// N32: call noalias i8* @_Znwj(i32 zeroext 4) // N64-LABEL: define i64* @_Z10alloc_longv() -// N64: call noalias i8* @_Znwm(i64 8) +// N64: call noalias i8* @_Znwm(i64 zeroext 8) long *alloc_long_array() { long *rv = new long[2]; @@ -24,13 +24,13 @@ long *alloc_long_array() { } // O32-LABEL: define i32* @_Z16alloc_long_arrayv() -// O32: call noalias i8* @_Znaj(i32 8) +// O32: call noalias i8* @_Znaj(i32 zeroext 8) // N32-LABEL: define i32* @_Z16alloc_long_arrayv() -// N32: call noalias i8* @_Znaj(i32 8) +// N32: call noalias i8* @_Znaj(i32 zeroext 8) // N64-LABEL: define i64* @_Z16alloc_long_arrayv() -// N64: call noalias i8* @_Znam(i64 16) +// N64: call noalias i8* @_Znam(i64 zeroext 16) #include diff --git a/test/Driver/cl-x86-flags.c b/test/Driver/cl-x86-flags.c index 62083db..5aae4c4 100644 --- a/test/Driver/cl-x86-flags.c +++ b/test/Driver/cl-x86-flags.c @@ -9,73 +9,73 @@ // MFLAGS-NOT: argument unused during compilation // -arch:IA32 is no-op. -// RUN: %clang_cl -m32 -arch:IA32 -### -- 2>&1 %s | FileCheck -check-prefix=IA32 %s +// RUN: %clang_cl -m32 -arch:IA32 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=IA32 %s // IA32-NOT: argument unused during compilation // IA32-NOT: -target-feature -// RUN: %clang_cl -m32 -arch:ia32 -### -- 2>&1 %s | FileCheck -check-prefix=ia32 %s +// RUN: %clang_cl -m32 -arch:ia32 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=ia32 %s // ia32: argument unused during compilation // ia32-NOT: -target-feature -// RUN: %clang_cl -m64 -arch:IA32 -### -- 2>&1 %s | FileCheck -check-prefix=IA3264 %s +// RUN: %clang_cl -m64 -arch:IA32 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=IA3264 %s // IA3264: argument unused during compilation // IA3264-NOT: -target-feature -// RUN: %clang_cl -m32 -arch:SSE -### -- 2>&1 %s | FileCheck -check-prefix=SSE %s +// RUN: %clang_cl -m32 -arch:SSE --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=SSE %s // SSE: -target-feature // SSE: +sse // SSE-NOT: argument unused during compilation -// RUN: %clang_cl -m32 -arch:sse -### -- 2>&1 %s | FileCheck -check-prefix=sse %s +// RUN: %clang_cl -m32 -arch:sse --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=sse %s // sse: argument unused during compilation // sse-NOT: -target-feature -// RUN: %clang_cl -m32 -arch:SSE2 -### -- 2>&1 %s | FileCheck -check-prefix=SSE2 %s +// RUN: %clang_cl -m32 -arch:SSE2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=SSE2 %s // SSE2: -target-feature // SSE2: +sse2 // SSE2-NOT: argument unused during compilation -// RUN: %clang_cl -m32 -arch:sse2 -### -- 2>&1 %s | FileCheck -check-prefix=sse %s +// RUN: %clang_cl -m32 -arch:sse2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=sse %s // sse2: argument unused during compilation // sse2-NOT: -target-feature -// RUN: %clang_cl -m64 -arch:SSE -### -- 2>&1 %s | FileCheck -check-prefix=SSE64 %s +// RUN: %clang_cl -m64 -arch:SSE --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=SSE64 %s // SSE64: argument unused during compilation // SSE64-NOT: -target-feature -// RUN: %clang_cl -m64 -arch:SSE2 -### -- 2>&1 %s | FileCheck -check-prefix=SSE264 %s +// RUN: %clang_cl -m64 -arch:SSE2 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=SSE264 %s // SSE264: argument unused during compilation // SSE264-NOT: -target-feature -// RUN: %clang_cl -m32 -arch:AVX -### -- 2>&1 %s | FileCheck -check-prefix=AVX %s +// RUN: %clang_cl -m32 -arch:AVX --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=AVX %s // AVX: -target-feature // AVX: +avx -// RUN: %clang_cl -m32 -arch:avx -### -- 2>&1 %s | FileCheck -check-prefix=avx %s +// RUN: %clang_cl -m32 -arch:avx --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=avx %s // avx: argument unused during compilation // avx-NOT: -target-feature -// RUN: %clang_cl -m32 -arch:AVX2 -### -- 2>&1 %s | FileCheck -check-prefix=AVX2 %s +// RUN: %clang_cl -m32 -arch:AVX2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=AVX2 %s // AVX2: -target-feature // AVX2: +avx2 -// RUN: %clang_cl -m32 -arch:avx2 -### -- 2>&1 %s | FileCheck -check-prefix=avx2 %s +// RUN: %clang_cl -m32 -arch:avx2 --target=i386 -### -- 2>&1 %s | FileCheck -check-prefix=avx2 %s // avx2: argument unused during compilation // avx2-NOT: -target-feature -// RUN: %clang_cl -m64 -arch:AVX -### -- 2>&1 %s | FileCheck -check-prefix=AVX64 %s +// RUN: %clang_cl -m64 -arch:AVX --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=AVX64 %s // AVX64: -target-feature // AVX64: +avx -// RUN: %clang_cl -m64 -arch:avx -### -- 2>&1 %s | FileCheck -check-prefix=avx64 %s +// RUN: %clang_cl -m64 -arch:avx --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=avx64 %s // avx64: argument unused during compilation // avx64-NOT: -target-feature -// RUN: %clang_cl -m64 -arch:AVX2 -### -- 2>&1 %s | FileCheck -check-prefix=AVX264 %s +// RUN: %clang_cl -m64 -arch:AVX2 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=AVX264 %s // AVX264: -target-feature // AVX264: +avx2 -// RUN: %clang_cl -m64 -arch:avx2 -### -- 2>&1 %s | FileCheck -check-prefix=avx264 %s +// RUN: %clang_cl -m64 -arch:avx2 --target=x86_64 -### -- 2>&1 %s | FileCheck -check-prefix=avx264 %s // avx264: argument unused during compilation // avx264-NOT: -target-feature diff --git a/test/Driver/mips-cs.cpp b/test/Driver/mips-cs.cpp index 275d615..ad031a9 100644 --- a/test/Driver/mips-cs.cpp +++ b/test/Driver/mips-cs.cpp @@ -17,6 +17,7 @@ // CHECK-BE-HF-32: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-HF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-32: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc" +// CHECK-BE-HF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-32: "[[TC]]/../../../../mips-linux-gnu/libc/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-32: "[[TC]]/../../../../mips-linux-gnu/libc/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-32: "[[TC]]{{/|\\\\}}crtbegin.o" @@ -44,6 +45,7 @@ // CHECK-BE-HF-16: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-HF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-16: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/mips16" +// CHECK-BE-HF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-16: "[[TC]]/mips16{{/|\\\\}}crtbegin.o" @@ -72,6 +74,7 @@ // CHECK-BE-HF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-HF-MICRO: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-MICRO: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/micromips" +// CHECK-BE-HF-MICRO: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-MICRO: "[[TC]]/micromips{{/|\\\\}}crtbegin.o" @@ -100,6 +103,7 @@ // CHECK-BE-HF-NAN: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-HF-NAN: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-NAN: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/nan2008" +// CHECK-BE-HF-NAN: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-HF-NAN: "[[TC]]/../../../../mips-linux-gnu/libc/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-NAN: "[[TC]]/../../../../mips-linux-gnu/libc/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-NAN: "[[TC]]/nan2008{{/|\\\\}}crtbegin.o" @@ -128,6 +132,7 @@ // CHECK-BE-SF-32: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-SF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-32: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/soft-float" +// CHECK-BE-SF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-32: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-32: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-32: "[[TC]]/soft-float{{/|\\\\}}crtbegin.o" @@ -156,6 +161,7 @@ // CHECK-BE-SF-16: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-SF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-16: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/mips16/soft-float" +// CHECK-BE-SF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/soft-float/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/soft-float/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-16: "[[TC]]/mips16/soft-float{{/|\\\\}}crtbegin.o" @@ -184,6 +190,7 @@ // CHECK-BE-SF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-SF-MICRO: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-MICRO: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/micromips/soft-float" +// CHECK-BE-SF-MICRO: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/soft-float/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/soft-float/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-MICRO: "[[TC]]/micromips/soft-float{{/|\\\\}}crtbegin.o" @@ -212,6 +219,7 @@ // CHECK-BE-HF-64: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-HF-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-64: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc" +// CHECK-BE-HF-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-HF-64: "[[TC]]/../../../../mips-linux-gnu/libc/usr/lib/../lib64{{/|\\\\}}crt1.o" // CHECK-BE-HF-64: "[[TC]]/../../../../mips-linux-gnu/libc/usr/lib/../lib64{{/|\\\\}}crti.o" // CHECK-BE-HF-64: "[[TC]]/64{{/|\\\\}}crtbegin.o" @@ -240,6 +248,7 @@ // CHECK-BE-SF-64: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-BE-SF-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-64: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/soft-float" +// CHECK-BE-SF-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-SF-64: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/usr/lib/../lib64{{/|\\\\}}crt1.o" // CHECK-BE-SF-64: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/usr/lib/../lib64{{/|\\\\}}crti.o" // CHECK-BE-SF-64: "[[TC]]/soft-float/64{{/|\\\\}}crtbegin.o" @@ -268,6 +277,7 @@ // CHECK-EL-HF-32: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-HF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-32: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/el" +// CHECK-EL-HF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-32: "[[TC]]/../../../../mips-linux-gnu/libc/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-32: "[[TC]]/../../../../mips-linux-gnu/libc/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-32: "[[TC]]/el{{/|\\\\}}crtbegin.o" @@ -296,6 +306,7 @@ // CHECK-EL-HF-16: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-HF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-16: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/mips16/el" +// CHECK-EL-HF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-16: "[[TC]]/mips16/el{{/|\\\\}}crtbegin.o" @@ -324,6 +335,7 @@ // CHECK-EL-HF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-HF-MICRO: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-MICRO: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/micromips/el" +// CHECK-EL-HF-MICRO: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-MICRO: "[[TC]]/micromips/el{{/|\\\\}}crtbegin.o" @@ -352,6 +364,7 @@ // CHECK-EL-HF-NAN: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-HF-NAN: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-NAN: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/nan2008/el" +// CHECK-EL-HF-NAN: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-HF-NAN: "[[TC]]/../../../../mips-linux-gnu/libc/nan2008/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-NAN: "[[TC]]/../../../../mips-linux-gnu/libc/nan2008/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-NAN: "[[TC]]/nan2008/el{{/|\\\\}}crtbegin.o" @@ -380,6 +393,7 @@ // CHECK-EL-SF-32: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-SF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-32: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/soft-float/el" +// CHECK-EL-SF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-32: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-32: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-32: "[[TC]]/soft-float/el{{/|\\\\}}crtbegin.o" @@ -408,6 +422,7 @@ // CHECK-EL-SF-16: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-SF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-16: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/mips16/soft-float/el" +// CHECK-EL-SF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/soft-float/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-16: "[[TC]]/../../../../mips-linux-gnu/libc/mips16/soft-float/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-16: "[[TC]]/mips16/soft-float/el{{/|\\\\}}crtbegin.o" @@ -436,6 +451,7 @@ // CHECK-EL-SF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-SF-MICRO: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-MICRO: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/micromips/soft-float/el" +// CHECK-EL-SF-MICRO: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/soft-float/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-MICRO: "[[TC]]/../../../../mips-linux-gnu/libc/micromips/soft-float/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-MICRO: "[[TC]]/micromips/soft-float/el{{/|\\\\}}crtbegin.o" @@ -464,6 +480,7 @@ // CHECK-EL-HF-64: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-HF-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-64: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/el" +// CHECK-EL-HF-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-HF-64: "[[TC]]/../../../../mips-linux-gnu/libc/el/usr/lib/../lib64{{/|\\\\}}crt1.o" // CHECK-EL-HF-64: "[[TC]]/../../../../mips-linux-gnu/libc/el/usr/lib/../lib64{{/|\\\\}}crti.o" // CHECK-EL-HF-64: "[[TC]]/el/64{{/|\\\\}}crtbegin.o" @@ -492,6 +509,7 @@ // CHECK-EL-SF-64: "[[TC]]/../../../../mips-linux-gnu/libc/usr/include" // CHECK-EL-SF-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-64: "--sysroot=[[TC]]/../../../../mips-linux-gnu/libc/soft-float/el" +// CHECK-EL-SF-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-SF-64: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/el/usr/lib/../lib64{{/|\\\\}}crt1.o" // CHECK-EL-SF-64: "[[TC]]/../../../../mips-linux-gnu/libc/soft-float/el/usr/lib/../lib64{{/|\\\\}}crti.o" // CHECK-EL-SF-64: "[[TC]]/soft-float/el/64{{/|\\\\}}crtbegin.o" diff --git a/test/Driver/mips-fsf.cpp b/test/Driver/mips-fsf.cpp index 4520aec..34ad914 100644 --- a/test/Driver/mips-fsf.cpp +++ b/test/Driver/mips-fsf.cpp @@ -17,6 +17,7 @@ // CHECK-BE-HF-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-32: "--sysroot=[[TC]]/../../../../sysroot/mips32" +// CHECK-BE-HF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-32: "[[TC]]/../../../../sysroot/mips32/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-32: "[[TC]]/../../../../sysroot/mips32/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-32: "[[TC]]/mips32{{/|\\\\}}crtbegin.o" @@ -43,6 +44,7 @@ // CHECK-BE-HF64-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-32: "--sysroot=[[TC]]/../../../../sysroot/mips32" +// CHECK-BE-HF64-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF64-32: "[[TC]]/../../../../sysroot/mips32/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-32: "[[TC]]/../../../../sysroot/mips32/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-32: "[[TC]]/mips32{{/|\\\\}}crtbegin.o" @@ -69,6 +71,7 @@ // CHECK-BE-SF-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/sof" +// CHECK-BE-SF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-32: "[[TC]]/../../../../sysroot/mips32/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-32: "[[TC]]/../../../../sysroot/mips32/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-32: "[[TC]]/mips32/sof{{/|\\\\}}crtbegin.o" @@ -95,6 +98,7 @@ // CHECK-BE-HF-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16" +// CHECK-BE-HF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-16: "[[TC]]/../../../../sysroot/mips32/mips16/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-16: "[[TC]]/../../../../sysroot/mips32/mips16/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-16: "[[TC]]/mips32/mips16{{/|\\\\}}crtbegin.o" @@ -121,6 +125,7 @@ // CHECK-BE-HF64-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-16: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16" +// CHECK-BE-HF64-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF64-16: "[[TC]]/../../../../sysroot/mips32/mips16/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-16: "[[TC]]/../../../../sysroot/mips32/mips16/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-16: "[[TC]]/mips32/mips16{{/|\\\\}}crtbegin.o" @@ -147,6 +152,7 @@ // CHECK-BE-SF-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/sof" +// CHECK-BE-SF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-16: "[[TC]]/../../../../sysroot/mips32/mips16/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-16: "[[TC]]/../../../../sysroot/mips32/mips16/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-16: "[[TC]]/mips32/mips16/sof{{/|\\\\}}crtbegin.o" @@ -173,6 +179,7 @@ // CHECK-BE-NAN-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-16: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/nan2008" +// CHECK-BE-NAN-16: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-16: "[[TC]]/../../../../sysroot/mips32/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-16: "[[TC]]/../../../../sysroot/mips32/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-16: "[[TC]]/mips32/mips16/nan2008{{/|\\\\}}crtbegin.o" @@ -199,6 +206,7 @@ // CHECK-BE-NAN64-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-16: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/nan2008" +// CHECK-BE-NAN64-16: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-16: "[[TC]]/../../../../sysroot/mips32/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-16: "[[TC]]/../../../../sysroot/mips32/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-16: "[[TC]]/mips32/mips16/nan2008{{/|\\\\}}crtbegin.o" @@ -225,6 +233,7 @@ // CHECK-BE-NAN-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/nan2008" +// CHECK-BE-NAN-32: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-32: "[[TC]]/../../../../sysroot/mips32/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-32: "[[TC]]/../../../../sysroot/mips32/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-32: "[[TC]]/mips32/nan2008{{/|\\\\}}crtbegin.o" @@ -251,6 +260,7 @@ // CHECK-BE-NAN64-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/nan2008" +// CHECK-BE-NAN64-32: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-32: "[[TC]]/../../../../sysroot/mips32/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-32: "[[TC]]/../../../../sysroot/mips32/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-32: "[[TC]]/mips32/nan2008{{/|\\\\}}crtbegin.o" @@ -277,6 +287,7 @@ // CHECK-BE-HF-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-32R2: "--sysroot=[[TC]]/../../../../sysroot" +// CHECK-BE-HF-32R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-32R2: "[[TC]]/../../../../sysroot/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-32R2: "[[TC]]/../../../../sysroot/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-32R2: "[[TC]]{{/|\\\\}}crtbegin.o" @@ -303,6 +314,7 @@ // CHECK-BE-HF64-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-32R2: "--sysroot=[[TC]]/../../../../sysroot" +// CHECK-BE-HF64-32R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF64-32R2: "[[TC]]/../../../../sysroot/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-32R2: "[[TC]]/../../../../sysroot/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-32R2: "[[TC]]{{/|\\\\}}crtbegin.o" @@ -329,6 +341,7 @@ // CHECK-BE-SF-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-32R2: "--sysroot=[[TC]]/../../../../sysroot/sof" +// CHECK-BE-SF-32R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-32R2: "[[TC]]/../../../../sysroot/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-32R2: "[[TC]]/../../../../sysroot/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-32R2: "[[TC]]/sof{{/|\\\\}}crtbegin.o" @@ -355,6 +368,7 @@ // CHECK-BE-HF-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16" +// CHECK-BE-HF-16R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-16R2: "[[TC]]/../../../../sysroot/mips16/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-16R2: "[[TC]]/../../../../sysroot/mips16/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-16R2: "[[TC]]/mips16{{/|\\\\}}crtbegin.o" @@ -381,6 +395,7 @@ // CHECK-BE-HF64-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16" +// CHECK-BE-HF64-16R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF64-16R2: "[[TC]]/../../../../sysroot/mips16/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-16R2: "[[TC]]/../../../../sysroot/mips16/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-16R2: "[[TC]]/mips16{{/|\\\\}}crtbegin.o" @@ -407,6 +422,7 @@ // CHECK-BE-SF-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/sof" +// CHECK-BE-SF-16R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-16R2: "[[TC]]/../../../../sysroot/mips16/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-16R2: "[[TC]]/../../../../sysroot/mips16/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-16R2: "[[TC]]/mips16/sof{{/|\\\\}}crtbegin.o" @@ -433,6 +449,7 @@ // CHECK-BE-NAN-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/nan2008" +// CHECK-BE-NAN-16R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-16R2: "[[TC]]/../../../../sysroot/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-16R2: "[[TC]]/../../../../sysroot/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-16R2: "[[TC]]/mips16/nan2008{{/|\\\\}}crtbegin.o" @@ -459,6 +476,7 @@ // CHECK-BE-NAN64-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/nan2008" +// CHECK-BE-NAN64-16R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-16R2: "[[TC]]/../../../../sysroot/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-16R2: "[[TC]]/../../../../sysroot/mips16/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-16R2: "[[TC]]/mips16/nan2008{{/|\\\\}}crtbegin.o" @@ -485,6 +503,7 @@ // CHECK-BE-NAN-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-32R2: "--sysroot=[[TC]]/../../../../sysroot/nan2008" +// CHECK-BE-NAN-32R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-32R2: "[[TC]]/../../../../sysroot/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-32R2: "[[TC]]/../../../../sysroot/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-32R2: "[[TC]]/nan2008{{/|\\\\}}crtbegin.o" @@ -511,6 +530,7 @@ // CHECK-BE-NAN64-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-32R2: "--sysroot=[[TC]]/../../../../sysroot/nan2008" +// CHECK-BE-NAN64-32R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-32R2: "[[TC]]/../../../../sysroot/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-32R2: "[[TC]]/../../../../sysroot/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-32R2: "[[TC]]/nan2008{{/|\\\\}}crtbegin.o" @@ -537,6 +557,7 @@ // CHECK-BE-NAN64-32R2-DEF: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-32R2-DEF: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-32R2-DEF: "--sysroot=[[TC]]/../../../../sysroot/nan2008" +// CHECK-BE-NAN64-32R2-DEF: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-32R2-DEF: "[[TC]]/../../../../sysroot/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-32R2-DEF: "[[TC]]/../../../../sysroot/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-32R2-DEF: "[[TC]]/nan2008{{/|\\\\}}crtbegin.o" @@ -563,6 +584,7 @@ // CHECK-BE-HF-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips" +// CHECK-BE-HF-MM: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF-MM: "[[TC]]/../../../../sysroot/micromips/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-MM: "[[TC]]/../../../../sysroot/micromips/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF-MM: "[[TC]]/micromips{{/|\\\\}}crtbegin.o" @@ -589,6 +611,7 @@ // CHECK-BE-HF64-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips" +// CHECK-BE-HF64-MM: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-HF64-MM: "[[TC]]/../../../../sysroot/micromips/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-MM: "[[TC]]/../../../../sysroot/micromips/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-MM: "[[TC]]/micromips{{/|\\\\}}crtbegin.o" @@ -615,6 +638,7 @@ // CHECK-BE-SF-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/sof" +// CHECK-BE-SF-MM: "-dynamic-linker" "/lib/ld.so.1" // CHECK-BE-SF-MM: "[[TC]]/../../../../sysroot/micromips/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-MM: "[[TC]]/../../../../sysroot/micromips/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-SF-MM: "[[TC]]/micromips/sof{{/|\\\\}}crtbegin.o" @@ -641,6 +665,7 @@ // CHECK-BE-NAN-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/nan2008" +// CHECK-BE-NAN-MM: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-MM: "[[TC]]/../../../../sysroot/micromips/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-MM: "[[TC]]/../../../../sysroot/micromips/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-MM: "[[TC]]/micromips/nan2008{{/|\\\\}}crtbegin.o" @@ -667,6 +692,7 @@ // CHECK-BE-NAN64-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/nan2008" +// CHECK-BE-NAN64-MM: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-MM: "[[TC]]/../../../../sysroot/micromips/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-MM: "[[TC]]/../../../../sysroot/micromips/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-MM: "[[TC]]/micromips/nan2008{{/|\\\\}}crtbegin.o" @@ -693,6 +719,7 @@ // CHECK-BE-HF-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64" +// CHECK-BE-HF-64-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-BE-HF-64-N32: "[[TC]]/../../../../sysroot/mips64/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-64-N32: "[[TC]]/../../../../sysroot/mips64/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF-64-N32: "[[TC]]/mips64{{/|\\\\}}crtbegin.o" @@ -719,6 +746,7 @@ // CHECK-BE-HF64-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64" +// CHECK-BE-HF64-64-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-BE-HF64-64-N32: "[[TC]]/../../../../sysroot/mips64/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-64-N32: "[[TC]]/../../../../sysroot/mips64/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-64-N32: "[[TC]]/mips64{{/|\\\\}}crtbegin.o" @@ -745,6 +773,7 @@ // CHECK-BE-SF-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/sof" +// CHECK-BE-SF-64-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-BE-SF-64-N32: "[[TC]]/../../../../sysroot/mips64/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-64-N32: "[[TC]]/../../../../sysroot/mips64/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-SF-64-N32: "[[TC]]/mips64/sof{{/|\\\\}}crtbegin.o" @@ -771,6 +800,7 @@ // CHECK-BE-NAN-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/nan2008" +// CHECK-BE-NAN-64-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-64-N32: "[[TC]]/../../../../sysroot/mips64/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-64-N32: "[[TC]]/../../../../sysroot/mips64/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-64-N32: "[[TC]]/mips64/nan2008{{/|\\\\}}crtbegin.o" @@ -797,6 +827,7 @@ // CHECK-BE-NAN64-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/nan2008" +// CHECK-BE-NAN64-64-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-64-N32: "[[TC]]/../../../../sysroot/mips64/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-64-N32: "[[TC]]/../../../../sysroot/mips64/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-64-N32: "[[TC]]/mips64/nan2008{{/|\\\\}}crtbegin.o" @@ -823,6 +854,7 @@ // CHECK-BE-HF-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64" +// CHECK-BE-HF-64-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-HF-64-64: "[[TC]]/../../../../sysroot/mips64/64/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-64-64: "[[TC]]/../../../../sysroot/mips64/64/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF-64-64: "[[TC]]/mips64/64{{/|\\\\}}crtbegin.o" @@ -849,6 +881,7 @@ // CHECK-BE-HF64-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64" +// CHECK-BE-HF64-64-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-HF64-64-64: "[[TC]]/../../../../sysroot/mips64/64/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-64-64: "[[TC]]/../../../../sysroot/mips64/64/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-64-64: "[[TC]]/mips64/64{{/|\\\\}}crtbegin.o" @@ -875,6 +908,7 @@ // CHECK-BE-SF-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/sof" +// CHECK-BE-SF-64-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-SF-64-64: "[[TC]]/../../../../sysroot/mips64/64/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-64-64: "[[TC]]/../../../../sysroot/mips64/64/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-SF-64-64: "[[TC]]/mips64/64/sof{{/|\\\\}}crtbegin.o" @@ -901,6 +935,7 @@ // CHECK-BE-NAN-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/nan2008" +// CHECK-BE-NAN-64-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-64-64: "[[TC]]/../../../../sysroot/mips64/64/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-64-64: "[[TC]]/../../../../sysroot/mips64/64/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-64-64: "[[TC]]/mips64/64/nan2008{{/|\\\\}}crtbegin.o" @@ -927,6 +962,7 @@ // CHECK-BE-NAN64-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/nan2008" +// CHECK-BE-NAN64-64-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-64-64: "[[TC]]/../../../../sysroot/mips64/64/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-64-64: "[[TC]]/../../../../sysroot/mips64/64/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-64-64: "[[TC]]/mips64/64/nan2008{{/|\\\\}}crtbegin.o" @@ -953,6 +989,7 @@ // CHECK-BE-HF-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2" +// CHECK-BE-HF-64R2-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-BE-HF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF-64R2-N32: "[[TC]]/mips64r2{{/|\\\\}}crtbegin.o" @@ -979,6 +1016,7 @@ // CHECK-BE-HF64-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2" +// CHECK-BE-HF64-64R2-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-BE-HF64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-64R2-N32: "[[TC]]/mips64r2{{/|\\\\}}crtbegin.o" @@ -1005,6 +1043,7 @@ // CHECK-BE-SF-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/sof" +// CHECK-BE-SF-64R2-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-BE-SF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-SF-64R2-N32: "[[TC]]/mips64r2/sof{{/|\\\\}}crtbegin.o" @@ -1031,6 +1070,7 @@ // CHECK-BE-NAN-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/nan2008" +// CHECK-BE-NAN-64R2-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-64R2-N32: "[[TC]]/mips64r2/nan2008{{/|\\\\}}crtbegin.o" @@ -1057,6 +1097,7 @@ // CHECK-BE-NAN64-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/nan2008" +// CHECK-BE-NAN64-64R2-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-64R2-N32: "[[TC]]/mips64r2/nan2008{{/|\\\\}}crtbegin.o" @@ -1083,6 +1124,7 @@ // CHECK-BE-HF-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64" +// CHECK-BE-HF-64R2-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-HF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF-64R2-64: "[[TC]]/mips64r2/64{{/|\\\\}}crtbegin.o" @@ -1109,6 +1151,7 @@ // CHECK-BE-HF64-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-HF64-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-HF64-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64" +// CHECK-BE-HF64-64R2-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-HF64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-HF64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-HF64-64R2-64: "[[TC]]/mips64r2/64{{/|\\\\}}crtbegin.o" @@ -1135,6 +1178,7 @@ // CHECK-BE-SF-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-SF-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-SF-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/sof" +// CHECK-BE-SF-64R2-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-BE-SF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-SF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-SF-64R2-64: "[[TC]]/mips64r2/64/sof{{/|\\\\}}crtbegin.o" @@ -1161,6 +1205,7 @@ // CHECK-BE-NAN-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/nan2008" +// CHECK-BE-NAN-64R2-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-BE-NAN-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN-64R2-64: "[[TC]]/mips64r2/64/nan2008{{/|\\\\}}crtbegin.o" @@ -1187,6 +1232,7 @@ // CHECK-BE-NAN64-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/nan2008" +// CHECK-BE-NAN64-64R2-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-64R2-64: "[[TC]]/mips64r2/64/nan2008{{/|\\\\}}crtbegin.o" @@ -1213,6 +1259,7 @@ // CHECK-BE-NAN64-64R2-64-DEF: "[[TC]]/../../../../sysroot/usr/include" // CHECK-BE-NAN64-64R2-64-DEF: "{{.*}}ld{{(.exe)?}}" // CHECK-BE-NAN64-64R2-64-DEF: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/nan2008" +// CHECK-BE-NAN64-64R2-64-DEF: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-BE-NAN64-64R2-64-DEF: "[[TC]]/../../../../sysroot/mips64r2/64/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-BE-NAN64-64R2-64-DEF: "[[TC]]/../../../../sysroot/mips64r2/64/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-BE-NAN64-64R2-64-DEF: "[[TC]]/mips64r2/64/nan2008{{/|\\\\}}crtbegin.o" @@ -1239,6 +1286,7 @@ // CHECK-EL-HF-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/el" +// CHECK-EL-HF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-32: "[[TC]]/../../../../sysroot/mips32/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-32: "[[TC]]/../../../../sysroot/mips32/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-32: "[[TC]]/mips32/el{{/|\\\\}}crtbegin.o" @@ -1265,6 +1313,7 @@ // CHECK-EL-HF64-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/el" +// CHECK-EL-HF64-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF64-32: "[[TC]]/../../../../sysroot/mips32/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-32: "[[TC]]/../../../../sysroot/mips32/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-32: "[[TC]]/mips32/el{{/|\\\\}}crtbegin.o" @@ -1291,6 +1340,7 @@ // CHECK-EL-SF-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/el/sof" +// CHECK-EL-SF-32: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-32: "[[TC]]/../../../../sysroot/mips32/el/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-32: "[[TC]]/../../../../sysroot/mips32/el/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-32: "[[TC]]/mips32/el/sof{{/|\\\\}}crtbegin.o" @@ -1317,6 +1367,7 @@ // CHECK-EL-HF-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/el" +// CHECK-EL-HF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-16: "[[TC]]/mips32/mips16/el{{/|\\\\}}crtbegin.o" @@ -1343,6 +1394,7 @@ // CHECK-EL-HF64-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-16: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/el" +// CHECK-EL-HF64-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF64-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-16: "[[TC]]/mips32/mips16/el{{/|\\\\}}crtbegin.o" @@ -1369,6 +1421,7 @@ // CHECK-EL-SF-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-16: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/el/sof" +// CHECK-EL-SF-16: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-16: "[[TC]]/mips32/mips16/el/sof{{/|\\\\}}crtbegin.o" @@ -1395,6 +1448,7 @@ // CHECK-EL-NAN-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-16: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/el/nan2008" +// CHECK-EL-NAN-16: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-16: "[[TC]]/mips32/mips16/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1421,6 +1475,7 @@ // CHECK-EL-NAN64-16: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-16: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-16: "--sysroot=[[TC]]/../../../../sysroot/mips32/mips16/el/nan2008" +// CHECK-EL-NAN64-16: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-16: "[[TC]]/../../../../sysroot/mips32/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-16: "[[TC]]/mips32/mips16/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1447,6 +1502,7 @@ // CHECK-EL-NAN-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/el/nan2008" +// CHECK-EL-NAN-32: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-32: "[[TC]]/../../../../sysroot/mips32/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-32: "[[TC]]/../../../../sysroot/mips32/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-32: "[[TC]]/mips32/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1473,6 +1529,7 @@ // CHECK-EL-NAN64-32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-32: "--sysroot=[[TC]]/../../../../sysroot/mips32/el/nan2008" +// CHECK-EL-NAN64-32: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-32: "[[TC]]/../../../../sysroot/mips32/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-32: "[[TC]]/../../../../sysroot/mips32/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-32: "[[TC]]/mips32/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1499,6 +1556,7 @@ // CHECK-EL-HF-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-32R2: "--sysroot=[[TC]]/../../../../sysroot/el" +// CHECK-EL-HF-32R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-32R2: "[[TC]]/../../../../sysroot/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-32R2: "[[TC]]/../../../../sysroot/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-32R2: "[[TC]]/el{{/|\\\\}}crtbegin.o" @@ -1525,6 +1583,7 @@ // CHECK-EL-HF64-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-32R2: "--sysroot=[[TC]]/../../../../sysroot/el" +// CHECK-EL-HF64-32R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF64-32R2: "[[TC]]/../../../../sysroot/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-32R2: "[[TC]]/../../../../sysroot/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-32R2: "[[TC]]/el{{/|\\\\}}crtbegin.o" @@ -1551,6 +1610,7 @@ // CHECK-EL-SF-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-32R2: "--sysroot=[[TC]]/../../../../sysroot/el/sof" +// CHECK-EL-SF-32R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-32R2: "[[TC]]/../../../../sysroot/el/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-32R2: "[[TC]]/../../../../sysroot/el/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-32R2: "[[TC]]/el/sof{{/|\\\\}}crtbegin.o" @@ -1577,6 +1637,7 @@ // CHECK-EL-HF-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/el" +// CHECK-EL-HF-16R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-16R2: "[[TC]]/../../../../sysroot/mips16/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-16R2: "[[TC]]/../../../../sysroot/mips16/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-16R2: "[[TC]]/mips16/el{{/|\\\\}}crtbegin.o" @@ -1603,6 +1664,7 @@ // CHECK-EL-HF64-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/el" +// CHECK-EL-HF64-16R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF64-16R2: "[[TC]]/../../../../sysroot/mips16/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-16R2: "[[TC]]/../../../../sysroot/mips16/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-16R2: "[[TC]]/mips16/el{{/|\\\\}}crtbegin.o" @@ -1629,6 +1691,7 @@ // CHECK-EL-SF-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/el/sof" +// CHECK-EL-SF-16R2: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-16R2: "[[TC]]/../../../../sysroot/mips16/el/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-16R2: "[[TC]]/../../../../sysroot/mips16/el/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-16R2: "[[TC]]/mips16/el/sof{{/|\\\\}}crtbegin.o" @@ -1655,6 +1718,7 @@ // CHECK-EL-NAN-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/el/nan2008" +// CHECK-EL-NAN-16R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-16R2: "[[TC]]/../../../../sysroot/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-16R2: "[[TC]]/../../../../sysroot/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-16R2: "[[TC]]/mips16/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1681,6 +1745,7 @@ // CHECK-EL-NAN64-16R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-16R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-16R2: "--sysroot=[[TC]]/../../../../sysroot/mips16/el/nan2008" +// CHECK-EL-NAN64-16R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-16R2: "[[TC]]/../../../../sysroot/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-16R2: "[[TC]]/../../../../sysroot/mips16/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-16R2: "[[TC]]/mips16/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1707,6 +1772,7 @@ // CHECK-EL-NAN-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-32R2: "--sysroot=[[TC]]/../../../../sysroot/el/nan2008" +// CHECK-EL-NAN-32R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-32R2: "[[TC]]/../../../../sysroot/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-32R2: "[[TC]]/../../../../sysroot/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-32R2: "[[TC]]/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1733,6 +1799,7 @@ // CHECK-EL-NAN64-32R2: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-32R2: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-32R2: "--sysroot=[[TC]]/../../../../sysroot/el/nan2008" +// CHECK-EL-NAN64-32R2: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-32R2: "[[TC]]/../../../../sysroot/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-32R2: "[[TC]]/../../../../sysroot/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-32R2: "[[TC]]/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1759,6 +1826,7 @@ // CHECK-EL-NAN64-32R2-DEF: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-32R2-DEF: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-32R2-DEF: "--sysroot=[[TC]]/../../../../sysroot/el/nan2008" +// CHECK-EL-NAN64-32R2-DEF: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-32R2-DEF: "[[TC]]/../../../../sysroot/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-32R2-DEF: "[[TC]]/../../../../sysroot/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-32R2-DEF: "[[TC]]/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1785,6 +1853,7 @@ // CHECK-EL-HF-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/el" +// CHECK-EL-HF-MM: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF-MM: "[[TC]]/../../../../sysroot/micromips/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-MM: "[[TC]]/../../../../sysroot/micromips/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF-MM: "[[TC]]/micromips/el{{/|\\\\}}crtbegin.o" @@ -1811,6 +1880,7 @@ // CHECK-EL-HF64-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/el" +// CHECK-EL-HF64-MM: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-HF64-MM: "[[TC]]/../../../../sysroot/micromips/el/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-MM: "[[TC]]/../../../../sysroot/micromips/el/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-MM: "[[TC]]/micromips/el{{/|\\\\}}crtbegin.o" @@ -1837,6 +1907,7 @@ // CHECK-EL-SF-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/el/sof" +// CHECK-EL-SF-MM: "-dynamic-linker" "/lib/ld.so.1" // CHECK-EL-SF-MM: "[[TC]]/../../../../sysroot/micromips/el/sof/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-MM: "[[TC]]/../../../../sysroot/micromips/el/sof/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-SF-MM: "[[TC]]/micromips/el/sof{{/|\\\\}}crtbegin.o" @@ -1863,6 +1934,7 @@ // CHECK-EL-NAN-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/el/nan2008" +// CHECK-EL-NAN-MM: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-MM: "[[TC]]/../../../../sysroot/micromips/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-MM: "[[TC]]/../../../../sysroot/micromips/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-MM: "[[TC]]/micromips/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1889,6 +1961,7 @@ // CHECK-EL-NAN64-MM: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-MM: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-MM: "--sysroot=[[TC]]/../../../../sysroot/micromips/el/nan2008" +// CHECK-EL-NAN64-MM: "-dynamic-linker" "/lib/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-MM: "[[TC]]/../../../../sysroot/micromips/el/nan2008/usr/lib/../lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-MM: "[[TC]]/../../../../sysroot/micromips/el/nan2008/usr/lib/../lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-MM: "[[TC]]/micromips/el/nan2008{{/|\\\\}}crtbegin.o" @@ -1915,6 +1988,7 @@ // CHECK-EL-HF-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/el" +// CHECK-EL-HF-64-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-EL-HF-64-N32: "[[TC]]/../../../../sysroot/mips64/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-64-N32: "[[TC]]/../../../../sysroot/mips64/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF-64-N32: "[[TC]]/mips64/el{{/|\\\\}}crtbegin.o" @@ -1941,6 +2015,7 @@ // CHECK-EL-HF64-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/el" +// CHECK-EL-HF64-64-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-EL-HF64-64-N32: "[[TC]]/../../../../sysroot/mips64/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-64-N32: "[[TC]]/../../../../sysroot/mips64/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-64-N32: "[[TC]]/mips64/el{{/|\\\\}}crtbegin.o" @@ -1967,6 +2042,7 @@ // CHECK-EL-SF-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/el/sof" +// CHECK-EL-SF-64-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-EL-SF-64-N32: "[[TC]]/../../../../sysroot/mips64/el/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-64-N32: "[[TC]]/../../../../sysroot/mips64/el/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-SF-64-N32: "[[TC]]/mips64/el/sof{{/|\\\\}}crtbegin.o" @@ -1993,6 +2069,7 @@ // CHECK-EL-NAN-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/el/nan2008" +// CHECK-EL-NAN-64-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-64-N32: "[[TC]]/../../../../sysroot/mips64/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-64-N32: "[[TC]]/../../../../sysroot/mips64/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-64-N32: "[[TC]]/mips64/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2019,6 +2096,7 @@ // CHECK-EL-NAN64-64-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-64-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-64-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64/el/nan2008" +// CHECK-EL-NAN64-64-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-64-N32: "[[TC]]/../../../../sysroot/mips64/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-64-N32: "[[TC]]/../../../../sysroot/mips64/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-64-N32: "[[TC]]/mips64/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2045,6 +2123,7 @@ // CHECK-EL-HF-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/el" +// CHECK-EL-HF-64-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-HF-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF-64-64: "[[TC]]/mips64/64/el{{/|\\\\}}crtbegin.o" @@ -2071,6 +2150,7 @@ // CHECK-EL-HF64-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/el" +// CHECK-EL-HF64-64-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-HF64-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-64-64: "[[TC]]/mips64/64/el{{/|\\\\}}crtbegin.o" @@ -2097,6 +2177,7 @@ // CHECK-EL-SF-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/el/sof" +// CHECK-EL-SF-64-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-SF-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-SF-64-64: "[[TC]]/mips64/64/el/sof{{/|\\\\}}crtbegin.o" @@ -2123,6 +2204,7 @@ // CHECK-EL-NAN-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/el/nan2008" +// CHECK-EL-NAN-64-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-64-64: "[[TC]]/mips64/64/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2149,6 +2231,7 @@ // CHECK-EL-NAN64-64-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-64-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-64-64: "--sysroot=[[TC]]/../../../../sysroot/mips64/64/el/nan2008" +// CHECK-EL-NAN64-64-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-64-64: "[[TC]]/../../../../sysroot/mips64/64/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-64-64: "[[TC]]/mips64/64/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2175,6 +2258,7 @@ // CHECK-EL-HF-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/el" +// CHECK-EL-HF-64R2-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-EL-HF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF-64R2-N32: "[[TC]]/mips64r2/el{{/|\\\\}}crtbegin.o" @@ -2201,6 +2285,7 @@ // CHECK-EL-HF64-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/el" +// CHECK-EL-HF64-64R2-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-EL-HF64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-64R2-N32: "[[TC]]/mips64r2/el{{/|\\\\}}crtbegin.o" @@ -2227,6 +2312,7 @@ // CHECK-EL-SF-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/el/sof" +// CHECK-EL-SF-64R2-N32: "-dynamic-linker" "/lib32/ld.so.1" // CHECK-EL-SF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-SF-64R2-N32: "[[TC]]/mips64r2/el/sof{{/|\\\\}}crtbegin.o" @@ -2253,6 +2339,7 @@ // CHECK-EL-NAN-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/el/nan2008" +// CHECK-EL-NAN-64R2-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-64R2-N32: "[[TC]]/mips64r2/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2279,6 +2366,7 @@ // CHECK-EL-NAN64-64R2-N32: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-64R2-N32: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-64R2-N32: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/el/nan2008" +// CHECK-EL-NAN64-64R2-N32: "-dynamic-linker" "/lib32/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-64R2-N32: "[[TC]]/../../../../sysroot/mips64r2/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-64R2-N32: "[[TC]]/mips64r2/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2305,6 +2393,7 @@ // CHECK-EL-HF-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/el" +// CHECK-EL-HF-64R2-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-HF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF-64R2-64: "[[TC]]/mips64r2/64/el{{/|\\\\}}crtbegin.o" @@ -2331,6 +2420,7 @@ // CHECK-EL-HF64-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-HF64-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-HF64-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/el" +// CHECK-EL-HF64-64R2-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-HF64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-HF64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-HF64-64R2-64: "[[TC]]/mips64r2/64/el{{/|\\\\}}crtbegin.o" @@ -2357,6 +2447,7 @@ // CHECK-EL-SF-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-SF-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-SF-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/el/sof" +// CHECK-EL-SF-64R2-64: "-dynamic-linker" "/lib64/ld.so.1" // CHECK-EL-SF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/sof/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-SF-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/sof/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-SF-64R2-64: "[[TC]]/mips64r2/64/el/sof{{/|\\\\}}crtbegin.o" @@ -2383,6 +2474,7 @@ // CHECK-EL-NAN-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008" +// CHECK-EL-NAN-64R2-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-EL-NAN-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN-64R2-64: "[[TC]]/mips64r2/64/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2409,6 +2501,7 @@ // CHECK-EL-NAN64-64R2-64: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-64R2-64: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-64R2-64: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008" +// CHECK-EL-NAN64-64R2-64: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-64R2-64: "[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-64R2-64: "[[TC]]/mips64r2/64/el/nan2008{{/|\\\\}}crtbegin.o" @@ -2435,6 +2528,7 @@ // CHECK-EL-NAN64-64R2-64-DEF: "[[TC]]/../../../../sysroot/usr/include" // CHECK-EL-NAN64-64R2-64-DEF: "{{.*}}ld{{(.exe)?}}" // CHECK-EL-NAN64-64R2-64-DEF: "--sysroot=[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008" +// CHECK-EL-NAN64-64R2-64-DEF: "-dynamic-linker" "/lib64/ld-linux-mipsn8.so.1" // CHECK-EL-NAN64-64R2-64-DEF: "[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008/usr/lib{{/|\\\\}}crt1.o" // CHECK-EL-NAN64-64R2-64-DEF: "[[TC]]/../../../../sysroot/mips64r2/64/el/nan2008/usr/lib{{/|\\\\}}crti.o" // CHECK-EL-NAN64-64R2-64-DEF: "[[TC]]/mips64r2/64/el/nan2008{{/|\\\\}}crtbegin.o" diff --git a/test/Makefile b/test/Makefile index bd0bd2e..5cb8a8b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -46,6 +46,7 @@ lit.site.cfg: FORCE @$(ECHOPATH) s=@CLANG_BINARY_DIR@=$(PROJ_OBJ_DIR)/..=g >> lit.tmp @$(ECHOPATH) s=@CLANG_TOOLS_DIR@=$(ToolDir)=g >> lit.tmp @$(ECHOPATH) s=@TARGET_TRIPLE@=$(TARGET_TRIPLE)=g >> lit.tmp + @$(ECHOPATH) s=@LLVM_HOST_TRIPLE@=$(HOST_TRIPLE)=g >> lit.tmp @$(ECHOPATH) s=@ENABLE_CLANG_ARCMT@=$(ENABLE_CLANG_ARCMT)=g >> lit.tmp @$(ECHOPATH) s=@ENABLE_CLANG_STATIC_ANALYZER@=$(ENABLE_CLANG_STATIC_ANALYZER)=g >> lit.tmp @$(ECHOPATH) s=@ENABLE_CLANG_EXAMPLES@=$(ENABLE_CLANG_EXAMPLES)=g >> lit.tmp diff --git a/test/Misc/backend-optimization-failure.cpp b/test/Misc/backend-optimization-failure.cpp index 1b79fb3..2ee42b8 100644 --- a/test/Misc/backend-optimization-failure.cpp +++ b/test/Misc/backend-optimization-failure.cpp @@ -6,8 +6,8 @@ void test_switch(int *A, int *B, int Length) { #pragma clang loop vectorize(enable) unroll(disable) - for (int i = 0; i < Length; i++) { - /* expected-warning {{loop not vectorized: failed explicitly specified loop vectorization}} */ switch (A[i]) { + /* expected-warning {{loop not vectorized: failed explicitly specified loop vectorization}} */ for (int i = 0; i < Length; i++) { + switch (A[i]) { case 0: B[i] = 1; break; diff --git a/test/Sema/dllexport.c b/test/Sema/dllexport.c index c6d04dc..6c71ad8 100644 --- a/test/Sema/dllexport.c +++ b/test/Sema/dllexport.c @@ -39,8 +39,13 @@ __declspec(dllexport) extern int GlobalRedecl2; int GlobalRedecl2; extern int GlobalRedecl3; // expected-note{{previous declaration is here}} +int useGlobalRedecl3() { return GlobalRedecl3; } __declspec(dllexport) extern int GlobalRedecl3; // expected-error{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}} + extern int GlobalRedecl4; // expected-note{{previous declaration is here}} +__declspec(dllexport) extern int GlobalRedecl4; // expected-warning{{redeclaration of 'GlobalRedecl4' should not add 'dllexport' attribute}} + + // External linkage is required. __declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}} @@ -86,11 +91,18 @@ __declspec(dllexport) void redecl3(); void redecl3() {} void redecl4(); // expected-note{{previous declaration is here}} +void useRedecl4() { redecl4(); } __declspec(dllexport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} void redecl5(); // expected-note{{previous declaration is here}} +void useRedecl5() { redecl5(); } __declspec(dllexport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllexport' attribute}} +// Allow with a warning if the decl hasn't been used yet. + void redecl6(); // expected-note{{previous declaration is here}} +__declspec(dllexport) void redecl6(); // expected-warning{{redeclaration of 'redecl6' should not add 'dllexport' attribute}} + + // External linkage is required. __declspec(dllexport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllexport'}} diff --git a/test/Sema/dllimport.c b/test/Sema/dllimport.c index 2702453..706b0b6 100644 --- a/test/Sema/dllimport.c +++ b/test/Sema/dllimport.c @@ -64,9 +64,16 @@ int GlobalRedecl2c __attribute__((dllimport)); __declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous declaration is here}} expected-note{{previous attribute is here}} extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} +// Adding an attribute on redeclaration. extern int GlobalRedecl4; // expected-note{{previous declaration is here}} +int useGlobalRedecl4() { return GlobalRedecl4; } __declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}} +// Allow with a warning if the decl hasn't been used yet. + extern int GlobalRedecl5; // expected-note{{previous declaration is here}} +__declspec(dllimport) extern int GlobalRedecl5; // expected-warning{{redeclaration of 'GlobalRedecl5' should not add 'dllimport' attribute}} + + // External linkage is required. __declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}} @@ -124,14 +131,20 @@ __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void redecl4(); // expected-note{{previous declaration is here}} +void useRedecl4() { redecl4(); } __declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} +// Allow with a warning if the decl hasn't been used yet. + void redecl5(); // expected-note{{previous declaration is here}} +__declspec(dllimport) void redecl5(); // expected-warning{{redeclaration of 'redecl5' should not add 'dllimport' attribute}} + + // Inline redeclarations are fine. -__declspec(dllimport) void redecl5(); - inline void redecl5() {} +__declspec(dllimport) void redecl6(); + inline void redecl6() {} - void redecl6(); // expected-note{{previous declaration is here}} -__declspec(dllimport) inline void redecl6() {} // expected-error{{redeclaration of 'redecl6' cannot add 'dllimport' attribute}} + void redecl7(); // expected-note{{previous declaration is here}} +__declspec(dllimport) inline void redecl7() {} // expected-warning{{redeclaration of 'redecl7' should not add 'dllimport' attribute}} // External linkage is required. __declspec(dllimport) static int staticFunc(); // expected-error{{'staticFunc' must have external linkage when declared 'dllimport'}} diff --git a/test/Sema/types.c b/test/Sema/types.c index 778a5fe..0450de1 100644 --- a/test/Sema/types.c +++ b/test/Sema/types.c @@ -1,4 +1,5 @@ // RUN: %clang_cc1 %s -pedantic -verify -triple=x86_64-apple-darwin9 +// RUN: %clang_cc1 %s -pedantic -verify -triple=mips64-linux-gnu // rdar://6097662 typedef int (*T)[2]; diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp index 50d163a..668553b 100644 --- a/test/SemaCXX/dllexport.cpp +++ b/test/SemaCXX/dllexport.cpp @@ -53,7 +53,12 @@ __declspec(dllexport) extern int GlobalRedecl2; int GlobalRedecl2; extern int GlobalRedecl3; // expected-note{{previous declaration is here}} -__declspec(dllexport) extern int GlobalRedecl3; // expected-error{{redeclaration of 'GlobalRedecl3' cannot add 'dllexport' attribute}} +__declspec(dllexport) extern int GlobalRedecl3; // expected-warning{{redeclaration of 'GlobalRedecl3' should not add 'dllexport' attribute}} + +extern "C" { + extern int GlobalRedecl4; // expected-note{{previous declaration is here}} +__declspec(dllexport) extern int GlobalRedecl4; // expected-warning{{redeclaration of 'GlobalRedecl4' should not add 'dllexport' attribute}} +} // External linkage is required. __declspec(dllexport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllexport'}} @@ -186,10 +191,15 @@ __declspec(dllexport) void redecl2(); void redecl2() {} void redecl3(); // expected-note{{previous declaration is here}} -__declspec(dllexport) void redecl3(); // expected-error{{redeclaration of 'redecl3' cannot add 'dllexport' attribute}} +__declspec(dllexport) void redecl3(); // expected-warning{{redeclaration of 'redecl3' should not add 'dllexport' attribute}} +extern "C" { void redecl4(); // expected-note{{previous declaration is here}} -__declspec(dllexport) inline void redecl4() {} // expected-error{{redeclaration of 'redecl4' cannot add 'dllexport' attribute}} +__declspec(dllexport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllexport' attribute}} +} + + void redecl5(); // expected-note{{previous declaration is here}} +__declspec(dllexport) inline void redecl5() {} // expected-warning{{redeclaration of 'redecl5' should not add 'dllexport' attribute}} // Friend functions struct FuncFriend { @@ -200,8 +210,8 @@ struct FuncFriend { }; __declspec(dllexport) void friend1() {} void friend2() {} -__declspec(dllexport) void friend3() {} // expected-error{{redeclaration of 'friend3' cannot add 'dllexport' attribute}} -__declspec(dllexport) inline void friend4() {} // expected-error{{redeclaration of 'friend4' cannot add 'dllexport' attribute}} +__declspec(dllexport) void friend3() {} // expected-warning{{redeclaration of 'friend3' should not add 'dllexport' attribute}} +__declspec(dllexport) inline void friend4() {} // expected-warning{{redeclaration of 'friend4' should not add 'dllexport' attribute}} // Implicit declarations can be redeclared with dllexport. __declspec(dllexport) void* operator new(__SIZE_TYPE__ n); diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp index 8e826f7..889b7b9 100644 --- a/test/SemaCXX/dllimport.cpp +++ b/test/SemaCXX/dllimport.cpp @@ -75,7 +75,12 @@ __declspec(dllimport) extern int GlobalRedecl3; // expected-note{{previous decla extern int GlobalRedecl3; // expected-warning{{'GlobalRedecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} extern int GlobalRedecl4; // expected-note{{previous declaration is here}} -__declspec(dllimport) extern int GlobalRedecl4; // expected-error{{redeclaration of 'GlobalRedecl4' cannot add 'dllimport' attribute}} +__declspec(dllimport) extern int GlobalRedecl4; // expected-warning{{redeclaration of 'GlobalRedecl4' should not add 'dllimport' attribute}} + +extern "C" { + extern int GlobalRedecl5; // expected-note{{previous declaration is here}} +__declspec(dllimport) extern int GlobalRedecl5; // expected-warning{{redeclaration of 'GlobalRedecl5' should not add 'dllimport' attribute}} +} // External linkage is required. __declspec(dllimport) static int StaticGlobal; // expected-error{{'StaticGlobal' must have external linkage when declared 'dllimport'}} @@ -224,10 +229,15 @@ __declspec(dllimport) void redecl3(); // expected-note{{previous declaration is void redecl3() {} // expected-warning{{'redecl3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void redecl4(); // expected-note{{previous declaration is here}} -__declspec(dllimport) void redecl4(); // expected-error{{redeclaration of 'redecl4' cannot add 'dllimport' attribute}} +__declspec(dllimport) void redecl4(); // expected-warning{{redeclaration of 'redecl4' should not add 'dllimport' attribute}} +extern "C" { void redecl5(); // expected-note{{previous declaration is here}} -__declspec(dllimport) inline void redecl5() {} // expected-error{{redeclaration of 'redecl5' cannot add 'dllimport' attribute}} +__declspec(dllimport) void redecl5(); // expected-warning{{redeclaration of 'redecl5' should not add 'dllimport' attribute}} +} + + void redecl6(); // expected-note{{previous declaration is here}} +__declspec(dllimport) inline void redecl6() {} // expected-warning{{redeclaration of 'redecl6' should not add 'dllimport' attribute}} // Friend functions struct FuncFriend { @@ -240,8 +250,8 @@ struct FuncFriend { __declspec(dllimport) void friend1(); void friend2(); // expected-warning{{'friend2' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} void friend3() {} // expected-warning{{'friend3' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}} -__declspec(dllimport) void friend4(); // expected-error{{redeclaration of 'friend4' cannot add 'dllimport' attribute}} -__declspec(dllimport) inline void friend5() {} // expected-error{{redeclaration of 'friend5' cannot add 'dllimport' attribute}} +__declspec(dllimport) void friend4(); // expected-warning{{redeclaration of 'friend4' should not add 'dllimport' attribute}} +__declspec(dllimport) inline void friend5() {} // expected-warning{{redeclaration of 'friend5' should not add 'dllimport' attribute}} // Implicit declarations can be redeclared with dllimport. __declspec(dllimport) void* operator new(__SIZE_TYPE__ n); diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp index aecb5ee..e942289 100644 --- a/test/SemaTemplate/deduction.cpp +++ b/test/SemaTemplate/deduction.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 // Template argument deduction with template template parameters. template class A> @@ -162,3 +162,33 @@ namespace test14 { foo(a); } } + +namespace PR21536 { + template struct X; + template struct S { + static_assert(sizeof...(B) == 1, ""); + void f() { + using T = A; + using T = int; + + using U = X; + using U = X; + } + }; + template void f(S); + void g() { f(S()); } +} + +namespace PR19372 { + template class C, typename ...Us> struct BindBack { + template using apply = C; + }; + template struct Y; + template using Z = Y; + + using T = BindBack::apply<>; + using T = Z; + + using U = BindBack::apply; + using U = Z; +} diff --git a/test/lit.cfg b/test/lit.cfg index b5c5628..ccefb70 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -272,6 +272,13 @@ config.substitutions.append( ('%test_debuginfo', ' ' + config.llvm_src_root + '/ config.substitutions.append( ('%itanium_abi_triple', makeItaniumABITriple(config.target_triple)) ) config.substitutions.append( ('%ms_abi_triple', makeMSABITriple(config.target_triple)) ) +# The host triple might not be set, at least if we're compiling clang from +# an already installed llvm. +if config.host_triple and config.host_triple != '@LLVM_HOST_TRIPLE@': + config.substitutions.append( ('%target_itanium_abi_host_triple', '--target=%s' % makeItaniumABITriple(config.host_triple)) ) +else: + config.substitutions.append( ('%target_itanium_abi_host_triple', '') ) + # FIXME: Find nicer way to prohibit this. config.substitutions.append( (' clang ', """*** Do not use 'clang' in tests, use '%clang'. ***""") ) -- cgit v1.1 From 081af4da16b9046c019ca40f64b1fb7ee8c6dca1 Mon Sep 17 00:00:00 2001 From: dim Date: Sun, 18 Jan 2015 16:17:27 +0000 Subject: Vendor import of llvm RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1): https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_360/rc1@226102 --- .clang-tidy | 1 + .gitignore | 15 + CMakeLists.txt | 75 +- CODE_OWNERS.TXT | 48 +- CREDITS.TXT | 12 +- Makefile.config.in | 12 +- Makefile.rules | 16 +- README.txt | 5 +- autoconf/config.sub | 4 +- autoconf/configure.ac | 123 +- bindings/Makefile | 6 +- bindings/go/README.txt | 53 + bindings/go/build.sh | 28 + bindings/go/conftest.go | 16 + bindings/go/llvm/DIBuilderBindings.cpp | 242 + bindings/go/llvm/DIBuilderBindings.h | 135 + bindings/go/llvm/IRBindings.cpp | 100 + bindings/go/llvm/IRBindings.h | 73 + bindings/go/llvm/InstrumentationBindings.cpp | 42 + bindings/go/llvm/InstrumentationBindings.h | 38 + bindings/go/llvm/SupportBindings.cpp | 27 + bindings/go/llvm/SupportBindings.h | 30 + bindings/go/llvm/analysis.go | 68 + bindings/go/llvm/bitreader.go | 50 + bindings/go/llvm/bitwriter.go | 39 + bindings/go/llvm/dibuilder.go | 491 + bindings/go/llvm/executionengine.go | 177 + bindings/go/llvm/executionengine_test.go | 98 + bindings/go/llvm/ir.go | 1846 ++++ bindings/go/llvm/ir_test.go | 95 + bindings/go/llvm/linker.go | 32 + bindings/go/llvm/llvm_config.go.in | 12 + bindings/go/llvm/llvm_dep.go | 19 + bindings/go/llvm/string.go | 105 + bindings/go/llvm/string_test.go | 28 + bindings/go/llvm/support.go | 54 + bindings/go/llvm/target.go | 300 + bindings/go/llvm/transforms_instrumentation.go | 43 + bindings/go/llvm/transforms_ipo.go | 42 + bindings/go/llvm/transforms_pmbuilder.go | 48 + bindings/go/llvm/transforms_scalar.go | 45 + bindings/go/llvm/version.go | 21 + bindings/ocaml/CMakeLists.txt | 11 + bindings/ocaml/Makefile | 4 +- bindings/ocaml/Makefile.ocaml | 142 +- bindings/ocaml/all_backends/CMakeLists.txt | 5 + bindings/ocaml/all_backends/Makefile | 4 +- bindings/ocaml/analysis/CMakeLists.txt | 5 + bindings/ocaml/analysis/Makefile | 8 +- bindings/ocaml/analysis/analysis_ocaml.c | 9 +- bindings/ocaml/analysis/llvm_analysis.ml | 2 +- bindings/ocaml/analysis/llvm_analysis.mli | 2 +- bindings/ocaml/backends/CMakeLists.txt | 27 + bindings/ocaml/backends/META.llvm_backend.in | 1 - bindings/ocaml/backends/backend_ocaml.c | 9 +- bindings/ocaml/bitreader/CMakeLists.txt | 5 + bindings/ocaml/bitreader/Makefile | 8 +- bindings/ocaml/bitreader/bitreader_ocaml.c | 56 +- bindings/ocaml/bitreader/llvm_bitreader.ml | 17 +- bindings/ocaml/bitreader/llvm_bitreader.mli | 3 +- bindings/ocaml/bitwriter/CMakeLists.txt | 5 + bindings/ocaml/bitwriter/Makefile | 8 +- bindings/ocaml/bitwriter/bitwriter_ocaml.c | 23 +- bindings/ocaml/bitwriter/llvm_bitwriter.ml | 17 +- bindings/ocaml/bitwriter/llvm_bitwriter.mli | 19 +- bindings/ocaml/executionengine/CMakeLists.txt | 6 + bindings/ocaml/executionengine/Makefile | 13 +- .../ocaml/executionengine/executionengine_ocaml.c | 315 +- .../ocaml/executionengine/llvm_executionengine.ml | 151 +- .../ocaml/executionengine/llvm_executionengine.mli | 221 +- bindings/ocaml/irreader/CMakeLists.txt | 5 + bindings/ocaml/irreader/irreader_ocaml.c | 30 +- bindings/ocaml/irreader/llvm_irreader.ml | 3 +- bindings/ocaml/linker/CMakeLists.txt | 5 + bindings/ocaml/linker/linker_ocaml.c | 34 +- bindings/ocaml/linker/llvm_linker.ml | 13 +- bindings/ocaml/linker/llvm_linker.mli | 9 +- bindings/ocaml/llvm/CMakeLists.txt | 11 + bindings/ocaml/llvm/META.llvm.in | 11 +- bindings/ocaml/llvm/Makefile | 9 +- bindings/ocaml/llvm/llvm.ml | 81 +- bindings/ocaml/llvm/llvm.mli | 204 +- bindings/ocaml/llvm/llvm_ocaml.c | 255 +- bindings/ocaml/target/CMakeLists.txt | 5 + bindings/ocaml/target/llvm_target.ml | 5 +- bindings/ocaml/target/llvm_target.mli | 6 +- bindings/ocaml/target/target_ocaml.c | 68 +- bindings/ocaml/transforms/CMakeLists.txt | 5 + bindings/ocaml/transforms/Makefile | 2 +- bindings/ocaml/transforms/ipo/CMakeLists.txt | 5 + bindings/ocaml/transforms/ipo/Makefile | 4 +- bindings/ocaml/transforms/ipo/ipo_ocaml.c | 10 +- bindings/ocaml/transforms/ipo/llvm_ipo.ml | 70 +- bindings/ocaml/transforms/ipo/llvm_ipo.mli | 124 +- .../transforms/passmgr_builder/CMakeLists.txt | 5 + .../passmgr_builder/llvm_passmgr_builder.mli | 20 +- .../passmgr_builder/passmgr_builder_ocaml.c | 8 +- bindings/ocaml/transforms/scalar/Makefile | 19 - .../ocaml/transforms/scalar/llvm_scalar_opts.ml | 114 - .../ocaml/transforms/scalar/llvm_scalar_opts.mli | 168 - .../ocaml/transforms/scalar/scalar_opts_ocaml.c | 213 - .../ocaml/transforms/scalar_opts/CMakeLists.txt | 5 + bindings/ocaml/transforms/scalar_opts/Makefile | 19 + .../transforms/scalar_opts/llvm_scalar_opts.ml | 120 + .../transforms/scalar_opts/llvm_scalar_opts.mli | 198 + .../transforms/scalar_opts/scalar_opts_ocaml.c | 243 + bindings/ocaml/transforms/utils/CMakeLists.txt | 5 + bindings/ocaml/transforms/utils/Makefile | 19 + .../ocaml/transforms/utils/llvm_transform_utils.ml | 10 + .../transforms/utils/llvm_transform_utils.mli | 17 + .../ocaml/transforms/utils/transform_utils_ocaml.c | 31 + bindings/ocaml/transforms/vectorize/CMakeLists.txt | 5 + bindings/ocaml/transforms/vectorize/Makefile | 2 +- .../ocaml/transforms/vectorize/llvm_vectorize.ml | 15 +- .../ocaml/transforms/vectorize/llvm_vectorize.mli | 17 +- cmake/config-ix.cmake | 58 +- cmake/modules/AddLLVM.cmake | 131 +- cmake/modules/AddOCaml.cmake | 201 + cmake/modules/AddSphinxTarget.cmake | 11 +- cmake/modules/CMakeLists.txt | 2 +- cmake/modules/CheckAtomic.cmake | 5 + cmake/modules/CrossCompile.cmake | 33 + cmake/modules/FindOCaml.cmake | 103 + cmake/modules/FindSphinx.cmake | 2 + cmake/modules/GetSVN.cmake | 128 +- cmake/modules/HandleLLVMOptions.cmake | 69 +- cmake/modules/LLVM-Config.cmake | 54 +- cmake/modules/LLVMConfig.cmake.in | 2 + cmake/modules/LLVMProcessSources.cmake | 13 +- cmake/modules/Makefile | 3 +- cmake/modules/TableGen.cmake | 39 +- cmake/platforms/iOS.cmake | 47 + configure | 713 +- docs/Atomics.rst | 66 +- docs/BitCodeFormat.rst | 36 +- docs/CMake.rst | 18 +- docs/CMakeLists.txt | 43 + docs/CodeGenerator.rst | 16 +- docs/CodingStandards.rst | 21 + docs/CommandGuide/lit.rst | 18 +- docs/CommandGuide/llvm-config.rst | 2 +- docs/CommandGuide/llvm-symbolizer.rst | 7 + docs/CommandGuide/opt.rst | 23 +- docs/CommandLine.rst | 10 +- docs/CompilerWriterInfo.rst | 1 + docs/CoverageMappingFormat.rst | 576 ++ docs/DeveloperPolicy.rst | 23 + docs/ExtendingLLVM.rst | 8 +- docs/GarbageCollection.rst | 2 +- docs/GettingStarted.rst | 26 +- docs/GettingStartedVS.rst | 4 +- docs/GoldPlugin.rst | 8 +- docs/HowToSubmitABug.rst | 2 +- docs/LangRef.rst | 846 +- docs/Lexicon.rst | 9 + docs/LinkTimeOptimization.rst | 2 +- docs/MCJITDesignAndImplementation.rst | 2 +- docs/Makefile | 7 +- docs/MergeFunctions.rst | 802 ++ docs/Passes.rst | 25 +- docs/Phabricator.rst | 3 +- docs/ProgrammersManual.rst | 7 +- docs/R600Usage.rst | 43 + docs/ReleaseNotes.rst | 443 +- docs/SourceLevelDebugging.rst | 918 +- docs/StackMaps.rst | 6 + docs/Statepoints.rst | 411 + docs/TableGen/BackEnds.rst | 3 +- docs/TableGen/LangIntro.rst | 13 +- docs/TableGen/LangRef.rst | 6 +- docs/TableGen/index.rst | 5 +- docs/TestingGuide.rst | 54 +- docs/WritingAnLLVMBackend.rst | 2 +- docs/WritingAnLLVMPass.rst | 13 +- docs/conf.py | 4 +- docs/index.rst | 25 +- docs/tutorial/LangImpl3.rst | 2 +- docs/tutorial/LangImpl4.rst | 2 +- docs/tutorial/LangImpl5.rst | 2 +- docs/tutorial/LangImpl6.rst | 2 +- docs/tutorial/LangImpl7.rst | 2 +- docs/tutorial/LangImpl8.rst | 716 +- docs/tutorial/LangImpl9.rst | 267 + examples/BrainF/BrainFDriver.cpp | 21 +- examples/BrainF/CMakeLists.txt | 1 - examples/BrainF/Makefile | 2 +- examples/ExceptionDemo/CMakeLists.txt | 1 + examples/ExceptionDemo/ExceptionDemo.cpp | 14 +- examples/ExceptionDemo/Makefile | 2 +- examples/Fibonacci/CMakeLists.txt | 1 - examples/Fibonacci/Makefile | 2 +- examples/Fibonacci/fibonacci.cpp | 8 +- examples/HowToUseJIT/CMakeLists.txt | 1 - examples/HowToUseJIT/HowToUseJIT.cpp | 7 +- examples/HowToUseJIT/Makefile | 2 +- examples/Kaleidoscope/CMakeLists.txt | 9 + examples/Kaleidoscope/Chapter2/CMakeLists.txt | 2 +- examples/Kaleidoscope/Chapter3/CMakeLists.txt | 2 +- examples/Kaleidoscope/Chapter4/CMakeLists.txt | 6 +- examples/Kaleidoscope/Chapter4/Makefile | 2 +- examples/Kaleidoscope/Chapter4/toy.cpp | 268 +- examples/Kaleidoscope/Chapter5/CMakeLists.txt | 6 +- examples/Kaleidoscope/Chapter5/Makefile | 2 +- examples/Kaleidoscope/Chapter5/toy.cpp | 465 +- examples/Kaleidoscope/Chapter6/CMakeLists.txt | 6 +- examples/Kaleidoscope/Chapter6/Makefile | 2 +- examples/Kaleidoscope/Chapter6/toy.cpp | 520 +- examples/Kaleidoscope/Chapter7/CMakeLists.txt | 6 +- examples/Kaleidoscope/Chapter7/Makefile | 2 +- examples/Kaleidoscope/Chapter7/toy.cpp | 604 +- examples/Kaleidoscope/Chapter8/CMakeLists.txt | 18 + examples/Kaleidoscope/Chapter8/Makefile | 16 + examples/Kaleidoscope/Chapter8/toy.cpp | 1494 +++ examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp | 1 - examples/Kaleidoscope/MCJIT/cached/toy.cpp | 1 - examples/Kaleidoscope/MCJIT/complete/toy.cpp | 129 +- examples/Kaleidoscope/MCJIT/initial/toy.cpp | 1 - examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp | 1 - examples/Kaleidoscope/MCJIT/lazy/toy.cpp | 1 - examples/Kaleidoscope/Makefile | 2 +- examples/ParallelJIT/CMakeLists.txt | 2 +- examples/ParallelJIT/Makefile | 2 +- examples/ParallelJIT/ParallelJIT.cpp | 6 +- include/llvm-c/BitReader.h | 4 +- include/llvm-c/BitWriter.h | 7 +- include/llvm-c/Core.h | 126 +- include/llvm-c/Disassembler.h | 20 +- include/llvm-c/ExecutionEngine.h | 5 +- include/llvm-c/Initialization.h | 4 +- include/llvm-c/Linker.h | 9 +- include/llvm-c/Support.h | 11 + include/llvm-c/Transforms/Scalar.h | 9 + include/llvm-c/lto.h | 50 +- include/llvm/ADT/APFloat.h | 103 +- include/llvm/ADT/APInt.h | 23 +- include/llvm/ADT/APSInt.h | 16 +- include/llvm/ADT/ArrayRef.h | 71 +- include/llvm/ADT/BitVector.h | 3 + include/llvm/ADT/DenseMap.h | 209 +- include/llvm/ADT/DenseSet.h | 54 +- include/llvm/ADT/DepthFirstIterator.h | 16 +- include/llvm/ADT/IntrusiveRefCntPtr.h | 3 + include/llvm/ADT/MapVector.h | 48 +- include/llvm/ADT/Optional.h | 68 + include/llvm/ADT/PostOrderIterator.h | 7 +- include/llvm/ADT/STLExtras.h | 33 +- include/llvm/ADT/ScopedHashTable.h | 4 +- include/llvm/ADT/SetVector.h | 4 +- include/llvm/ADT/SmallBitVector.h | 8 +- include/llvm/ADT/SmallPtrSet.h | 21 +- include/llvm/ADT/SmallSet.h | 16 +- include/llvm/ADT/SmallVector.h | 145 +- include/llvm/ADT/SparseBitVector.h | 2 +- include/llvm/ADT/SparseMultiSet.h | 2 +- include/llvm/ADT/SparseSet.h | 2 +- include/llvm/ADT/StringMap.h | 45 +- include/llvm/ADT/StringRef.h | 34 +- include/llvm/ADT/StringSet.h | 15 +- include/llvm/ADT/TinyPtrVector.h | 9 +- include/llvm/ADT/Triple.h | 52 +- include/llvm/ADT/Twine.h | 14 +- include/llvm/ADT/VariadicFunction.h | 8 +- include/llvm/ADT/ilist.h | 54 - include/llvm/ADT/ilist_node.h | 4 +- include/llvm/ADT/iterator.h | 2 +- include/llvm/ADT/iterator_range.h | 5 +- include/llvm/Analysis/AliasAnalysis.h | 55 +- include/llvm/Analysis/AliasSetTracker.h | 61 +- include/llvm/Analysis/AssumptionCache.h | 142 + include/llvm/Analysis/BlockFrequencyInfoImpl.h | 2 +- include/llvm/Analysis/BranchProbabilityInfo.h | 4 + include/llvm/Analysis/CFGPrinter.h | 14 +- include/llvm/Analysis/CGSCCPassManager.h | 196 +- include/llvm/Analysis/CallGraph.h | 39 +- include/llvm/Analysis/CodeMetrics.h | 16 +- include/llvm/Analysis/DOTGraphTraitsPass.h | 12 +- include/llvm/Analysis/DependenceAnalysis.h | 16 +- include/llvm/Analysis/DominanceFrontier.h | 2 + include/llvm/Analysis/DominanceFrontierImpl.h | 8 +- include/llvm/Analysis/FindUsedTypes.h | 66 - .../llvm/Analysis/FunctionTargetTransformInfo.h | 49 + include/llvm/Analysis/IVUsers.h | 2 +- include/llvm/Analysis/InlineCost.h | 2 + include/llvm/Analysis/InstructionSimplify.h | 134 +- include/llvm/Analysis/IntervalIterator.h | 4 +- include/llvm/Analysis/JumpInstrTableInfo.h | 15 +- include/llvm/Analysis/LazyCallGraph.h | 20 +- include/llvm/Analysis/LazyValueInfo.h | 37 +- include/llvm/Analysis/Loads.h | 6 +- include/llvm/Analysis/LoopPass.h | 9 + include/llvm/Analysis/MemoryDependenceAnalysis.h | 26 +- include/llvm/Analysis/PHITransAddr.h | 10 +- include/llvm/Analysis/Passes.h | 16 + include/llvm/Analysis/PostDominators.h | 2 +- include/llvm/Analysis/RegionInfo.h | 4 + include/llvm/Analysis/RegionInfoImpl.h | 8 +- include/llvm/Analysis/ScalarEvolution.h | 36 +- include/llvm/Analysis/ScalarEvolutionExpressions.h | 6 +- include/llvm/Analysis/TargetTransformInfo.h | 36 +- include/llvm/Analysis/ValueTracking.h | 53 +- include/llvm/AsmParser/Parser.h | 52 +- include/llvm/Bitcode/BitCodes.h | 12 +- include/llvm/Bitcode/BitcodeWriterPass.h | 6 +- include/llvm/Bitcode/BitstreamReader.h | 333 +- include/llvm/Bitcode/BitstreamWriter.h | 33 +- include/llvm/Bitcode/LLVMBitCodes.h | 15 +- include/llvm/Bitcode/ReaderWriter.h | 70 +- include/llvm/CMakeLists.txt | 13 - include/llvm/CodeGen/Analysis.h | 28 +- include/llvm/CodeGen/AsmPrinter.h | 29 +- include/llvm/CodeGen/CalcSpillWeights.h | 6 +- include/llvm/CodeGen/CallingConvLower.h | 54 +- include/llvm/CodeGen/CommandFlags.h | 65 +- include/llvm/CodeGen/DFAPacketizer.h | 5 +- include/llvm/CodeGen/DIE.h | 587 ++ include/llvm/CodeGen/FastISel.h | 543 +- include/llvm/CodeGen/ForwardControlFlowIntegrity.h | 122 + include/llvm/CodeGen/FunctionLoweringInfo.h | 19 +- include/llvm/CodeGen/GCMetadata.h | 36 +- include/llvm/CodeGen/GCMetadataPrinter.h | 26 +- include/llvm/CodeGen/GCStrategy.h | 173 +- include/llvm/CodeGen/GCs.h | 2 + include/llvm/CodeGen/ISDOpcodes.h | 13 +- include/llvm/CodeGen/JITCodeEmitter.h | 344 - include/llvm/CodeGen/JumpInstrTables.h | 31 +- include/llvm/CodeGen/LexicalScopes.h | 18 +- include/llvm/CodeGen/LinkAllCodegenComponents.h | 1 + include/llvm/CodeGen/LiveInterval.h | 180 +- include/llvm/CodeGen/LiveIntervalAnalysis.h | 53 +- include/llvm/CodeGen/LiveIntervalUnion.h | 10 +- include/llvm/CodeGen/LivePhysRegs.h | 6 +- include/llvm/CodeGen/LiveRangeEdit.h | 20 +- include/llvm/CodeGen/LiveVariables.h | 10 +- include/llvm/CodeGen/MachineBasicBlock.h | 6 + include/llvm/CodeGen/MachineCodeEmitter.h | 334 - include/llvm/CodeGen/MachineCodeInfo.h | 53 - include/llvm/CodeGen/MachineCombinerPattern.h | 29 + include/llvm/CodeGen/MachineDominators.h | 142 +- include/llvm/CodeGen/MachineFrameInfo.h | 58 +- include/llvm/CodeGen/MachineFunction.h | 28 +- include/llvm/CodeGen/MachineInstr.h | 71 +- include/llvm/CodeGen/MachineInstrBuilder.h | 49 +- include/llvm/CodeGen/MachineMemOperand.h | 10 +- include/llvm/CodeGen/MachineModuleInfo.h | 56 +- include/llvm/CodeGen/MachineOperand.h | 12 + include/llvm/CodeGen/MachinePostDominators.h | 2 +- include/llvm/CodeGen/MachineRegisterInfo.h | 31 +- include/llvm/CodeGen/MachineRelocation.h | 342 - include/llvm/CodeGen/MachineScheduler.h | 3 +- include/llvm/CodeGen/MachineTraceMetrics.h | 15 +- include/llvm/CodeGen/MachineValueType.h | 63 +- include/llvm/CodeGen/PBQP/CostAllocator.h | 151 +- include/llvm/CodeGen/PBQP/Graph.h | 185 +- include/llvm/CodeGen/PBQP/Math.h | 65 +- include/llvm/CodeGen/PBQP/ReductionRules.h | 10 +- include/llvm/CodeGen/PBQP/RegAllocSolver.h | 359 - include/llvm/CodeGen/PBQP/Solution.h | 4 +- include/llvm/CodeGen/PBQPRAConstraint.h | 69 + include/llvm/CodeGen/Passes.h | 82 +- include/llvm/CodeGen/RegAllocPBQP.h | 613 +- include/llvm/CodeGen/RegisterScavenging.h | 62 +- include/llvm/CodeGen/RuntimeLibcalls.h | 10 + include/llvm/CodeGen/ScheduleDAG.h | 6 + include/llvm/CodeGen/ScheduleDAGInstrs.h | 6 +- include/llvm/CodeGen/SelectionDAG.h | 82 +- include/llvm/CodeGen/SelectionDAGISel.h | 14 +- include/llvm/CodeGen/SelectionDAGNodes.h | 130 +- include/llvm/CodeGen/StackMapLivenessAnalysis.h | 6 +- include/llvm/CodeGen/StackMaps.h | 70 +- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 2 - include/llvm/CodeGen/TargetSchedule.h | 3 +- include/llvm/Config/config.h.cmake | 15 +- include/llvm/Config/config.h.in | 6 + include/llvm/Config/llvm-config.h.cmake | 3 + include/llvm/Config/llvm-config.h.in | 3 + include/llvm/DebugInfo/DIContext.h | 15 +- .../llvm/DebugInfo/DWARFAbbreviationDeclaration.h | 60 + include/llvm/DebugInfo/DWARFAcceleratorTable.h | 49 + include/llvm/DebugInfo/DWARFCompileUnit.h | 31 + include/llvm/DebugInfo/DWARFContext.h | 292 + include/llvm/DebugInfo/DWARFDebugAbbrev.h | 63 + include/llvm/DebugInfo/DWARFDebugArangeSet.h | 70 + include/llvm/DebugInfo/DWARFDebugAranges.h | 87 + include/llvm/DebugInfo/DWARFDebugFrame.h | 43 + include/llvm/DebugInfo/DWARFDebugInfoEntry.h | 160 + include/llvm/DebugInfo/DWARFDebugLine.h | 238 + include/llvm/DebugInfo/DWARFDebugLoc.h | 81 + include/llvm/DebugInfo/DWARFDebugRangeList.h | 77 + include/llvm/DebugInfo/DWARFFormValue.h | 8 + include/llvm/DebugInfo/DWARFRelocMap.h | 22 + include/llvm/DebugInfo/DWARFSection.h | 24 + include/llvm/DebugInfo/DWARFTypeUnit.h | 38 + include/llvm/DebugInfo/DWARFUnit.h | 245 + include/llvm/ExecutionEngine/ExecutionEngine.h | 202 +- include/llvm/ExecutionEngine/JIT.h | 38 - include/llvm/ExecutionEngine/JITEventListener.h | 36 +- include/llvm/ExecutionEngine/JITMemoryManager.h | 164 - include/llvm/ExecutionEngine/ObjectBuffer.h | 83 - include/llvm/ExecutionEngine/ObjectCache.h | 11 +- include/llvm/ExecutionEngine/ObjectImage.h | 71 - include/llvm/ExecutionEngine/RTDyldMemoryManager.h | 21 +- include/llvm/ExecutionEngine/RuntimeDyld.h | 51 +- include/llvm/ExecutionEngine/RuntimeDyldChecker.h | 53 +- include/llvm/IR/Argument.h | 8 + include/llvm/IR/AssemblyAnnotationWriter.h | 4 +- include/llvm/IR/BasicBlock.h | 16 + include/llvm/IR/CFG.h | 6 + include/llvm/IR/CallingConv.h | 11 +- include/llvm/IR/Constant.h | 8 + include/llvm/IR/ConstantRange.h | 99 +- include/llvm/IR/Constants.h | 158 +- include/llvm/IR/DIBuilder.h | 224 +- include/llvm/IR/DataLayout.h | 311 +- include/llvm/IR/DebugInfo.h | 776 +- include/llvm/IR/DebugLoc.h | 98 +- include/llvm/IR/DerivedTypes.h | 17 +- include/llvm/IR/DiagnosticInfo.h | 17 +- include/llvm/IR/DiagnosticPrinter.h | 4 +- include/llvm/IR/Dominators.h | 49 + include/llvm/IR/Function.h | 33 +- include/llvm/IR/GVMaterializer.h | 10 +- include/llvm/IR/GlobalObject.h | 16 +- include/llvm/IR/GlobalValue.h | 12 +- include/llvm/IR/IRBuilder.h | 139 +- include/llvm/IR/IRPrintingPasses.h | 8 +- include/llvm/IR/InlineAsm.h | 12 +- include/llvm/IR/InstrTypes.h | 88 +- include/llvm/IR/Instruction.h | 42 +- include/llvm/IR/Instructions.h | 24 +- include/llvm/IR/IntrinsicInst.h | 46 +- include/llvm/IR/Intrinsics.h | 44 +- include/llvm/IR/Intrinsics.td | 59 +- include/llvm/IR/IntrinsicsARM.td | 12 +- include/llvm/IR/IntrinsicsNVVM.td | 18 +- include/llvm/IR/IntrinsicsPowerPC.td | 70 +- include/llvm/IR/IntrinsicsR600.td | 17 +- include/llvm/IR/IntrinsicsX86.td | 780 +- include/llvm/IR/LLVMContext.h | 34 +- include/llvm/IR/LeakDetector.h | 92 - include/llvm/IR/LegacyPassManager.h | 12 +- include/llvm/IR/LegacyPassManagers.h | 10 +- include/llvm/IR/MDBuilder.h | 48 +- include/llvm/IR/Mangler.h | 6 +- include/llvm/IR/Metadata.def | 59 + include/llvm/IR/Metadata.h | 954 +- include/llvm/IR/MetadataTracking.h | 99 + include/llvm/IR/Module.h | 96 +- include/llvm/IR/Operator.h | 72 +- include/llvm/IR/PassManager.h | 821 +- include/llvm/IR/PassManagerInternal.h | 349 + include/llvm/IR/PatternMatch.h | 766 +- include/llvm/IR/PredIteratorCache.h | 6 +- include/llvm/IR/Statepoint.h | 215 + include/llvm/IR/TrackingMDRef.h | 170 + include/llvm/IR/Type.h | 9 +- include/llvm/IR/TypeFinder.h | 1 + include/llvm/IR/UseListOrder.h | 62 + include/llvm/IR/User.h | 45 +- include/llvm/IR/Value.h | 334 +- include/llvm/IR/ValueHandle.h | 165 +- include/llvm/IR/ValueMap.h | 45 +- include/llvm/IR/Verifier.h | 4 +- include/llvm/IRReader/IRReader.h | 17 +- include/llvm/InitializePasses.h | 15 +- include/llvm/LTO/LTOCodeGenerator.h | 24 +- include/llvm/LTO/LTOModule.h | 37 +- include/llvm/LinkAllPasses.h | 13 +- include/llvm/Linker/Linker.h | 84 +- include/llvm/MC/ConstantPools.h | 6 +- include/llvm/MC/MCAnalysis/MCAtom.h | 199 - include/llvm/MC/MCAnalysis/MCFunction.h | 142 - include/llvm/MC/MCAnalysis/MCModule.h | 134 - include/llvm/MC/MCAnalysis/MCModuleYAML.h | 40 - include/llvm/MC/MCAsmBackend.h | 18 +- include/llvm/MC/MCAsmInfo.h | 84 +- include/llvm/MC/MCAsmInfoDarwin.h | 2 +- include/llvm/MC/MCAsmInfoELF.h | 3 + include/llvm/MC/MCAssembler.h | 80 +- include/llvm/MC/MCContext.h | 15 + include/llvm/MC/MCDisassembler.h | 31 +- include/llvm/MC/MCDwarf.h | 14 +- include/llvm/MC/MCELFStreamer.h | 13 +- include/llvm/MC/MCExpr.h | 51 +- include/llvm/MC/MCInst.h | 9 +- include/llvm/MC/MCInstPrinter.h | 2 +- include/llvm/MC/MCInstrDesc.h | 69 +- include/llvm/MC/MCInstrItineraries.h | 59 +- include/llvm/MC/MCLinkerOptimizationHint.h | 4 +- include/llvm/MC/MCMachObjectWriter.h | 34 +- include/llvm/MC/MCObjectDisassembler.h | 174 - include/llvm/MC/MCObjectFileInfo.h | 9 +- include/llvm/MC/MCObjectStreamer.h | 13 +- include/llvm/MC/MCObjectSymbolizer.h | 83 - include/llvm/MC/MCObjectWriter.h | 6 +- include/llvm/MC/MCParser/AsmLexer.h | 2 +- include/llvm/MC/MCParser/MCAsmLexer.h | 43 +- include/llvm/MC/MCParser/MCAsmParser.h | 73 +- include/llvm/MC/MCParser/MCAsmParserExtension.h | 9 + include/llvm/MC/MCRegisterInfo.h | 85 +- include/llvm/MC/MCSchedule.h | 57 +- include/llvm/MC/MCStreamer.h | 51 +- include/llvm/MC/MCSubtargetInfo.h | 23 +- include/llvm/MC/MCSymbol.h | 18 +- include/llvm/MC/MCTargetAsmParser.h | 41 +- include/llvm/MC/MCTargetOptions.h | 14 +- include/llvm/MC/MCTargetOptionsCommandFlags.h | 8 +- include/llvm/MC/MCWin64EH.h | 40 +- include/llvm/MC/MCWinCOFFStreamer.h | 8 +- include/llvm/MC/MCWinEH.h | 55 + include/llvm/MC/StringTableBuilder.h | 16 +- include/llvm/MC/SubtargetFeature.h | 8 +- include/llvm/Object/Archive.h | 31 +- include/llvm/Object/Binary.h | 62 +- include/llvm/Object/COFF.h | 500 +- include/llvm/Object/COFFYAML.h | 32 + include/llvm/Object/ELF.h | 2 +- include/llvm/Object/ELFObjectFile.h | 299 +- include/llvm/Object/ELFTypes.h | 8 +- include/llvm/Object/ELFYAML.h | 10 +- include/llvm/Object/Error.h | 3 +- include/llvm/Object/IRObjectFile.h | 29 +- include/llvm/Object/MachO.h | 265 +- include/llvm/Object/MachOUniversal.h | 21 +- include/llvm/Object/ObjectFile.h | 195 +- include/llvm/Object/RelocVisitor.h | 319 +- include/llvm/Object/SymbolicFile.h | 22 +- include/llvm/Option/ArgList.h | 1 + include/llvm/PassRegistry.h | 48 +- include/llvm/PassSupport.h | 9 + include/llvm/ProfileData/CoverageMapping.h | 448 + include/llvm/ProfileData/CoverageMappingReader.h | 208 + include/llvm/ProfileData/CoverageMappingWriter.h | 63 + include/llvm/ProfileData/InstrProfReader.h | 62 +- include/llvm/ProfileData/InstrProfWriter.h | 16 +- include/llvm/ProfileData/SampleProf.h | 247 + include/llvm/ProfileData/SampleProfReader.h | 170 + include/llvm/ProfileData/SampleProfWriter.h | 110 + include/llvm/Support/ARMBuildAttributes.h | 17 +- include/llvm/Support/ARMEHABI.h | 6 +- include/llvm/Support/ARMWinEH.h | 16 +- include/llvm/Support/Allocator.h | 66 +- include/llvm/Support/CBindingWrapping.h | 4 +- include/llvm/Support/COFF.h | 67 +- include/llvm/Support/Casting.h | 34 + include/llvm/Support/CodeGen.h | 4 + include/llvm/Support/CommandLine.h | 843 +- include/llvm/Support/Compiler.h | 61 +- include/llvm/Support/Compression.h | 2 +- include/llvm/Support/CrashRecoveryContext.h | 11 +- include/llvm/Support/DataExtractor.h | 11 + include/llvm/Support/DataTypes.h.cmake | 13 +- include/llvm/Support/DataTypes.h.in | 6 - include/llvm/Support/Dwarf.h | 171 +- include/llvm/Support/DynamicLibrary.h | 11 +- include/llvm/Support/ELF.h | 767 +- include/llvm/Support/ELFRelocs/AArch64.def | 147 + include/llvm/Support/ELFRelocs/ARM.def | 138 + include/llvm/Support/ELFRelocs/Hexagon.def | 92 + include/llvm/Support/ELFRelocs/Mips.def | 112 + include/llvm/Support/ELFRelocs/PowerPC.def | 61 + include/llvm/Support/ELFRelocs/PowerPC64.def | 88 + include/llvm/Support/ELFRelocs/Sparc.def | 89 + include/llvm/Support/ELFRelocs/SystemZ.def | 67 + include/llvm/Support/ELFRelocs/i386.def | 47 + include/llvm/Support/ELFRelocs/x86_64.def | 44 + include/llvm/Support/Endian.h | 43 +- include/llvm/Support/EndianStream.h | 10 +- include/llvm/Support/ErrorOr.h | 52 +- include/llvm/Support/FileOutputBuffer.h | 4 +- include/llvm/Support/FileSystem.h | 81 +- include/llvm/Support/Format.h | 76 +- include/llvm/Support/GCOV.h | 10 +- include/llvm/Support/GenericDomTree.h | 298 +- include/llvm/Support/GenericDomTreeConstruction.h | 6 +- include/llvm/Support/IncludeFile.h | 79 - include/llvm/Support/LEB128.h | 22 +- include/llvm/Support/LineIterator.h | 17 +- include/llvm/Support/MD5.h | 8 +- include/llvm/Support/MachO.h | 374 +- include/llvm/Support/ManagedStatic.h | 4 +- include/llvm/Support/MathExtras.h | 45 +- include/llvm/Support/MemoryBuffer.h | 105 +- include/llvm/Support/MemoryObject.h | 70 +- include/llvm/Support/Mutex.h | 21 +- include/llvm/Support/MutexGuard.h | 4 +- include/llvm/Support/OnDiskHashTable.h | 8 +- include/llvm/Support/Options.h | 120 + include/llvm/Support/Path.h | 68 +- include/llvm/Support/Process.h | 117 +- include/llvm/Support/Program.h | 56 +- include/llvm/Support/RWMutex.h | 33 +- include/llvm/Support/RandomNumberGenerator.h | 35 +- include/llvm/Support/Registry.h | 1 - include/llvm/Support/ScaledNumber.h | 1 - include/llvm/Support/SourceMgr.h | 18 +- include/llvm/Support/SpecialCaseList.h | 16 +- include/llvm/Support/StreamableMemoryObject.h | 178 - include/llvm/Support/StreamingMemoryObject.h | 92 + include/llvm/Support/StringPool.h | 2 +- include/llvm/Support/StringRefMemoryObject.h | 41 - include/llvm/Support/SwapByteOrder.h | 7 +- include/llvm/Support/TargetRegistry.h | 22 +- include/llvm/Support/ThreadLocal.h | 2 +- include/llvm/Support/Threading.h | 3 +- include/llvm/Support/TimeValue.h | 20 +- include/llvm/Support/ToolOutputFile.h | 14 +- include/llvm/Support/UniqueLock.h | 67 + include/llvm/Support/Win64EH.h | 12 +- include/llvm/Support/WindowsError.h | 4 +- include/llvm/Support/YAMLParser.h | 5 +- include/llvm/Support/YAMLTraits.h | 12 +- include/llvm/Support/raw_ostream.h | 19 +- include/llvm/TableGen/Record.h | 95 +- include/llvm/TableGen/SetTheory.h | 4 +- include/llvm/TableGen/StringToOffsetTable.h | 12 +- include/llvm/Target/Target.td | 72 +- include/llvm/Target/TargetFrameLowering.h | 14 + include/llvm/Target/TargetInstrInfo.h | 230 +- include/llvm/Target/TargetIntrinsicInfo.h | 2 +- include/llvm/Target/TargetJITInfo.h | 137 - include/llvm/Target/TargetLibraryInfo.h | 27 +- include/llvm/Target/TargetLowering.h | 377 +- include/llvm/Target/TargetLoweringObjectFile.h | 8 +- include/llvm/Target/TargetMachine.h | 95 +- include/llvm/Target/TargetOpcodes.h | 19 +- include/llvm/Target/TargetOptions.h | 49 +- include/llvm/Target/TargetRegisterInfo.h | 55 +- include/llvm/Target/TargetSelectionDAG.td | 20 + include/llvm/Target/TargetSelectionDAGInfo.h | 2 +- include/llvm/Target/TargetSubtargetInfo.h | 61 +- include/llvm/Transforms/IPO/PassManagerBuilder.h | 16 +- include/llvm/Transforms/Instrumentation.h | 46 +- include/llvm/Transforms/Scalar.h | 18 +- include/llvm/Transforms/Utils/BasicBlockUtils.h | 5 + include/llvm/Transforms/Utils/BuildLibCalls.h | 14 - include/llvm/Transforms/Utils/Cloning.h | 11 +- include/llvm/Transforms/Utils/CodeExtractor.h | 4 +- include/llvm/Transforms/Utils/CtorUtils.h | 4 +- include/llvm/Transforms/Utils/Local.h | 25 +- include/llvm/Transforms/Utils/LoopUtils.h | 9 +- include/llvm/Transforms/Utils/ModuleUtils.h | 4 +- include/llvm/Transforms/Utils/PromoteMemToReg.h | 4 +- include/llvm/Transforms/Utils/SimplifyLibCalls.h | 175 +- include/llvm/Transforms/Utils/SymbolRewriter.h | 155 + .../llvm/Transforms/Utils/UnifyFunctionExitNodes.h | 4 +- include/llvm/Transforms/Utils/UnrollLoop.h | 3 +- include/llvm/Transforms/Utils/ValueMapper.h | 21 +- include/llvm/Transforms/Utils/VectorUtils.h | 14 +- include/llvm/module.modulemap | 27 +- lib/Analysis/AliasAnalysis.cpp | 85 +- lib/Analysis/AliasAnalysisEvaluator.cpp | 8 +- lib/Analysis/AliasSetTracker.cpp | 105 +- lib/Analysis/Analysis.cpp | 2 + lib/Analysis/AssumptionCache.cpp | 125 + lib/Analysis/BasicAliasAnalysis.cpp | 269 +- lib/Analysis/BlockFrequencyInfoImpl.cpp | 3 +- lib/Analysis/BranchProbabilityInfo.cpp | 3 +- lib/Analysis/CFG.cpp | 6 +- lib/Analysis/CFGPrinter.cpp | 16 +- lib/Analysis/CFLAliasAnalysis.cpp | 1013 +++ lib/Analysis/CGSCCPassManager.cpp | 103 +- lib/Analysis/CMakeLists.txt | 4 + lib/Analysis/CaptureTracking.cpp | 4 +- lib/Analysis/CodeMetrics.cpp | 92 +- lib/Analysis/ConstantFolding.cpp | 121 +- lib/Analysis/DependenceAnalysis.cpp | 73 +- lib/Analysis/FunctionTargetTransformInfo.cpp | 50 + lib/Analysis/IPA/CMakeLists.txt | 1 - lib/Analysis/IPA/CallGraph.cpp | 3 - lib/Analysis/IPA/CallGraphSCCPass.cpp | 11 +- lib/Analysis/IPA/FindUsedTypes.cpp | 100 - lib/Analysis/IPA/IPA.cpp | 1 - lib/Analysis/IPA/InlineCost.cpp | 36 +- lib/Analysis/IVUsers.cpp | 8 +- lib/Analysis/InstructionSimplify.cpp | 877 +- lib/Analysis/JumpInstrTableInfo.cpp | 17 +- lib/Analysis/LazyCallGraph.cpp | 15 +- lib/Analysis/LazyValueInfo.cpp | 553 +- lib/Analysis/LibCallSemantics.cpp | 4 +- lib/Analysis/Lint.cpp | 30 +- lib/Analysis/Loads.cpp | 192 +- lib/Analysis/LoopInfo.cpp | 4 +- lib/Analysis/LoopPass.cpp | 11 + lib/Analysis/MemDepPrinter.cpp | 28 +- lib/Analysis/MemoryBuiltins.cpp | 10 +- lib/Analysis/MemoryDependenceAnalysis.cpp | 251 +- lib/Analysis/NoAliasAnalysis.cpp | 5 +- lib/Analysis/PHITransAddr.cpp | 6 +- lib/Analysis/PtrUseVisitor.cpp | 2 +- lib/Analysis/RegionInfo.cpp | 2 +- lib/Analysis/RegionPass.cpp | 3 +- lib/Analysis/ScalarEvolution.cpp | 1212 ++- lib/Analysis/ScalarEvolutionAliasAnalysis.cpp | 4 +- lib/Analysis/ScalarEvolutionExpander.cpp | 4 +- lib/Analysis/ScalarEvolutionNormalization.cpp | 2 +- lib/Analysis/ScopedNoAliasAA.cpp | 245 + lib/Analysis/StratifiedSets.h | 692 ++ lib/Analysis/TargetTransformInfo.cpp | 67 +- lib/Analysis/TypeBasedAliasAnalysis.cpp | 58 +- lib/Analysis/ValueTracking.cpp | 1159 ++- lib/AsmParser/LLLexer.cpp | 134 +- lib/AsmParser/LLLexer.h | 11 +- lib/AsmParser/LLParser.cpp | 864 +- lib/AsmParser/LLParser.h | 104 +- lib/AsmParser/LLToken.h | 16 +- lib/AsmParser/Parser.cpp | 44 +- lib/Bitcode/Reader/BitReader.cpp | 7 +- lib/Bitcode/Reader/BitcodeReader.cpp | 1139 ++- lib/Bitcode/Reader/BitcodeReader.h | 104 +- lib/Bitcode/Reader/BitstreamReader.cpp | 89 +- lib/Bitcode/Writer/BitWriter.cpp | 14 +- lib/Bitcode/Writer/BitcodeWriter.cpp | 379 +- lib/Bitcode/Writer/BitcodeWriterPass.cpp | 4 +- lib/Bitcode/Writer/ValueEnumerator.cpp | 524 +- lib/Bitcode/Writer/ValueEnumerator.h | 39 +- lib/CodeGen/AggressiveAntiDepBreaker.cpp | 45 +- lib/CodeGen/AggressiveAntiDepBreaker.h | 65 +- lib/CodeGen/AllocationOrder.h | 4 +- lib/CodeGen/Analysis.cpp | 68 +- lib/CodeGen/AntiDepBreaker.h | 24 +- lib/CodeGen/AsmPrinter/ARMException.cpp | 6 +- lib/CodeGen/AsmPrinter/AddressPool.h | 4 +- lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 437 +- lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 185 +- lib/CodeGen/AsmPrinter/AsmPrinterHandler.h | 4 +- lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp | 20 +- lib/CodeGen/AsmPrinter/ByteStreamer.h | 6 +- lib/CodeGen/AsmPrinter/CMakeLists.txt | 2 + lib/CodeGen/AsmPrinter/DIE.cpp | 33 +- lib/CodeGen/AsmPrinter/DIE.h | 587 -- lib/CodeGen/AsmPrinter/DIEHash.cpp | 4 +- lib/CodeGen/AsmPrinter/DIEHash.h | 6 +- .../AsmPrinter/DbgValueHistoryCalculator.cpp | 97 +- lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h | 6 +- lib/CodeGen/AsmPrinter/DebugLocEntry.h | 146 +- lib/CodeGen/AsmPrinter/DebugLocList.h | 10 +- lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp | 18 +- lib/CodeGen/AsmPrinter/DwarfAccelTable.h | 14 +- lib/CodeGen/AsmPrinter/DwarfCFIException.cpp | 2 +- lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp | 836 ++ lib/CodeGen/AsmPrinter/DwarfCompileUnit.h | 250 + lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 1181 +-- lib/CodeGen/AsmPrinter/DwarfDebug.h | 215 +- lib/CodeGen/AsmPrinter/DwarfException.h | 37 +- lib/CodeGen/AsmPrinter/DwarfExpression.cpp | 260 + lib/CodeGen/AsmPrinter/DwarfExpression.h | 133 + lib/CodeGen/AsmPrinter/DwarfFile.cpp | 65 +- lib/CodeGen/AsmPrinter/DwarfFile.h | 54 +- lib/CodeGen/AsmPrinter/DwarfStringPool.cpp | 8 +- lib/CodeGen/AsmPrinter/DwarfStringPool.h | 14 +- lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 730 +- lib/CodeGen/AsmPrinter/DwarfUnit.h | 243 +- lib/CodeGen/AsmPrinter/EHStreamer.cpp | 67 +- lib/CodeGen/AsmPrinter/EHStreamer.h | 22 +- lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp | 21 +- lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp | 38 +- lib/CodeGen/AsmPrinter/Win64Exception.cpp | 151 +- lib/CodeGen/AsmPrinter/Win64Exception.h | 56 + lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp | 167 +- lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h | 4 +- lib/CodeGen/AtomicExpandLoadLinkedPass.cpp | 380 - lib/CodeGen/AtomicExpandPass.cpp | 563 ++ lib/CodeGen/BasicTargetTransformInfo.cpp | 41 +- lib/CodeGen/BranchFolding.cpp | 92 +- lib/CodeGen/BranchFolding.h | 28 +- lib/CodeGen/CMakeLists.txt | 8 +- lib/CodeGen/CalcSpillWeights.cpp | 12 +- lib/CodeGen/CallingConvLower.cpp | 83 +- lib/CodeGen/CodeGen.cpp | 3 +- lib/CodeGen/CodeGenPrepare.cpp | 1822 +++- lib/CodeGen/CriticalAntiDepBreaker.cpp | 70 +- lib/CodeGen/CriticalAntiDepBreaker.h | 27 +- lib/CodeGen/DFAPacketizer.cpp | 21 +- lib/CodeGen/DeadMachineInstructionElim.cpp | 26 +- lib/CodeGen/DwarfEHPrepare.cpp | 8 +- lib/CodeGen/EarlyIfConversion.cpp | 14 +- lib/CodeGen/ErlangGC.cpp | 3 +- lib/CodeGen/ExecutionDepsFix.cpp | 166 +- lib/CodeGen/ExpandISelPseudos.cpp | 4 +- lib/CodeGen/ExpandPostRAPseudos.cpp | 7 +- lib/CodeGen/ForwardControlFlowIntegrity.cpp | 374 + lib/CodeGen/GCMetadata.cpp | 7 +- lib/CodeGen/GCMetadataPrinter.cpp | 8 - lib/CodeGen/GCStrategy.cpp | 25 +- lib/CodeGen/GlobalMerge.cpp | 7 +- lib/CodeGen/IfConversion.cpp | 30 +- lib/CodeGen/InlineSpiller.cpp | 80 +- lib/CodeGen/InterferenceCache.h | 4 +- lib/CodeGen/IntrinsicLowering.cpp | 33 +- lib/CodeGen/JITCodeEmitter.cpp | 14 - lib/CodeGen/JumpInstrTables.cpp | 19 +- lib/CodeGen/LLVMTargetMachine.cpp | 66 +- lib/CodeGen/LexicalScopes.cpp | 11 +- lib/CodeGen/LiveDebugVariables.cpp | 88 +- lib/CodeGen/LiveDebugVariables.h | 9 +- lib/CodeGen/LiveInterval.cpp | 322 +- lib/CodeGen/LiveIntervalAnalysis.cpp | 603 +- lib/CodeGen/LiveIntervalUnion.cpp | 18 +- lib/CodeGen/LiveRangeCalc.cpp | 225 +- lib/CodeGen/LiveRangeCalc.h | 57 +- lib/CodeGen/LiveRangeEdit.cpp | 23 +- lib/CodeGen/LiveRegMatrix.cpp | 65 +- lib/CodeGen/LiveStackAnalysis.cpp | 5 +- lib/CodeGen/LiveVariables.cpp | 262 +- lib/CodeGen/LocalStackSlotAllocation.cpp | 10 +- lib/CodeGen/MachineBasicBlock.cpp | 57 +- lib/CodeGen/MachineBlockPlacement.cpp | 16 +- lib/CodeGen/MachineCSE.cpp | 68 +- lib/CodeGen/MachineCodeEmitter.cpp | 14 - lib/CodeGen/MachineCombiner.cpp | 435 + lib/CodeGen/MachineCopyPropagation.cpp | 5 +- lib/CodeGen/MachineDominanceFrontier.cpp | 2 +- lib/CodeGen/MachineDominators.cpp | 2 + lib/CodeGen/MachineFunction.cpp | 109 +- lib/CodeGen/MachineFunctionAnalysis.cpp | 3 +- lib/CodeGen/MachineFunctionPrinterPass.cpp | 2 +- lib/CodeGen/MachineInstr.cpp | 142 +- lib/CodeGen/MachineInstrBundle.cpp | 19 +- lib/CodeGen/MachineLICM.cpp | 44 +- lib/CodeGen/MachineModuleInfo.cpp | 18 +- lib/CodeGen/MachineRegionInfo.cpp | 4 +- lib/CodeGen/MachineRegisterInfo.cpp | 37 +- lib/CodeGen/MachineSSAUpdater.cpp | 4 +- lib/CodeGen/MachineScheduler.cpp | 51 +- lib/CodeGen/MachineSink.cpp | 211 +- lib/CodeGen/MachineTraceMetrics.cpp | 76 +- lib/CodeGen/MachineVerifier.cpp | 181 +- lib/CodeGen/OptimizePHIs.cpp | 7 +- lib/CodeGen/PHIElimination.cpp | 10 +- lib/CodeGen/PHIEliminationUtils.h | 4 +- lib/CodeGen/Passes.cpp | 161 +- lib/CodeGen/PeepholeOptimizer.cpp | 812 +- lib/CodeGen/PostRASchedulerList.cpp | 43 +- lib/CodeGen/ProcessImplicitDefs.cpp | 5 +- lib/CodeGen/PrologEpilogInserter.cpp | 100 +- lib/CodeGen/PrologEpilogInserter.h | 4 +- lib/CodeGen/PseudoSourceValue.cpp | 8 +- lib/CodeGen/RegAllocBase.cpp | 5 +- lib/CodeGen/RegAllocBase.h | 9 +- lib/CodeGen/RegAllocBasic.cpp | 1 - lib/CodeGen/RegAllocFast.cpp | 57 +- lib/CodeGen/RegAllocGreedy.cpp | 237 +- lib/CodeGen/RegAllocPBQP.cpp | 777 +- lib/CodeGen/RegisterClassInfo.cpp | 9 +- lib/CodeGen/RegisterCoalescer.cpp | 965 +- lib/CodeGen/RegisterCoalescer.h | 50 +- lib/CodeGen/RegisterPressure.cpp | 3 +- lib/CodeGen/RegisterScavenging.cpp | 131 +- lib/CodeGen/ScheduleDAG.cpp | 9 +- lib/CodeGen/ScheduleDAGInstrs.cpp | 58 +- lib/CodeGen/ScheduleDAGPrinter.cpp | 1 - lib/CodeGen/ScoreboardHazardRecognizer.cpp | 2 +- lib/CodeGen/SelectionDAG/CMakeLists.txt | 1 + lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2827 ++++-- lib/CodeGen/SelectionDAG/FastISel.cpp | 1011 ++- lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 118 +- lib/CodeGen/SelectionDAG/InstrEmitter.cpp | 48 +- lib/CodeGen/SelectionDAG/InstrEmitter.h | 5 +- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 491 +- lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp | 61 +- lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 146 +- lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 11 + lib/CodeGen/SelectionDAG/LegalizeTypes.h | 18 +- lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp | 12 +- lib/CodeGen/SelectionDAG/LegalizeVectorOps.cpp | 67 +- lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 257 +- lib/CodeGen/SelectionDAG/ResourcePriorityQueue.cpp | 50 +- lib/CodeGen/SelectionDAG/SDNodeDbgValue.h | 58 +- lib/CodeGen/SelectionDAG/ScheduleDAGFast.cpp | 32 +- lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp | 78 +- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp | 46 +- lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.h | 4 +- lib/CodeGen/SelectionDAG/ScheduleDAGVLIW.cpp | 7 +- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 524 +- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 1286 +-- lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 72 +- lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp | 12 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 246 +- lib/CodeGen/SelectionDAG/StatepointLowering.cpp | 684 ++ lib/CodeGen/SelectionDAG/StatepointLowering.h | 138 + lib/CodeGen/SelectionDAG/TargetLowering.cpp | 105 +- lib/CodeGen/ShadowStackGC.cpp | 2 +- lib/CodeGen/SjLjEHPrepare.cpp | 15 +- lib/CodeGen/SpillPlacement.cpp | 54 +- lib/CodeGen/SpillPlacement.h | 13 +- lib/CodeGen/Spiller.cpp | 184 - lib/CodeGen/Spiller.h | 9 +- lib/CodeGen/SplitKit.cpp | 76 +- lib/CodeGen/SplitKit.h | 4 +- lib/CodeGen/StackColoring.cpp | 5 +- lib/CodeGen/StackMapLivenessAnalysis.cpp | 6 +- lib/CodeGen/StackMaps.cpp | 46 +- lib/CodeGen/StackProtector.cpp | 57 +- lib/CodeGen/StackSlotColoring.cpp | 4 +- lib/CodeGen/StatepointExampleGC.cpp | 54 + lib/CodeGen/TailDuplication.cpp | 9 +- lib/CodeGen/TargetFrameLoweringImpl.cpp | 6 +- lib/CodeGen/TargetInstrInfo.cpp | 125 +- lib/CodeGen/TargetLoweringBase.cpp | 97 +- lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 179 +- lib/CodeGen/TargetOptionsImpl.cpp | 7 + lib/CodeGen/TargetRegisterInfo.cpp | 11 +- lib/CodeGen/TargetSchedule.cpp | 33 +- lib/CodeGen/TwoAddressInstructionPass.cpp | 28 +- lib/CodeGen/UnreachableBlockElim.cpp | 11 +- lib/CodeGen/VirtRegMap.cpp | 65 +- lib/DebugInfo/CMakeLists.txt | 2 + lib/DebugInfo/DIContext.cpp | 4 +- lib/DebugInfo/DWARFAbbreviationDeclaration.cpp | 2 +- lib/DebugInfo/DWARFAbbreviationDeclaration.h | 60 - lib/DebugInfo/DWARFAcceleratorTable.cpp | 132 + lib/DebugInfo/DWARFCompileUnit.cpp | 2 +- lib/DebugInfo/DWARFCompileUnit.h | 30 - lib/DebugInfo/DWARFContext.cpp | 249 +- lib/DebugInfo/DWARFContext.h | 285 - lib/DebugInfo/DWARFDebugAbbrev.cpp | 6 +- lib/DebugInfo/DWARFDebugAbbrev.h | 63 - lib/DebugInfo/DWARFDebugArangeSet.cpp | 2 +- lib/DebugInfo/DWARFDebugArangeSet.h | 70 - lib/DebugInfo/DWARFDebugAranges.cpp | 8 +- lib/DebugInfo/DWARFDebugAranges.h | 87 - lib/DebugInfo/DWARFDebugFrame.cpp | 5 +- lib/DebugInfo/DWARFDebugFrame.h | 43 - lib/DebugInfo/DWARFDebugInfoEntry.cpp | 147 +- lib/DebugInfo/DWARFDebugInfoEntry.h | 157 - lib/DebugInfo/DWARFDebugLine.cpp | 40 +- lib/DebugInfo/DWARFDebugLine.h | 232 - lib/DebugInfo/DWARFDebugLoc.cpp | 4 +- lib/DebugInfo/DWARFDebugLoc.h | 81 - lib/DebugInfo/DWARFDebugRangeList.cpp | 2 +- lib/DebugInfo/DWARFDebugRangeList.h | 77 - lib/DebugInfo/DWARFFormValue.cpp | 74 +- lib/DebugInfo/DWARFRelocMap.h | 22 - lib/DebugInfo/DWARFTypeUnit.cpp | 2 +- lib/DebugInfo/DWARFTypeUnit.h | 37 - lib/DebugInfo/DWARFUnit.cpp | 49 +- lib/DebugInfo/DWARFUnit.h | 163 - lib/DebugInfo/SyntaxHighlighting.cpp | 37 + lib/DebugInfo/SyntaxHighlighting.h | 39 + lib/ExecutionEngine/CMakeLists.txt | 2 +- lib/ExecutionEngine/EventListenerCommon.h | 135 +- lib/ExecutionEngine/ExecutionEngine.cpp | 184 +- lib/ExecutionEngine/ExecutionEngineBindings.cpp | 33 +- lib/ExecutionEngine/GDBRegistrationListener.cpp | 247 + .../IntelJITEvents/IntelJITEventListener.cpp | 155 +- lib/ExecutionEngine/IntelJITEvents/LLVMBuild.txt | 1 + lib/ExecutionEngine/Interpreter/CMakeLists.txt | 2 +- .../Interpreter/ExternalFunctions.cpp | 35 +- lib/ExecutionEngine/Interpreter/Interpreter.cpp | 13 +- lib/ExecutionEngine/Interpreter/Interpreter.h | 84 +- lib/ExecutionEngine/JIT/CMakeLists.txt | 8 - lib/ExecutionEngine/JIT/JIT.cpp | 695 -- lib/ExecutionEngine/JIT/JIT.h | 229 - lib/ExecutionEngine/JIT/JITEmitter.cpp | 1249 --- lib/ExecutionEngine/JIT/JITMemoryManager.cpp | 904 -- lib/ExecutionEngine/JIT/LLVMBuild.txt | 22 - lib/ExecutionEngine/JIT/Makefile | 38 - lib/ExecutionEngine/LLVMBuild.txt | 4 +- lib/ExecutionEngine/MCJIT/MCJIT.cpp | 232 +- lib/ExecutionEngine/MCJIT/MCJIT.h | 63 +- lib/ExecutionEngine/MCJIT/ObjectBuffer.h | 48 + lib/ExecutionEngine/Makefile | 2 +- .../OProfileJIT/OProfileJITEventListener.cpp | 191 +- lib/ExecutionEngine/RTDyldMemoryManager.cpp | 37 +- lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt | 1 - lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp | 213 - lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h | 44 - .../RuntimeDyld/ObjectImageCommon.h | 89 - lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp | 380 +- .../RuntimeDyld/RuntimeDyldChecker.cpp | 1365 +-- .../RuntimeDyld/RuntimeDyldCheckerImpl.h | 76 + lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 409 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 35 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h | 71 +- .../RuntimeDyld/RuntimeDyldMachO.cpp | 235 +- lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h | 127 +- .../RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h | 351 +- .../RuntimeDyld/Targets/RuntimeDyldMachOARM.h | 179 +- .../RuntimeDyld/Targets/RuntimeDyldMachOI386.h | 172 +- .../RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h | 35 +- lib/ExecutionEngine/TargetSelect.cpp | 5 +- lib/IR/AsmWriter.cpp | 543 +- lib/IR/AsmWriter.h | 11 +- lib/IR/AttributeImpl.h | 4 +- lib/IR/AutoUpgrade.cpp | 229 +- lib/IR/BasicBlock.cpp | 60 +- lib/IR/CMakeLists.txt | 4 +- lib/IR/ConstantFold.cpp | 125 +- lib/IR/ConstantFold.h | 4 +- lib/IR/Constants.cpp | 529 +- lib/IR/ConstantsContext.h | 628 +- lib/IR/Core.cpp | 240 +- lib/IR/DIBuilder.cpp | 1428 ++- lib/IR/DataLayout.cpp | 77 +- lib/IR/DebugInfo.cpp | 678 +- lib/IR/DebugLoc.cpp | 303 +- lib/IR/DiagnosticInfo.cpp | 3 +- lib/IR/DiagnosticPrinter.cpp | 2 +- lib/IR/Dominators.cpp | 38 +- lib/IR/Function.cpp | 196 +- lib/IR/GCOV.cpp | 13 +- lib/IR/Globals.cpp | 41 +- lib/IR/IRBuilder.cpp | 161 +- lib/IR/IRPrintingPasses.cpp | 12 +- lib/IR/InlineAsm.cpp | 4 + lib/IR/Instruction.cpp | 37 +- lib/IR/Instructions.cpp | 76 +- lib/IR/IntrinsicInst.cpp | 22 +- lib/IR/LLVMContext.cpp | 87 +- lib/IR/LLVMContextImpl.cpp | 57 +- lib/IR/LLVMContextImpl.h | 271 +- lib/IR/LeakDetector.cpp | 69 - lib/IR/LeaksContext.h | 11 +- lib/IR/LegacyPassManager.cpp | 33 +- lib/IR/MDBuilder.cpp | 55 +- lib/IR/Mangler.cpp | 96 +- lib/IR/Metadata.cpp | 1134 ++- lib/IR/MetadataTracking.cpp | 58 + lib/IR/Module.cpp | 128 +- lib/IR/PassManager.cpp | 165 +- lib/IR/PassRegistry.cpp | 56 +- lib/IR/Statepoint.cpp | 61 + lib/IR/SymbolTableListTraitsImpl.h | 4 +- lib/IR/Type.cpp | 59 +- lib/IR/TypeFinder.cpp | 32 +- lib/IR/Use.cpp | 2 +- lib/IR/UseListOrder.cpp | 43 + lib/IR/User.cpp | 3 - lib/IR/Value.cpp | 180 +- lib/IR/ValueSymbolTable.cpp | 33 +- lib/IR/Verifier.cpp | 589 +- lib/IRReader/IRReader.cpp | 56 +- lib/LTO/LLVMBuild.txt | 2 +- lib/LTO/LTOCodeGenerator.cpp | 112 +- lib/LTO/LTOModule.cpp | 275 +- lib/Linker/LinkModules.cpp | 1800 ++-- lib/MC/CMakeLists.txt | 5 +- lib/MC/ConstantPools.cpp | 2 +- lib/MC/ELFObjectWriter.cpp | 108 +- lib/MC/LLVMBuild.txt | 2 +- lib/MC/MCAnalysis/CMakeLists.txt | 8 - lib/MC/MCAnalysis/LLVMBuild.txt | 5 - lib/MC/MCAnalysis/MCAtom.cpp | 114 - lib/MC/MCAnalysis/MCFunction.cpp | 76 - lib/MC/MCAnalysis/MCModule.cpp | 142 - lib/MC/MCAnalysis/MCModuleYAML.cpp | 464 - lib/MC/MCAnalysis/MCObjectDisassembler.cpp | 574 -- lib/MC/MCAnalysis/MCObjectSymbolizer.cpp | 268 - lib/MC/MCAnalysis/Makefile | 14 - lib/MC/MCAsmInfo.cpp | 12 +- lib/MC/MCAsmInfoCOFF.cpp | 1 - lib/MC/MCAsmInfoDarwin.cpp | 38 +- lib/MC/MCAsmInfoELF.cpp | 10 + lib/MC/MCAsmStreamer.cpp | 45 +- lib/MC/MCAssembler.cpp | 99 +- lib/MC/MCContext.cpp | 65 +- lib/MC/MCDisassembler.cpp | 39 - lib/MC/MCDisassembler/CMakeLists.txt | 3 + lib/MC/MCDisassembler/Disassembler.cpp | 73 +- lib/MC/MCDisassembler/Disassembler.h | 4 +- lib/MC/MCDisassembler/MCDisassembler.cpp | 39 + lib/MC/MCDisassembler/MCExternalSymbolizer.cpp | 198 + lib/MC/MCDisassembler/MCRelocationInfo.cpp | 39 + lib/MC/MCDwarf.cpp | 231 +- lib/MC/MCELFStreamer.cpp | 57 +- lib/MC/MCExpr.cpp | 175 +- lib/MC/MCExternalSymbolizer.cpp | 198 - lib/MC/MCLinkerOptimizationHint.cpp | 2 +- lib/MC/MCMachOStreamer.cpp | 10 +- lib/MC/MCNullStreamer.cpp | 1 - lib/MC/MCObjectFileInfo.cpp | 65 +- lib/MC/MCObjectStreamer.cpp | 75 +- lib/MC/MCParser/AsmLexer.cpp | 18 +- lib/MC/MCParser/AsmParser.cpp | 221 +- lib/MC/MCParser/COFFAsmParser.cpp | 12 +- lib/MC/MCParser/DarwinAsmParser.cpp | 8 +- lib/MC/MCParser/ELFAsmParser.cpp | 2 +- lib/MC/MCParser/MCAsmLexer.cpp | 4 + lib/MC/MCParser/MCAsmParser.cpp | 2 +- lib/MC/MCRelocationInfo.cpp | 39 - lib/MC/MCSectionCOFF.cpp | 18 +- lib/MC/MCSectionELF.cpp | 4 +- lib/MC/MCStreamer.cpp | 114 +- lib/MC/MCSubtargetInfo.cpp | 12 +- lib/MC/MCTargetOptions.cpp | 11 +- lib/MC/MCWin64EH.cpp | 88 +- lib/MC/MCWinEH.cpp | 77 + lib/MC/MachObjectWriter.cpp | 125 +- lib/MC/Makefile | 2 +- lib/MC/StringTableBuilder.cpp | 45 +- lib/MC/SubtargetFeature.cpp | 18 +- lib/MC/WinCOFFObjectWriter.cpp | 347 +- lib/MC/WinCOFFStreamer.cpp | 35 +- lib/Object/Archive.cpp | 54 +- lib/Object/Binary.cpp | 37 +- lib/Object/COFFObjectFile.cpp | 994 +- lib/Object/COFFYAML.cpp | 106 + lib/Object/ELF.cpp | 745 +- lib/Object/ELFObjectFile.cpp | 37 +- lib/Object/ELFYAML.cpp | 297 +- lib/Object/Error.cpp | 10 +- lib/Object/IRObjectFile.cpp | 91 +- lib/Object/MachOObjectFile.cpp | 1218 ++- lib/Object/MachOUniversal.cpp | 51 +- lib/Object/Object.cpp | 60 +- lib/Object/ObjectFile.cpp | 30 +- lib/Object/RecordStreamer.h | 4 +- lib/Object/SymbolicFile.cpp | 37 +- lib/Option/ArgList.cpp | 11 +- lib/Option/OptTable.cpp | 18 +- lib/Option/Option.cpp | 12 +- lib/ProfileData/CMakeLists.txt | 6 + lib/ProfileData/CoverageMapping.cpp | 474 + lib/ProfileData/CoverageMappingReader.cpp | 553 ++ lib/ProfileData/CoverageMappingWriter.cpp | 187 + lib/ProfileData/InstrProf.cpp | 6 +- lib/ProfileData/InstrProfIndexed.h | 9 +- lib/ProfileData/InstrProfReader.cpp | 104 +- lib/ProfileData/InstrProfWriter.cpp | 59 +- lib/ProfileData/LLVMBuild.txt | 2 +- lib/ProfileData/SampleProf.cpp | 51 + lib/ProfileData/SampleProfReader.cpp | 399 + lib/ProfileData/SampleProfWriter.cpp | 126 + lib/Support/APFloat.cpp | 74 +- lib/Support/APInt.cpp | 75 +- lib/Support/CMakeLists.txt | 69 +- lib/Support/CommandLine.cpp | 608 +- lib/Support/Compression.cpp | 6 + lib/Support/DataStream.cpp | 4 +- lib/Support/Debug.cpp | 24 +- lib/Support/Dwarf.cpp | 105 +- lib/Support/Errno.cpp | 8 +- lib/Support/ErrorHandling.cpp | 11 +- lib/Support/FileOutputBuffer.cpp | 40 +- lib/Support/FileUtilities.cpp | 16 +- lib/Support/GraphWriter.cpp | 5 +- lib/Support/Host.cpp | 84 +- lib/Support/IncludeFile.cpp | 20 - lib/Support/LineIterator.cpp | 55 +- lib/Support/LockFileManager.cpp | 8 +- lib/Support/MD5.cpp | 48 +- lib/Support/MathExtras.cpp | 32 + lib/Support/MemoryBuffer.cpp | 155 +- lib/Support/MemoryObject.cpp | 19 - lib/Support/Options.cpp | 33 + lib/Support/Path.cpp | 183 +- lib/Support/Process.cpp | 25 - lib/Support/RandomNumberGenerator.cpp | 30 +- lib/Support/ScaledNumber.cpp | 5 +- lib/Support/SmallPtrSet.cpp | 27 +- lib/Support/SourceMgr.cpp | 11 +- lib/Support/SpecialCaseList.cpp | 32 +- lib/Support/StreamableMemoryObject.cpp | 140 - lib/Support/StreamingMemoryObject.cpp | 127 + lib/Support/StringRef.cpp | 22 +- lib/Support/StringRefMemoryObject.cpp | 29 - lib/Support/ThreadLocal.cpp | 47 +- lib/Support/TimeValue.cpp | 6 - lib/Support/Timer.cpp | 8 +- lib/Support/ToolOutputFile.cpp | 15 +- lib/Support/Triple.cpp | 184 +- lib/Support/Unix/Host.inc | 12 +- lib/Support/Unix/Memory.inc | 4 +- lib/Support/Unix/Path.inc | 251 +- lib/Support/Unix/Process.inc | 142 +- lib/Support/Unix/Program.inc | 82 +- lib/Support/Unix/RWMutex.inc | 12 +- lib/Support/Unix/Signals.inc | 266 +- lib/Support/Unix/ThreadLocal.inc | 45 +- lib/Support/Unix/TimeValue.inc | 2 +- lib/Support/Unix/Unix.h | 4 +- lib/Support/Windows/DynamicLibrary.inc | 72 +- lib/Support/Windows/Host.inc | 2 +- lib/Support/Windows/Path.inc | 378 +- lib/Support/Windows/Process.inc | 41 +- lib/Support/Windows/Program.inc | 200 +- lib/Support/Windows/RWMutex.inc | 8 +- lib/Support/Windows/ThreadLocal.inc | 2 +- lib/Support/Windows/WindowsSupport.h | 9 + lib/Support/Windows/explicit_symbols.inc | 30 + lib/Support/YAMLParser.cpp | 60 +- lib/Support/YAMLTraits.cpp | 61 +- lib/Support/raw_ostream.cpp | 89 +- lib/TableGen/Main.cpp | 30 +- lib/TableGen/Record.cpp | 48 +- lib/TableGen/TGLexer.cpp | 3 +- lib/TableGen/TGLexer.h | 17 +- lib/TableGen/TGParser.cpp | 223 +- lib/TableGen/TGParser.h | 6 +- lib/Target/AArch64/AArch64.h | 11 +- lib/Target/AArch64/AArch64A53Fix835769.cpp | 240 + lib/Target/AArch64/AArch64A57FPLoadBalancing.cpp | 706 ++ lib/Target/AArch64/AArch64AddressTypePromotion.cpp | 6 +- lib/Target/AArch64/AArch64AdvSIMDScalarPass.cpp | 12 +- lib/Target/AArch64/AArch64AsmPrinter.cpp | 33 +- lib/Target/AArch64/AArch64BranchRelaxation.cpp | 11 +- lib/Target/AArch64/AArch64CallingConvention.h | 141 + lib/Target/AArch64/AArch64CallingConvention.td | 35 +- .../AArch64/AArch64CleanupLocalDynamicTLSPass.cpp | 4 +- lib/Target/AArch64/AArch64CollectLOH.cpp | 52 +- lib/Target/AArch64/AArch64ConditionOptimizer.cpp | 422 + lib/Target/AArch64/AArch64ConditionalCompares.cpp | 12 +- .../AArch64/AArch64DeadRegisterDefinitionsPass.cpp | 9 +- lib/Target/AArch64/AArch64ExpandPseudoInsts.cpp | 3 +- lib/Target/AArch64/AArch64FastISel.cpp | 4554 ++++++++-- lib/Target/AArch64/AArch64FrameLowering.cpp | 57 +- lib/Target/AArch64/AArch64FrameLowering.h | 4 +- lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 272 +- lib/Target/AArch64/AArch64ISelLowering.cpp | 1319 ++- lib/Target/AArch64/AArch64ISelLowering.h | 42 +- lib/Target/AArch64/AArch64InstrAtomics.td | 9 +- lib/Target/AArch64/AArch64InstrFormats.td | 44 +- lib/Target/AArch64/AArch64InstrInfo.cpp | 997 +- lib/Target/AArch64/AArch64InstrInfo.h | 42 +- lib/Target/AArch64/AArch64InstrInfo.td | 416 +- lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp | 16 +- lib/Target/AArch64/AArch64MCInstLower.cpp | 3 +- lib/Target/AArch64/AArch64MCInstLower.h | 6 +- lib/Target/AArch64/AArch64MachineCombinerPattern.h | 42 + lib/Target/AArch64/AArch64MachineFunctionInfo.h | 6 +- lib/Target/AArch64/AArch64PBQPRegAlloc.cpp | 383 + lib/Target/AArch64/AArch64PBQPRegAlloc.h | 38 + lib/Target/AArch64/AArch64PerfectShuffle.h | 5 + lib/Target/AArch64/AArch64PromoteConstant.cpp | 8 +- lib/Target/AArch64/AArch64RegisterInfo.cpp | 12 +- lib/Target/AArch64/AArch64RegisterInfo.h | 6 +- lib/Target/AArch64/AArch64RegisterInfo.td | 5 +- lib/Target/AArch64/AArch64SchedA57.td | 371 +- lib/Target/AArch64/AArch64SchedA57WriteRes.td | 52 +- lib/Target/AArch64/AArch64SelectionDAGInfo.cpp | 3 +- lib/Target/AArch64/AArch64SelectionDAGInfo.h | 4 +- lib/Target/AArch64/AArch64StorePairSuppress.cpp | 14 +- lib/Target/AArch64/AArch64Subtarget.cpp | 34 +- lib/Target/AArch64/AArch64Subtarget.h | 40 +- lib/Target/AArch64/AArch64TargetMachine.cpp | 133 +- lib/Target/AArch64/AArch64TargetMachine.h | 34 +- lib/Target/AArch64/AArch64TargetObjectFile.h | 4 +- lib/Target/AArch64/AArch64TargetTransformInfo.cpp | 78 +- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 149 +- lib/Target/AArch64/CMakeLists.txt | 6 +- .../AArch64/Disassembler/AArch64Disassembler.cpp | 67 +- .../AArch64/Disassembler/AArch64Disassembler.h | 11 +- .../Disassembler/AArch64ExternalSymbolizer.h | 4 +- lib/Target/AArch64/Disassembler/LLVMBuild.txt | 2 +- .../AArch64/InstPrinter/AArch64InstPrinter.cpp | 18 +- .../AArch64/InstPrinter/AArch64InstPrinter.h | 9 +- lib/Target/AArch64/LLVMBuild.txt | 2 +- .../AArch64/MCTargetDesc/AArch64AddressingModes.h | 104 +- .../AArch64/MCTargetDesc/AArch64AsmBackend.cpp | 53 +- .../MCTargetDesc/AArch64ELFObjectWriter.cpp | 2 +- .../AArch64/MCTargetDesc/AArch64ELFStreamer.cpp | 74 +- .../AArch64/MCTargetDesc/AArch64ELFStreamer.h | 8 +- .../AArch64/MCTargetDesc/AArch64FixupKinds.h | 4 +- .../AArch64/MCTargetDesc/AArch64MCAsmInfo.cpp | 7 +- lib/Target/AArch64/MCTargetDesc/AArch64MCAsmInfo.h | 4 +- .../AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp | 5 +- lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.cpp | 5 +- lib/Target/AArch64/MCTargetDesc/AArch64MCExpr.h | 7 +- .../AArch64/MCTargetDesc/AArch64MCTargetDesc.cpp | 47 +- .../AArch64/MCTargetDesc/AArch64MCTargetDesc.h | 15 +- .../MCTargetDesc/AArch64MachObjectWriter.cpp | 85 +- .../AArch64/MCTargetDesc/AArch64TargetStreamer.cpp | 2 + .../AArch64/TargetInfo/AArch64TargetInfo.cpp | 13 +- lib/Target/AArch64/Utils/AArch64BaseInfo.cpp | 36 +- lib/Target/AArch64/Utils/AArch64BaseInfo.h | 13 +- lib/Target/ARM/A15SDOptimizer.cpp | 6 +- lib/Target/ARM/ARM.h | 9 +- lib/Target/ARM/ARM.td | 34 +- lib/Target/ARM/ARMAsmPrinter.cpp | 161 +- lib/Target/ARM/ARMAsmPrinter.h | 10 +- lib/Target/ARM/ARMBaseInstrInfo.cpp | 264 +- lib/Target/ARM/ARMBaseInstrInfo.h | 76 +- lib/Target/ARM/ARMBaseRegisterInfo.cpp | 59 +- lib/Target/ARM/ARMBaseRegisterInfo.h | 6 +- lib/Target/ARM/ARMCallingConv.h | 29 +- lib/Target/ARM/ARMCodeEmitter.cpp | 1909 ---- lib/Target/ARM/ARMConstantIslandPass.cpp | 47 +- lib/Target/ARM/ARMConstantPoolValue.h | 4 +- lib/Target/ARM/ARMExpandPseudoInsts.cpp | 14 +- lib/Target/ARM/ARMFPUName.def | 1 + lib/Target/ARM/ARMFPUName.h | 6 +- lib/Target/ARM/ARMFastISel.cpp | 185 +- lib/Target/ARM/ARMFeatures.h | 4 +- lib/Target/ARM/ARMFrameLowering.cpp | 415 +- lib/Target/ARM/ARMFrameLowering.h | 4 +- lib/Target/ARM/ARMHazardRecognizer.cpp | 4 +- lib/Target/ARM/ARMHazardRecognizer.h | 6 +- lib/Target/ARM/ARMISelDAGToDAG.cpp | 88 +- lib/Target/ARM/ARMISelLowering.cpp | 1087 ++- lib/Target/ARM/ARMISelLowering.h | 36 +- lib/Target/ARM/ARMInstrFormats.td | 10 + lib/Target/ARM/ARMInstrInfo.cpp | 50 +- lib/Target/ARM/ARMInstrInfo.h | 8 +- lib/Target/ARM/ARMInstrInfo.td | 362 +- lib/Target/ARM/ARMInstrNEON.td | 48 +- lib/Target/ARM/ARMInstrThumb.td | 28 +- lib/Target/ARM/ARMInstrThumb2.td | 179 +- lib/Target/ARM/ARMInstrVFP.td | 80 +- lib/Target/ARM/ARMJITInfo.cpp | 344 - lib/Target/ARM/ARMJITInfo.h | 177 - lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 273 +- lib/Target/ARM/ARMMCInstLower.cpp | 36 +- lib/Target/ARM/ARMMachineFunctionInfo.h | 22 +- lib/Target/ARM/ARMOptimizeBarriersPass.cpp | 2 +- lib/Target/ARM/ARMPerfectShuffle.h | 5 + lib/Target/ARM/ARMRegisterInfo.h | 4 +- lib/Target/ARM/ARMRelocations.h | 62 - lib/Target/ARM/ARMSelectionDAGInfo.cpp | 2 +- lib/Target/ARM/ARMSelectionDAGInfo.h | 4 +- lib/Target/ARM/ARMSubtarget.cpp | 157 +- lib/Target/ARM/ARMSubtarget.h | 79 +- lib/Target/ARM/ARMTargetMachine.cpp | 137 +- lib/Target/ARM/ARMTargetMachine.h | 43 +- lib/Target/ARM/ARMTargetObjectFile.h | 4 +- lib/Target/ARM/ARMTargetTransformInfo.cpp | 31 +- lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 888 +- lib/Target/ARM/CMakeLists.txt | 5 +- lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 442 +- lib/Target/ARM/Disassembler/LLVMBuild.txt | 2 +- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 221 +- lib/Target/ARM/InstPrinter/ARMInstPrinter.h | 7 +- lib/Target/ARM/MCTargetDesc/ARMAddressingModes.h | 51 +- lib/Target/ARM/MCTargetDesc/ARMArchName.h | 6 +- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 432 +- lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h | 69 + lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h | 33 + lib/Target/ARM/MCTargetDesc/ARMAsmBackendELF.h | 27 + lib/Target/ARM/MCTargetDesc/ARMAsmBackendWinCOFF.h | 26 + lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h | 4 +- lib/Target/ARM/MCTargetDesc/ARMELFObjectWriter.cpp | 23 +- lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp | 39 +- lib/Target/ARM/MCTargetDesc/ARMFixupKinds.h | 4 +- lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp | 6 +- lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.h | 7 +- lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 22 + lib/Target/ARM/MCTargetDesc/ARMMCExpr.cpp | 6 - lib/Target/ARM/MCTargetDesc/ARMMCExpr.h | 11 +- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.cpp | 106 +- lib/Target/ARM/MCTargetDesc/ARMMCTargetDesc.h | 4 +- .../ARM/MCTargetDesc/ARMMachObjectWriter.cpp | 39 +- lib/Target/ARM/MCTargetDesc/ARMUnwindOpAsm.h | 6 +- lib/Target/ARM/MCTargetDesc/LLVMBuild.txt | 2 +- lib/Target/ARM/MLxExpansionPass.cpp | 4 +- lib/Target/ARM/Makefile | 2 +- lib/Target/ARM/Thumb1FrameLowering.cpp | 131 +- lib/Target/ARM/Thumb1FrameLowering.h | 4 +- lib/Target/ARM/Thumb1InstrInfo.cpp | 34 +- lib/Target/ARM/Thumb1InstrInfo.h | 9 +- lib/Target/ARM/Thumb1RegisterInfo.cpp | 390 +- lib/Target/ARM/Thumb1RegisterInfo.h | 6 +- lib/Target/ARM/Thumb2ITBlockPass.cpp | 7 +- lib/Target/ARM/Thumb2InstrInfo.cpp | 9 + lib/Target/ARM/Thumb2InstrInfo.h | 10 +- lib/Target/ARM/Thumb2RegisterInfo.cpp | 2 +- lib/Target/ARM/Thumb2RegisterInfo.h | 6 +- lib/Target/ARM/Thumb2SizeReduction.cpp | 6 +- lib/Target/CMakeLists.txt | 1 - lib/Target/CppBackend/CPPTargetMachine.h | 16 +- lib/Target/Hexagon/CMakeLists.txt | 25 +- lib/Target/Hexagon/Disassembler/CMakeLists.txt | 3 + .../Hexagon/Disassembler/HexagonDisassembler.cpp | 181 + lib/Target/Hexagon/Disassembler/LLVMBuild.txt | 23 + lib/Target/Hexagon/Disassembler/Makefile | 16 + lib/Target/Hexagon/Hexagon.h | 4 +- lib/Target/Hexagon/Hexagon.td | 14 +- lib/Target/Hexagon/HexagonAsmPrinter.cpp | 26 +- lib/Target/Hexagon/HexagonAsmPrinter.h | 4 +- lib/Target/Hexagon/HexagonCFGOptimizer.cpp | 28 +- lib/Target/Hexagon/HexagonCallingConvLower.cpp | 6 +- lib/Target/Hexagon/HexagonCallingConvLower.h | 4 +- lib/Target/Hexagon/HexagonCopyToCombine.cpp | 40 +- lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp | 46 +- lib/Target/Hexagon/HexagonFixupHwLoops.cpp | 14 +- lib/Target/Hexagon/HexagonFrameLowering.cpp | 31 +- lib/Target/Hexagon/HexagonFrameLowering.h | 4 +- lib/Target/Hexagon/HexagonHardwareLoops.cpp | 53 +- lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 152 +- lib/Target/Hexagon/HexagonISelLowering.cpp | 61 +- lib/Target/Hexagon/HexagonISelLowering.h | 15 +- lib/Target/Hexagon/HexagonInstrFormats.td | 22 +- lib/Target/Hexagon/HexagonInstrFormatsV4.td | 5 + lib/Target/Hexagon/HexagonInstrInfo.cpp | 672 +- lib/Target/Hexagon/HexagonInstrInfo.h | 9 +- lib/Target/Hexagon/HexagonInstrInfo.td | 5350 +++++++---- lib/Target/Hexagon/HexagonInstrInfoV3.td | 141 +- lib/Target/Hexagon/HexagonInstrInfoV4.td | 3636 +++++--- lib/Target/Hexagon/HexagonInstrInfoV5.td | 495 +- lib/Target/Hexagon/HexagonIntrinsics.td | 9 +- lib/Target/Hexagon/HexagonIntrinsicsDerived.td | 7 +- lib/Target/Hexagon/HexagonIntrinsicsV4.td | 9 +- lib/Target/Hexagon/HexagonMCInstLower.cpp | 1 - lib/Target/Hexagon/HexagonMachineFunctionInfo.h | 4 +- lib/Target/Hexagon/HexagonMachineScheduler.cpp | 10 +- lib/Target/Hexagon/HexagonMachineScheduler.h | 20 +- lib/Target/Hexagon/HexagonNewValueJump.cpp | 51 +- lib/Target/Hexagon/HexagonOperands.td | 23 + lib/Target/Hexagon/HexagonPeephole.cpp | 27 +- lib/Target/Hexagon/HexagonRegisterInfo.cpp | 37 +- lib/Target/Hexagon/HexagonRegisterInfo.h | 4 +- lib/Target/Hexagon/HexagonRegisterInfo.td | 164 +- lib/Target/Hexagon/HexagonSelectionDAGInfo.h | 4 +- .../Hexagon/HexagonSplitConst32AndConst64.cpp | 15 +- lib/Target/Hexagon/HexagonSplitTFRCondSets.cpp | 26 +- lib/Target/Hexagon/HexagonSubtarget.h | 28 +- lib/Target/Hexagon/HexagonTargetMachine.cpp | 43 +- lib/Target/Hexagon/HexagonTargetMachine.h | 31 +- lib/Target/Hexagon/HexagonTargetObjectFile.cpp | 5 +- lib/Target/Hexagon/HexagonTargetObjectFile.h | 4 +- lib/Target/Hexagon/HexagonVLIWPacketizer.cpp | 142 +- .../Hexagon/HexagonVarargsCallingConvention.h | 20 +- lib/Target/Hexagon/InstPrinter/CMakeLists.txt | 3 - .../Hexagon/InstPrinter/HexagonInstPrinter.cpp | 204 - .../Hexagon/InstPrinter/HexagonInstPrinter.h | 87 - lib/Target/Hexagon/InstPrinter/LLVMBuild.txt | 23 - lib/Target/Hexagon/InstPrinter/Makefile | 15 - lib/Target/Hexagon/LLVMBuild.txt | 4 +- lib/Target/Hexagon/MCTargetDesc/CMakeLists.txt | 6 + .../Hexagon/MCTargetDesc/HexagonAsmBackend.cpp | 74 + lib/Target/Hexagon/MCTargetDesc/HexagonBaseInfo.h | 14 +- .../MCTargetDesc/HexagonELFObjectWriter.cpp | 62 + .../Hexagon/MCTargetDesc/HexagonInstPrinter.cpp | 254 + .../Hexagon/MCTargetDesc/HexagonInstPrinter.h | 87 + .../Hexagon/MCTargetDesc/HexagonMCAsmInfo.cpp | 1 - lib/Target/Hexagon/MCTargetDesc/HexagonMCAsmInfo.h | 4 +- .../Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp | 88 + .../Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h | 60 + lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.cpp | 128 +- lib/Target/Hexagon/MCTargetDesc/HexagonMCInst.h | 124 +- .../Hexagon/MCTargetDesc/HexagonMCTargetDesc.cpp | 63 +- .../Hexagon/MCTargetDesc/HexagonMCTargetDesc.h | 26 +- lib/Target/Hexagon/MCTargetDesc/LLVMBuild.txt | 2 +- lib/Target/Hexagon/Makefile | 16 +- lib/Target/MSP430/InstPrinter/MSP430InstPrinter.h | 4 +- lib/Target/MSP430/MCTargetDesc/MSP430MCAsmInfo.h | 4 +- .../MSP430/MCTargetDesc/MSP430MCTargetDesc.cpp | 2 +- .../MSP430/MCTargetDesc/MSP430MCTargetDesc.h | 4 +- lib/Target/MSP430/MSP430.h | 4 +- lib/Target/MSP430/MSP430BranchSelector.cpp | 3 +- lib/Target/MSP430/MSP430CallingConv.td | 2 +- lib/Target/MSP430/MSP430FrameLowering.cpp | 69 +- lib/Target/MSP430/MSP430FrameLowering.h | 4 +- lib/Target/MSP430/MSP430ISelDAGToDAG.cpp | 6 +- lib/Target/MSP430/MSP430ISelLowering.cpp | 58 +- lib/Target/MSP430/MSP430ISelLowering.h | 6 +- lib/Target/MSP430/MSP430InstrInfo.cpp | 2 +- lib/Target/MSP430/MSP430InstrInfo.h | 4 +- lib/Target/MSP430/MSP430InstrInfo.td | 236 +- lib/Target/MSP430/MSP430MCInstLower.cpp | 5 +- lib/Target/MSP430/MSP430MCInstLower.h | 4 +- lib/Target/MSP430/MSP430MachineFunctionInfo.h | 4 +- lib/Target/MSP430/MSP430RegisterInfo.cpp | 48 +- lib/Target/MSP430/MSP430RegisterInfo.h | 6 +- lib/Target/MSP430/MSP430RegisterInfo.td | 38 +- lib/Target/MSP430/MSP430SelectionDAGInfo.h | 4 +- lib/Target/MSP430/MSP430Subtarget.cpp | 2 +- lib/Target/MSP430/MSP430Subtarget.h | 24 +- lib/Target/MSP430/MSP430TargetMachine.cpp | 11 +- lib/Target/MSP430/MSP430TargetMachine.h | 30 +- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 1436 ++- lib/Target/Mips/CMakeLists.txt | 6 +- lib/Target/Mips/Disassembler/LLVMBuild.txt | 2 +- lib/Target/Mips/Disassembler/MipsDisassembler.cpp | 537 +- lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp | 33 +- lib/Target/Mips/InstPrinter/MipsInstPrinter.h | 6 +- lib/Target/Mips/LLVMBuild.txt | 2 +- lib/Target/Mips/MCTargetDesc/CMakeLists.txt | 1 + lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h | 4 +- lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 45 + lib/Target/Mips/MCTargetDesc/MipsABIInfo.h | 61 + lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp | 17 +- lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h | 6 +- lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h | 4 +- .../Mips/MCTargetDesc/MipsELFObjectWriter.cpp | 11 +- lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp | 40 +- lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h | 24 +- lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h | 9 +- lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp | 2 +- lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h | 4 +- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 250 +- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h | 66 +- lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp | 5 +- lib/Target/Mips/MCTargetDesc/MipsMCExpr.h | 7 +- lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h | 7 +- lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp | 9 +- lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h | 4 +- .../Mips/MCTargetDesc/MipsNaClELFStreamer.cpp | 4 +- .../Mips/MCTargetDesc/MipsTargetStreamer.cpp | 253 +- lib/Target/Mips/Makefile | 2 +- lib/Target/Mips/MicroMipsInstrFPU.td | 8 +- lib/Target/Mips/MicroMipsInstrFormats.td | 277 + lib/Target/Mips/MicroMipsInstrInfo.td | 520 +- lib/Target/Mips/Mips.h | 6 +- lib/Target/Mips/Mips16FrameLowering.cpp | 8 +- lib/Target/Mips/Mips16FrameLowering.h | 4 +- lib/Target/Mips/Mips16HardFloat.cpp | 28 +- lib/Target/Mips/Mips16HardFloat.h | 23 +- lib/Target/Mips/Mips16HardFloatInfo.h | 4 +- lib/Target/Mips/Mips16ISelDAGToDAG.cpp | 17 +- lib/Target/Mips/Mips16ISelDAGToDAG.h | 4 +- lib/Target/Mips/Mips16ISelLowering.cpp | 53 +- lib/Target/Mips/Mips16ISelLowering.h | 15 +- lib/Target/Mips/Mips16InstrFormats.td | 2 +- lib/Target/Mips/Mips16InstrInfo.cpp | 6 +- lib/Target/Mips/Mips16InstrInfo.h | 4 +- lib/Target/Mips/Mips16InstrInfo.td | 20 +- lib/Target/Mips/Mips16RegisterInfo.cpp | 8 +- lib/Target/Mips/Mips16RegisterInfo.h | 4 +- lib/Target/Mips/Mips32r6InstrFormats.td | 2 +- lib/Target/Mips/Mips64InstrInfo.td | 26 +- lib/Target/Mips/MipsABIInfo.cpp | 45 - lib/Target/Mips/MipsABIInfo.h | 61 - lib/Target/Mips/MipsAnalyzeImmediate.cpp | 3 +- lib/Target/Mips/MipsAnalyzeImmediate.h | 4 +- lib/Target/Mips/MipsAsmPrinter.cpp | 59 +- lib/Target/Mips/MipsAsmPrinter.h | 12 +- lib/Target/Mips/MipsCCState.h | 7 +- lib/Target/Mips/MipsCallingConv.td | 58 +- lib/Target/Mips/MipsCodeEmitter.cpp | 481 - lib/Target/Mips/MipsCondMov.td | 37 + lib/Target/Mips/MipsConstantIslandPass.cpp | 11 +- lib/Target/Mips/MipsDelaySlotFiller.cpp | 139 +- lib/Target/Mips/MipsFastISel.cpp | 1131 ++- lib/Target/Mips/MipsFrameLowering.cpp | 2 +- lib/Target/Mips/MipsFrameLowering.h | 4 +- lib/Target/Mips/MipsISelDAGToDAG.h | 4 +- lib/Target/Mips/MipsISelLowering.cpp | 286 +- lib/Target/Mips/MipsISelLowering.h | 41 +- lib/Target/Mips/MipsInstrFPU.td | 68 +- lib/Target/Mips/MipsInstrFormats.td | 16 +- lib/Target/Mips/MipsInstrInfo.cpp | 2 +- lib/Target/Mips/MipsInstrInfo.h | 4 +- lib/Target/Mips/MipsInstrInfo.td | 232 +- lib/Target/Mips/MipsJITInfo.cpp | 286 - lib/Target/Mips/MipsJITInfo.h | 71 - lib/Target/Mips/MipsLongBranch.cpp | 28 +- lib/Target/Mips/MipsMCInstLower.h | 4 +- lib/Target/Mips/MipsMSAInstrInfo.td | 2 +- lib/Target/Mips/MipsMachineFunction.cpp | 18 +- lib/Target/Mips/MipsMachineFunction.h | 10 +- lib/Target/Mips/MipsModuleISelDAGToDAG.h | 4 +- lib/Target/Mips/MipsOptimizePICCall.cpp | 2 +- lib/Target/Mips/MipsOptionRecord.h | 12 +- lib/Target/Mips/MipsOs16.h | 8 +- lib/Target/Mips/MipsRegisterInfo.cpp | 6 +- lib/Target/Mips/MipsRegisterInfo.h | 4 +- lib/Target/Mips/MipsRegisterInfo.td | 44 +- lib/Target/Mips/MipsRelocations.h | 41 - lib/Target/Mips/MipsSEFrameLowering.cpp | 62 +- lib/Target/Mips/MipsSEFrameLowering.h | 4 +- lib/Target/Mips/MipsSEISelDAGToDAG.cpp | 7 +- lib/Target/Mips/MipsSEISelDAGToDAG.h | 4 +- lib/Target/Mips/MipsSEISelLowering.cpp | 91 +- lib/Target/Mips/MipsSEISelLowering.h | 15 +- lib/Target/Mips/MipsSEInstrInfo.cpp | 24 +- lib/Target/Mips/MipsSEInstrInfo.h | 5 +- lib/Target/Mips/MipsSERegisterInfo.cpp | 4 +- lib/Target/Mips/MipsSERegisterInfo.h | 4 +- lib/Target/Mips/MipsSelectionDAGInfo.h | 4 +- lib/Target/Mips/MipsSubtarget.cpp | 58 +- lib/Target/Mips/MipsSubtarget.h | 38 +- lib/Target/Mips/MipsTargetMachine.cpp | 100 +- lib/Target/Mips/MipsTargetMachine.h | 47 +- lib/Target/Mips/MipsTargetObjectFile.cpp | 73 +- lib/Target/Mips/MipsTargetObjectFile.h | 23 +- lib/Target/Mips/MipsTargetStreamer.h | 73 +- lib/Target/NVPTX/CMakeLists.txt | 24 +- lib/Target/NVPTX/InstPrinter/NVPTXInstPrinter.h | 4 +- lib/Target/NVPTX/MCTargetDesc/NVPTXBaseInfo.h | 4 +- lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.cpp | 5 +- lib/Target/NVPTX/MCTargetDesc/NVPTXMCAsmInfo.h | 8 +- lib/Target/NVPTX/MCTargetDesc/NVPTXMCTargetDesc.h | 4 +- lib/Target/NVPTX/ManagedStringPool.h | 4 +- lib/Target/NVPTX/NVPTX.h | 10 +- lib/Target/NVPTX/NVPTXAllocaHoisting.h | 6 +- lib/Target/NVPTX/NVPTXAsmPrinter.cpp | 229 +- lib/Target/NVPTX/NVPTXAsmPrinter.h | 30 +- lib/Target/NVPTX/NVPTXFrameLowering.cpp | 10 +- lib/Target/NVPTX/NVPTXFrameLowering.h | 4 +- lib/Target/NVPTX/NVPTXGenericToNVVM.cpp | 74 +- lib/Target/NVPTX/NVPTXISelDAGToDAG.cpp | 9 +- lib/Target/NVPTX/NVPTXISelDAGToDAG.h | 5 + lib/Target/NVPTX/NVPTXISelLowering.cpp | 105 +- lib/Target/NVPTX/NVPTXISelLowering.h | 16 +- lib/Target/NVPTX/NVPTXImageOptimizer.cpp | 2 +- lib/Target/NVPTX/NVPTXInstrInfo.cpp | 2 +- lib/Target/NVPTX/NVPTXInstrInfo.h | 4 +- lib/Target/NVPTX/NVPTXInstrInfo.td | 10 +- lib/Target/NVPTX/NVPTXLowerAggrCopies.h | 4 +- lib/Target/NVPTX/NVPTXLowerStructArgs.cpp | 134 + lib/Target/NVPTX/NVPTXMCExpr.h | 7 +- lib/Target/NVPTX/NVPTXMachineFunctionInfo.h | 5 + lib/Target/NVPTX/NVPTXPrologEpilogPass.cpp | 9 +- lib/Target/NVPTX/NVPTXRegisterInfo.h | 4 +- lib/Target/NVPTX/NVPTXReplaceImageHandles.cpp | 6 +- lib/Target/NVPTX/NVPTXSection.h | 4 +- lib/Target/NVPTX/NVPTXSubtarget.cpp | 3 +- lib/Target/NVPTX/NVPTXSubtarget.h | 24 +- lib/Target/NVPTX/NVPTXTargetMachine.cpp | 23 +- lib/Target/NVPTX/NVPTXTargetMachine.h | 41 +- lib/Target/NVPTX/NVPTXTargetObjectFile.h | 7 +- lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp | 115 + lib/Target/NVPTX/NVPTXUtilities.cpp | 19 +- lib/Target/NVPTX/NVPTXUtilities.h | 4 +- lib/Target/NVPTX/NVPTXVector.td | 4 +- lib/Target/NVPTX/NVPTXutil.h | 4 +- lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 224 +- lib/Target/PowerPC/CMakeLists.txt | 5 +- lib/Target/PowerPC/Disassembler/LLVMBuild.txt | 2 +- .../PowerPC/Disassembler/PPCDisassembler.cpp | 28 +- lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp | 7 + lib/Target/PowerPC/InstPrinter/PPCInstPrinter.h | 5 +- lib/Target/PowerPC/LLVMBuild.txt | 2 +- lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 2 +- .../PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp | 23 +- lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h | 4 +- lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp | 11 +- lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.h | 11 +- .../PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp | 57 + lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp | 73 +- lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.h | 11 +- .../PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp | 26 +- lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 4 +- .../PowerPC/MCTargetDesc/PPCMachObjectWriter.cpp | 20 +- lib/Target/PowerPC/MCTargetDesc/PPCPredicates.h | 4 +- lib/Target/PowerPC/Makefile | 2 +- lib/Target/PowerPC/PPC.h | 7 +- lib/Target/PowerPC/PPC.td | 52 +- lib/Target/PowerPC/PPCAsmPrinter.cpp | 232 +- lib/Target/PowerPC/PPCBranchSelector.cpp | 28 +- lib/Target/PowerPC/PPCCTRLoops.cpp | 25 +- lib/Target/PowerPC/PPCCallingConv.h | 35 + lib/Target/PowerPC/PPCCallingConv.td | 48 +- lib/Target/PowerPC/PPCCodeEmitter.cpp | 293 - lib/Target/PowerPC/PPCFastISel.cpp | 246 +- lib/Target/PowerPC/PPCFrameLowering.cpp | 89 +- lib/Target/PowerPC/PPCFrameLowering.h | 4 +- lib/Target/PowerPC/PPCHazardRecognizers.h | 12 +- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 2293 ++++- lib/Target/PowerPC/PPCISelLowering.cpp | 1622 ++-- lib/Target/PowerPC/PPCISelLowering.h | 126 +- lib/Target/PowerPC/PPCInstr64Bit.td | 73 +- lib/Target/PowerPC/PPCInstrAltivec.td | 114 +- lib/Target/PowerPC/PPCInstrBuilder.h | 4 +- lib/Target/PowerPC/PPCInstrFormats.td | 115 +- lib/Target/PowerPC/PPCInstrInfo.cpp | 71 +- lib/Target/PowerPC/PPCInstrInfo.h | 15 +- lib/Target/PowerPC/PPCInstrInfo.td | 458 +- lib/Target/PowerPC/PPCInstrSPE.td | 447 + lib/Target/PowerPC/PPCInstrVSX.td | 156 +- lib/Target/PowerPC/PPCJITInfo.cpp | 482 - lib/Target/PowerPC/PPCJITInfo.h | 46 - lib/Target/PowerPC/PPCMCInstLower.cpp | 6 +- lib/Target/PowerPC/PPCMachineFunctionInfo.cpp | 3 +- lib/Target/PowerPC/PPCMachineFunctionInfo.h | 11 +- lib/Target/PowerPC/PPCPerfectShuffle.h | 5 + lib/Target/PowerPC/PPCRegisterInfo.cpp | 82 +- lib/Target/PowerPC/PPCRegisterInfo.h | 6 +- lib/Target/PowerPC/PPCRegisterInfo.td | 9 +- lib/Target/PowerPC/PPCRelocations.h | 56 - lib/Target/PowerPC/PPCSchedule.td | 2 + lib/Target/PowerPC/PPCScheduleP7.td | 3 + lib/Target/PowerPC/PPCScheduleP8.td | 397 + lib/Target/PowerPC/PPCSelectionDAGInfo.h | 4 +- lib/Target/PowerPC/PPCSubtarget.cpp | 119 +- lib/Target/PowerPC/PPCSubtarget.h | 86 +- lib/Target/PowerPC/PPCTargetMachine.cpp | 136 +- lib/Target/PowerPC/PPCTargetMachine.h | 42 +- lib/Target/PowerPC/PPCTargetObjectFile.h | 4 +- lib/Target/PowerPC/PPCTargetStreamer.h | 4 +- lib/Target/PowerPC/PPCTargetTransformInfo.cpp | 80 +- lib/Target/PowerPC/README.txt | 275 - lib/Target/R600/AMDGPU.h | 17 +- lib/Target/R600/AMDGPU.td | 25 +- lib/Target/R600/AMDGPUAlwaysInlinePass.cpp | 66 + lib/Target/R600/AMDGPUAsmPrinter.cpp | 270 +- lib/Target/R600/AMDGPUAsmPrinter.h | 38 +- lib/Target/R600/AMDGPUCallingConv.td | 32 +- lib/Target/R600/AMDGPUFrameLowering.h | 6 +- lib/Target/R600/AMDGPUISelDAGToDAG.cpp | 471 +- lib/Target/R600/AMDGPUISelLowering.cpp | 1038 ++- lib/Target/R600/AMDGPUISelLowering.h | 91 +- lib/Target/R600/AMDGPUInstrInfo.cpp | 58 +- lib/Target/R600/AMDGPUInstrInfo.h | 19 +- lib/Target/R600/AMDGPUInstrInfo.td | 63 +- lib/Target/R600/AMDGPUInstructions.td | 115 +- lib/Target/R600/AMDGPUIntrinsicInfo.cpp | 2 +- lib/Target/R600/AMDGPUIntrinsicInfo.h | 8 +- lib/Target/R600/AMDGPUMCInstLower.cpp | 23 +- lib/Target/R600/AMDGPUMCInstLower.h | 9 +- lib/Target/R600/AMDGPUMachineFunction.cpp | 4 +- lib/Target/R600/AMDGPUMachineFunction.h | 12 +- lib/Target/R600/AMDGPUPromoteAlloca.cpp | 48 +- lib/Target/R600/AMDGPURegisterInfo.cpp | 3 +- lib/Target/R600/AMDGPURegisterInfo.h | 8 +- lib/Target/R600/AMDGPUSubtarget.cpp | 80 +- lib/Target/R600/AMDGPUSubtarget.h | 58 +- lib/Target/R600/AMDGPUTargetMachine.cpp | 145 +- lib/Target/R600/AMDGPUTargetMachine.h | 52 +- lib/Target/R600/AMDGPUTargetTransformInfo.cpp | 20 +- lib/Target/R600/AMDILCFGStructurizer.cpp | 5 +- lib/Target/R600/AMDKernelCodeT.h | 704 ++ lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp | 320 + lib/Target/R600/AsmParser/CMakeLists.txt | 3 + lib/Target/R600/AsmParser/LLVMBuild.txt | 23 + lib/Target/R600/AsmParser/Makefile | 15 + lib/Target/R600/CIInstructions.td | 42 + lib/Target/R600/CMakeLists.txt | 8 +- lib/Target/R600/CaymanInstructions.td | 2 + lib/Target/R600/EvergreenInstructions.td | 73 +- lib/Target/R600/InstPrinter/AMDGPUInstPrinter.cpp | 275 +- lib/Target/R600/InstPrinter/AMDGPUInstPrinter.h | 23 +- lib/Target/R600/LLVMBuild.txt | 5 +- lib/Target/R600/MCTargetDesc/AMDGPUAsmBackend.cpp | 13 +- lib/Target/R600/MCTargetDesc/AMDGPUFixupKinds.h | 6 +- lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.cpp | 23 +- lib/Target/R600/MCTargetDesc/AMDGPUMCAsmInfo.h | 18 +- lib/Target/R600/MCTargetDesc/AMDGPUMCCodeEmitter.h | 6 +- .../R600/MCTargetDesc/AMDGPUMCTargetDesc.cpp | 19 +- lib/Target/R600/MCTargetDesc/AMDGPUMCTargetDesc.h | 7 +- lib/Target/R600/MCTargetDesc/SIMCCodeEmitter.cpp | 13 +- lib/Target/R600/Makefile | 4 +- lib/Target/R600/Processors.td | 32 +- lib/Target/R600/R600ClauseMergePass.cpp | 3 +- lib/Target/R600/R600ControlFlowFinalizer.cpp | 21 +- lib/Target/R600/R600Defines.h | 6 +- lib/Target/R600/R600EmitClauseMarkers.cpp | 3 +- lib/Target/R600/R600ExpandSpecialInstrs.cpp | 3 +- lib/Target/R600/R600ISelLowering.cpp | 176 +- lib/Target/R600/R600ISelLowering.h | 6 +- lib/Target/R600/R600InstrFormats.td | 3 + lib/Target/R600/R600InstrInfo.cpp | 15 +- lib/Target/R600/R600InstrInfo.h | 12 +- lib/Target/R600/R600Instructions.td | 44 +- lib/Target/R600/R600MachineFunctionInfo.h | 6 +- lib/Target/R600/R600MachineScheduler.cpp | 33 +- lib/Target/R600/R600MachineScheduler.h | 4 +- lib/Target/R600/R600OptimizeVectorRegisters.cpp | 8 +- lib/Target/R600/R600Packetizer.cpp | 15 +- lib/Target/R600/R600RegisterInfo.h | 6 +- lib/Target/R600/SIDefines.h | 96 +- lib/Target/R600/SIFixSGPRCopies.cpp | 106 +- lib/Target/R600/SIFixSGPRLiveRanges.cpp | 147 +- lib/Target/R600/SIFoldOperands.cpp | 275 + lib/Target/R600/SIISelLowering.cpp | 1643 ++-- lib/Target/R600/SIISelLowering.h | 57 +- lib/Target/R600/SIInsertWaits.cpp | 90 +- lib/Target/R600/SIInstrFormats.td | 256 +- lib/Target/R600/SIInstrInfo.cpp | 1702 +++- lib/Target/R600/SIInstrInfo.h | 195 +- lib/Target/R600/SIInstrInfo.td | 1817 +++- lib/Target/R600/SIInstructions.td | 3016 +++--- lib/Target/R600/SILoadStoreOptimizer.cpp | 434 + lib/Target/R600/SILowerControlFlow.cpp | 86 +- lib/Target/R600/SILowerI1Copies.cpp | 105 +- lib/Target/R600/SIMachineFunctionInfo.cpp | 96 +- lib/Target/R600/SIMachineFunctionInfo.h | 41 +- lib/Target/R600/SIPrepareScratchRegs.cpp | 196 + lib/Target/R600/SIRegisterInfo.cpp | 355 +- lib/Target/R600/SIRegisterInfo.h | 50 +- lib/Target/R600/SIRegisterInfo.td | 78 +- lib/Target/R600/SISchedule.td | 80 +- lib/Target/R600/SIShrinkInstructions.cpp | 136 +- lib/Target/R600/SITypeRewriter.cpp | 2 +- lib/Target/R600/TargetInfo/AMDGPUTargetInfo.cpp | 6 +- lib/Target/R600/VIInstrFormats.td | 145 + lib/Target/R600/VIInstructions.td | 89 + lib/Target/README.txt | 84 +- lib/Target/Sparc/AsmParser/SparcAsmParser.cpp | 13 +- lib/Target/Sparc/CMakeLists.txt | 5 +- lib/Target/Sparc/DelaySlotFiller.cpp | 9 +- lib/Target/Sparc/Disassembler/LLVMBuild.txt | 2 +- .../Sparc/Disassembler/SparcDisassembler.cpp | 61 +- lib/Target/Sparc/InstPrinter/SparcInstPrinter.h | 4 +- lib/Target/Sparc/MCTargetDesc/SparcFixupKinds.h | 4 +- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.cpp | 5 +- lib/Target/Sparc/MCTargetDesc/SparcMCAsmInfo.h | 4 +- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.cpp | 5 +- lib/Target/Sparc/MCTargetDesc/SparcMCExpr.h | 7 +- .../Sparc/MCTargetDesc/SparcMCTargetDesc.cpp | 6 +- lib/Target/Sparc/MCTargetDesc/SparcMCTargetDesc.h | 4 +- lib/Target/Sparc/Makefile | 2 +- lib/Target/Sparc/README.txt | 2 - lib/Target/Sparc/Sparc.h | 6 +- lib/Target/Sparc/SparcAsmPrinter.cpp | 5 +- lib/Target/Sparc/SparcCodeEmitter.cpp | 280 - lib/Target/Sparc/SparcFrameLowering.cpp | 6 +- lib/Target/Sparc/SparcFrameLowering.h | 4 +- lib/Target/Sparc/SparcISelDAGToDAG.cpp | 15 +- lib/Target/Sparc/SparcISelLowering.cpp | 72 +- lib/Target/Sparc/SparcISelLowering.h | 4 +- lib/Target/Sparc/SparcInstrInfo.h | 4 +- lib/Target/Sparc/SparcInstrInfo.td | 2 +- lib/Target/Sparc/SparcInstrVIS.td | 34 +- lib/Target/Sparc/SparcJITInfo.cpp | 326 - lib/Target/Sparc/SparcJITInfo.h | 67 - lib/Target/Sparc/SparcMachineFunctionInfo.h | 4 +- lib/Target/Sparc/SparcRegisterInfo.cpp | 6 +- lib/Target/Sparc/SparcRegisterInfo.h | 4 +- lib/Target/Sparc/SparcRelocations.h | 56 - lib/Target/Sparc/SparcSelectionDAGInfo.h | 4 +- lib/Target/Sparc/SparcSubtarget.h | 25 +- lib/Target/Sparc/SparcTargetMachine.cpp | 26 +- lib/Target/Sparc/SparcTargetMachine.h | 29 +- lib/Target/Sparc/SparcTargetObjectFile.h | 4 +- lib/Target/Sparc/SparcTargetStreamer.h | 4 +- lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp | 9 +- lib/Target/SystemZ/CMakeLists.txt | 2 +- lib/Target/SystemZ/Disassembler/LLVMBuild.txt | 2 +- .../SystemZ/Disassembler/SystemZDisassembler.cpp | 21 +- .../SystemZ/InstPrinter/SystemZInstPrinter.h | 4 +- lib/Target/SystemZ/LLVMBuild.txt | 2 +- .../SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp | 7 +- lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h | 7 +- lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h | 4 +- .../SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp | 15 +- .../SystemZ/MCTargetDesc/SystemZMCTargetDesc.h | 4 +- lib/Target/SystemZ/Makefile | 1 - lib/Target/SystemZ/SystemZ.h | 4 +- lib/Target/SystemZ/SystemZAsmPrinter.cpp | 5 +- lib/Target/SystemZ/SystemZAsmPrinter.h | 4 +- lib/Target/SystemZ/SystemZCallingConv.h | 4 +- lib/Target/SystemZ/SystemZConstantPoolValue.h | 4 +- lib/Target/SystemZ/SystemZElimCompare.cpp | 4 +- lib/Target/SystemZ/SystemZFrameLowering.cpp | 16 +- lib/Target/SystemZ/SystemZFrameLowering.h | 4 +- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp | 12 +- lib/Target/SystemZ/SystemZISelLowering.cpp | 65 +- lib/Target/SystemZ/SystemZISelLowering.h | 11 +- lib/Target/SystemZ/SystemZInstrBuilder.h | 4 +- lib/Target/SystemZ/SystemZInstrFP.td | 4 +- lib/Target/SystemZ/SystemZInstrInfo.cpp | 2 +- lib/Target/SystemZ/SystemZInstrInfo.h | 4 +- lib/Target/SystemZ/SystemZInstrInfo.td | 26 +- lib/Target/SystemZ/SystemZLongBranch.cpp | 2 +- lib/Target/SystemZ/SystemZMCInstLower.h | 4 +- lib/Target/SystemZ/SystemZMachineFunctionInfo.h | 4 +- lib/Target/SystemZ/SystemZRegisterInfo.cpp | 8 +- lib/Target/SystemZ/SystemZRegisterInfo.h | 4 +- lib/Target/SystemZ/SystemZSelectionDAGInfo.h | 4 +- lib/Target/SystemZ/SystemZShortenInst.cpp | 2 +- lib/Target/SystemZ/SystemZSubtarget.h | 22 +- lib/Target/SystemZ/SystemZTargetMachine.cpp | 19 +- lib/Target/SystemZ/SystemZTargetMachine.h | 28 +- lib/Target/Target.cpp | 2 +- lib/Target/TargetJITInfo.cpp | 14 - lib/Target/TargetLibraryInfo.cpp | 19 +- lib/Target/TargetLoweringObjectFile.cpp | 31 +- lib/Target/TargetMachine.cpp | 41 +- lib/Target/TargetMachineC.cpp | 15 +- lib/Target/TargetSubtargetInfo.cpp | 4 +- lib/Target/X86/AsmParser/CMakeLists.txt | 3 + lib/Target/X86/AsmParser/LLVMBuild.txt | 2 +- lib/Target/X86/AsmParser/X86AsmInstrumentation.cpp | 1033 ++- lib/Target/X86/AsmParser/X86AsmInstrumentation.h | 28 +- lib/Target/X86/AsmParser/X86AsmParser.cpp | 559 +- lib/Target/X86/AsmParser/X86AsmParserCommon.h | 10 +- lib/Target/X86/AsmParser/X86Operand.h | 95 +- lib/Target/X86/CMakeLists.txt | 3 - lib/Target/X86/Disassembler/LLVMBuild.txt | 2 +- lib/Target/X86/Disassembler/X86Disassembler.cpp | 211 +- lib/Target/X86/Disassembler/X86Disassembler.h | 16 +- .../X86/Disassembler/X86DisassemblerDecoder.cpp | 171 +- .../X86/Disassembler/X86DisassemblerDecoder.h | 23 +- .../Disassembler/X86DisassemblerDecoderCommon.h | 35 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp | 75 +- lib/Target/X86/InstPrinter/X86ATTInstPrinter.h | 23 +- lib/Target/X86/InstPrinter/X86InstComments.cpp | 340 +- lib/Target/X86/InstPrinter/X86InstComments.h | 6 +- lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp | 52 +- lib/Target/X86/InstPrinter/X86IntelInstPrinter.h | 12 +- lib/Target/X86/MCTargetDesc/LLVMBuild.txt | 2 +- lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 65 +- lib/Target/X86/MCTargetDesc/X86BaseInfo.h | 168 +- lib/Target/X86/MCTargetDesc/X86ELFObjectWriter.cpp | 2 +- lib/Target/X86/MCTargetDesc/X86FixupKinds.h | 4 +- lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp | 25 +- lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h | 9 +- lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp | 116 +- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp | 11 +- lib/Target/X86/MCTargetDesc/X86MCTargetDesc.h | 8 +- .../X86/MCTargetDesc/X86MachObjectWriter.cpp | 131 +- lib/Target/X86/MCTargetDesc/X86WinCOFFStreamer.cpp | 11 +- lib/Target/X86/README.txt | 177 - lib/Target/X86/TargetInfo/X86TargetInfo.cpp | 2 +- lib/Target/X86/Utils/LLVMBuild.txt | 2 +- lib/Target/X86/Utils/X86ShuffleDecode.cpp | 170 + lib/Target/X86/Utils/X86ShuffleDecode.h | 31 +- lib/Target/X86/X86.h | 14 +- lib/Target/X86/X86.td | 262 +- lib/Target/X86/X86AsmPrinter.cpp | 28 +- lib/Target/X86/X86AsmPrinter.h | 75 +- lib/Target/X86/X86AtomicExpandPass.cpp | 283 - lib/Target/X86/X86CallingConv.h | 17 +- lib/Target/X86/X86CallingConv.td | 77 +- lib/Target/X86/X86CodeEmitter.cpp | 1498 --- lib/Target/X86/X86FastISel.cpp | 611 +- lib/Target/X86/X86FixupLEAs.cpp | 9 +- lib/Target/X86/X86FloatingPoint.cpp | 392 +- lib/Target/X86/X86FrameLowering.cpp | 507 +- lib/Target/X86/X86FrameLowering.h | 23 +- lib/Target/X86/X86ISelDAGToDAG.cpp | 222 +- lib/Target/X86/X86ISelLowering.cpp | 9557 ++++++++++++++------ lib/Target/X86/X86ISelLowering.h | 266 +- lib/Target/X86/X86InstrAVX512.td | 3774 +++++--- lib/Target/X86/X86InstrArithmetic.td | 359 +- lib/Target/X86/X86InstrBuilder.h | 4 +- lib/Target/X86/X86InstrCompiler.td | 186 +- lib/Target/X86/X86InstrControl.td | 92 +- lib/Target/X86/X86InstrExtension.td | 26 +- lib/Target/X86/X86InstrFMA.td | 6 +- lib/Target/X86/X86InstrFPStack.td | 85 +- lib/Target/X86/X86InstrFormats.td | 168 +- lib/Target/X86/X86InstrFragmentsSIMD.td | 61 +- lib/Target/X86/X86InstrInfo.cpp | 1082 ++- lib/Target/X86/X86InstrInfo.h | 10 +- lib/Target/X86/X86InstrInfo.td | 775 +- lib/Target/X86/X86InstrMMX.td | 45 +- lib/Target/X86/X86InstrSGX.td | 24 + lib/Target/X86/X86InstrSSE.td | 1760 ++-- lib/Target/X86/X86InstrShiftRotate.td | 58 +- lib/Target/X86/X86InstrSystem.td | 40 +- lib/Target/X86/X86InstrTSX.td | 9 +- lib/Target/X86/X86IntrinsicsInfo.h | 547 ++ lib/Target/X86/X86JITInfo.cpp | 588 -- lib/Target/X86/X86JITInfo.h | 79 - lib/Target/X86/X86MCInstLower.cpp | 527 +- lib/Target/X86/X86MachineFunctionInfo.cpp | 19 + lib/Target/X86/X86MachineFunctionInfo.h | 27 +- lib/Target/X86/X86PadShortFunction.cpp | 5 +- lib/Target/X86/X86RegisterInfo.cpp | 43 +- lib/Target/X86/X86RegisterInfo.h | 5 +- lib/Target/X86/X86RegisterInfo.td | 45 +- lib/Target/X86/X86Relocations.h | 52 - lib/Target/X86/X86SchedHaswell.td | 1885 +++- lib/Target/X86/X86SchedSandyBridge.td | 1 + lib/Target/X86/X86Schedule.td | 20 +- lib/Target/X86/X86ScheduleAtom.td | 5 + lib/Target/X86/X86ScheduleBtVer2.td | 341 + lib/Target/X86/X86ScheduleSLM.td | 1 + lib/Target/X86/X86SelectionDAGInfo.cpp | 37 +- lib/Target/X86/X86SelectionDAGInfo.h | 9 +- lib/Target/X86/X86Subtarget.cpp | 85 +- lib/Target/X86/X86Subtarget.h | 98 +- lib/Target/X86/X86TargetMachine.cpp | 117 +- lib/Target/X86/X86TargetMachine.h | 37 +- lib/Target/X86/X86TargetObjectFile.h | 4 +- lib/Target/X86/X86TargetTransformInfo.cpp | 162 +- lib/Target/X86/X86VZeroUpper.cpp | 22 +- lib/Target/XCore/Disassembler/LLVMBuild.txt | 2 +- .../XCore/Disassembler/XCoreDisassembler.cpp | 57 +- lib/Target/XCore/InstPrinter/XCoreInstPrinter.h | 4 +- lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.cpp | 1 - lib/Target/XCore/MCTargetDesc/XCoreMCAsmInfo.h | 4 +- .../XCore/MCTargetDesc/XCoreMCTargetDesc.cpp | 8 +- lib/Target/XCore/MCTargetDesc/XCoreMCTargetDesc.h | 4 +- lib/Target/XCore/XCore.h | 4 +- lib/Target/XCore/XCoreAsmPrinter.cpp | 4 +- lib/Target/XCore/XCoreFrameLowering.cpp | 26 +- lib/Target/XCore/XCoreFrameLowering.h | 6 +- lib/Target/XCore/XCoreFrameToArgsOffsetElim.cpp | 3 +- lib/Target/XCore/XCoreISelLowering.cpp | 72 +- lib/Target/XCore/XCoreISelLowering.h | 6 +- lib/Target/XCore/XCoreInstrInfo.cpp | 9 +- lib/Target/XCore/XCoreInstrInfo.h | 4 +- lib/Target/XCore/XCoreInstrInfo.td | 38 +- lib/Target/XCore/XCoreMCInstLower.h | 4 +- lib/Target/XCore/XCoreMachineFunctionInfo.h | 6 +- lib/Target/XCore/XCoreRegisterInfo.cpp | 17 +- lib/Target/XCore/XCoreRegisterInfo.h | 4 +- lib/Target/XCore/XCoreSelectionDAGInfo.cpp | 2 +- lib/Target/XCore/XCoreSelectionDAGInfo.h | 4 +- lib/Target/XCore/XCoreSubtarget.h | 22 +- lib/Target/XCore/XCoreTargetMachine.cpp | 18 +- lib/Target/XCore/XCoreTargetMachine.h | 27 +- lib/Target/XCore/XCoreTargetObjectFile.cpp | 6 +- lib/Target/XCore/XCoreTargetObjectFile.h | 4 +- lib/Target/XCore/XCoreTargetStreamer.h | 4 +- lib/Target/XCore/XCoreTargetTransformInfo.cpp | 6 +- lib/Transforms/IPO/ArgumentPromotion.cpp | 132 +- lib/Transforms/IPO/ConstantMerge.cpp | 2 +- lib/Transforms/IPO/DeadArgumentElimination.cpp | 28 +- lib/Transforms/IPO/ExtractGV.cpp | 10 +- lib/Transforms/IPO/FunctionAttrs.cpp | 30 +- lib/Transforms/IPO/GlobalDCE.cpp | 54 +- lib/Transforms/IPO/GlobalOpt.cpp | 109 +- lib/Transforms/IPO/InlineAlways.cpp | 4 + lib/Transforms/IPO/InlineSimple.cpp | 4 + lib/Transforms/IPO/Inliner.cpp | 22 +- lib/Transforms/IPO/Internalize.cpp | 4 +- lib/Transforms/IPO/MergeFunctions.cpp | 77 +- lib/Transforms/IPO/PassManagerBuilder.cpp | 212 +- lib/Transforms/IPO/PruneEH.cpp | 4 +- lib/Transforms/IPO/StripSymbols.cpp | 31 +- lib/Transforms/InstCombine/InstCombine.h | 97 +- lib/Transforms/InstCombine/InstCombineAddSub.cpp | 242 +- lib/Transforms/InstCombine/InstCombineAndOrXor.cpp | 535 +- lib/Transforms/InstCombine/InstCombineCalls.cpp | 416 +- lib/Transforms/InstCombine/InstCombineCasts.cpp | 125 +- lib/Transforms/InstCombine/InstCombineCompares.cpp | 505 +- .../InstCombine/InstCombineLoadStoreAlloca.cpp | 387 +- .../InstCombine/InstCombineMulDivRem.cpp | 471 +- lib/Transforms/InstCombine/InstCombinePHI.cpp | 12 +- lib/Transforms/InstCombine/InstCombineSelect.cpp | 140 +- lib/Transforms/InstCombine/InstCombineShifts.cpp | 56 +- .../InstCombine/InstCombineSimplifyDemanded.cpp | 77 +- lib/Transforms/InstCombine/InstCombineWorklist.h | 4 +- .../InstCombine/InstructionCombining.cpp | 241 +- .../Instrumentation/AddressSanitizer.cpp | 858 +- lib/Transforms/Instrumentation/CMakeLists.txt | 3 +- .../Instrumentation/DataFlowSanitizer.cpp | 204 +- lib/Transforms/Instrumentation/DebugIR.cpp | 617 -- lib/Transforms/Instrumentation/DebugIR.h | 98 - lib/Transforms/Instrumentation/GCOVProfiling.cpp | 57 +- lib/Transforms/Instrumentation/InstrProfiling.cpp | 309 + lib/Transforms/Instrumentation/Instrumentation.cpp | 2 + lib/Transforms/Instrumentation/LLVMBuild.txt | 2 +- lib/Transforms/Instrumentation/MemorySanitizer.cpp | 419 +- .../Instrumentation/SanitizerCoverage.cpp | 314 + lib/Transforms/Instrumentation/ThreadSanitizer.cpp | 44 +- lib/Transforms/ObjCARC/ARCRuntimeEntryPoints.h | 6 +- lib/Transforms/ObjCARC/CMakeLists.txt | 1 + lib/Transforms/ObjCARC/DependencyAnalysis.cpp | 10 +- lib/Transforms/ObjCARC/DependencyAnalysis.h | 10 +- lib/Transforms/ObjCARC/ObjCARC.cpp | 1 + lib/Transforms/ObjCARC/ObjCARC.h | 20 +- lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp | 6 +- lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.h | 6 +- lib/Transforms/ObjCARC/ObjCARCContract.cpp | 13 +- lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 91 +- lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp | 4 +- lib/Transforms/ObjCARC/ProvenanceAnalysis.h | 6 +- .../ObjCARC/ProvenanceAnalysisEvaluator.cpp | 92 + lib/Transforms/Scalar/ADCE.cpp | 2 +- lib/Transforms/Scalar/AlignmentFromAssumptions.cpp | 428 + lib/Transforms/Scalar/CMakeLists.txt | 1 + lib/Transforms/Scalar/ConstantHoisting.cpp | 4 +- .../Scalar/CorrelatedValuePropagation.cpp | 18 +- lib/Transforms/Scalar/DeadStoreElimination.cpp | 9 +- lib/Transforms/Scalar/EarlyCSE.cpp | 29 +- lib/Transforms/Scalar/GVN.cpp | 440 +- lib/Transforms/Scalar/IndVarSimplify.cpp | 154 +- lib/Transforms/Scalar/JumpThreading.cpp | 130 +- lib/Transforms/Scalar/LICM.cpp | 99 +- lib/Transforms/Scalar/LLVMBuild.txt | 2 +- lib/Transforms/Scalar/LoadCombine.cpp | 25 +- lib/Transforms/Scalar/LoopDeletion.cpp | 5 +- lib/Transforms/Scalar/LoopInstSimplify.cpp | 11 +- lib/Transforms/Scalar/LoopRerollPass.cpp | 58 +- lib/Transforms/Scalar/LoopRotation.cpp | 49 +- lib/Transforms/Scalar/LoopStrengthReduce.cpp | 72 +- lib/Transforms/Scalar/LoopUnrollPass.cpp | 158 +- lib/Transforms/Scalar/LoopUnswitch.cpp | 24 +- lib/Transforms/Scalar/MemCpyOptimizer.cpp | 62 +- lib/Transforms/Scalar/MergedLoadStoreMotion.cpp | 151 +- lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp | 4 + lib/Transforms/Scalar/Reassociate.cpp | 473 +- lib/Transforms/Scalar/Reg2Mem.cpp | 2 +- lib/Transforms/Scalar/SCCP.cpp | 8 +- lib/Transforms/Scalar/SROA.cpp | 1824 ++-- lib/Transforms/Scalar/SampleProfile.cpp | 570 +- lib/Transforms/Scalar/Scalar.cpp | 14 + lib/Transforms/Scalar/ScalarReplAggregates.cpp | 52 +- lib/Transforms/Scalar/Scalarizer.cpp | 33 +- .../Scalar/SeparateConstOffsetFromGEP.cpp | 333 +- lib/Transforms/Scalar/SimplifyCFGPass.cpp | 27 +- lib/Transforms/Scalar/Sink.cpp | 11 +- lib/Transforms/Scalar/StructurizeCFG.cpp | 7 +- lib/Transforms/Scalar/TailRecursionElimination.cpp | 36 +- lib/Transforms/Utils/AddDiscriminators.cpp | 8 +- lib/Transforms/Utils/BasicBlockUtils.cpp | 12 + lib/Transforms/Utils/BreakCriticalEdges.cpp | 24 +- lib/Transforms/Utils/BuildLibCalls.cpp | 188 +- lib/Transforms/Utils/CMakeLists.txt | 7 +- lib/Transforms/Utils/CloneFunction.cpp | 20 +- lib/Transforms/Utils/CloneModule.cpp | 13 +- lib/Transforms/Utils/CtorUtils.cpp | 71 +- lib/Transforms/Utils/FlattenCFG.cpp | 9 +- lib/Transforms/Utils/GlobalStatus.cpp | 7 +- lib/Transforms/Utils/InlineFunction.cpp | 507 +- lib/Transforms/Utils/IntegerDivision.cpp | 16 +- lib/Transforms/Utils/LCSSA.cpp | 49 +- lib/Transforms/Utils/Local.cpp | 155 +- lib/Transforms/Utils/LoopSimplify.cpp | 53 +- lib/Transforms/Utils/LoopUnroll.cpp | 62 +- lib/Transforms/Utils/LoopUnrollRuntime.cpp | 258 +- lib/Transforms/Utils/LowerSwitch.cpp | 45 +- lib/Transforms/Utils/Mem2Reg.cpp | 7 +- lib/Transforms/Utils/ModuleUtils.cpp | 2 +- lib/Transforms/Utils/PromoteMemoryToRegister.cpp | 42 +- lib/Transforms/Utils/SimplifyCFG.cpp | 979 +- lib/Transforms/Utils/SimplifyIndVar.cpp | 148 +- lib/Transforms/Utils/SimplifyInstructions.cpp | 7 +- lib/Transforms/Utils/SimplifyLibCalls.cpp | 3758 ++++---- lib/Transforms/Utils/SymbolRewriter.cpp | 527 ++ lib/Transforms/Utils/ValueMapper.cpp | 292 +- lib/Transforms/Vectorize/BBVectorize.cpp | 40 +- lib/Transforms/Vectorize/LoopVectorize.cpp | 714 +- lib/Transforms/Vectorize/SLPVectorizer.cpp | 1369 ++- projects/CMakeLists.txt | 4 +- test/Analysis/BasicAA/2008-04-15-Byval.ll | 2 +- test/Analysis/BasicAA/assume.ll | 23 + test/Analysis/BasicAA/full-store-partial-alias.ll | 12 +- test/Analysis/BasicAA/gcsetest.ll | 4 +- test/Analysis/BasicAA/invariant_load.ll | 2 +- test/Analysis/BasicAA/modref.ll | 34 +- test/Analysis/BasicAA/phi-aa.ll | 1 + test/Analysis/BasicAA/zext.ll | 209 + test/Analysis/BlockFrequencyInfo/bad_input.ll | 4 +- test/Analysis/BlockFrequencyInfo/basic.ll | 6 +- .../Analysis/BlockFrequencyInfo/double_backedge.ll | 4 +- test/Analysis/BlockFrequencyInfo/double_exit.ll | 8 +- .../extremely-likely-loop-successor.ll | 2 +- test/Analysis/BlockFrequencyInfo/irreducible.ll | 48 +- .../BlockFrequencyInfo/loop_with_branch.ll | 4 +- .../nested_loop_with_branches.ll | 4 +- test/Analysis/BranchProbabilityInfo/basic.ll | 6 +- .../Analysis/CFLAliasAnalysis/arguments-globals.ll | 20 + test/Analysis/CFLAliasAnalysis/arguments.ll | 15 + .../CFLAliasAnalysis/basic-interproc-ret.ll | 26 + test/Analysis/CFLAliasAnalysis/basic-interproc.ll | 24 + test/Analysis/CFLAliasAnalysis/const-expr-gep.ll | 21 + .../CFLAliasAnalysis/constant-over-index.ll | 30 + test/Analysis/CFLAliasAnalysis/empty.ll | 12 + .../CFLAliasAnalysis/full-store-partial-alias.ll | 37 + .../CFLAliasAnalysis/gep-signed-arithmetic.ll | 17 + .../CFLAliasAnalysis/multilevel-combine.ll | 31 + test/Analysis/CFLAliasAnalysis/multilevel.ll | 30 + test/Analysis/CFLAliasAnalysis/must-and-partial.ll | 39 + test/Analysis/CFLAliasAnalysis/phi-and-select.ll | 36 + test/Analysis/CFLAliasAnalysis/simple.ll | 18 + test/Analysis/CFLAliasAnalysis/va.ll | 29 + test/Analysis/CostModel/ARM/cast.ll | 112 +- test/Analysis/CostModel/PowerPC/cmp-expanded.ll | 14 + test/Analysis/CostModel/X86/cast.ll | 43 +- test/Analysis/CostModel/X86/cmp.ll | 11 + test/Analysis/CostModel/X86/sitofp.ll | 45 + test/Analysis/CostModel/X86/uitofp.ll | 12 +- .../NonCanonicalizedSubscript.ll | 40 + test/Analysis/Dominators/basic.ll | 60 + test/Analysis/GlobalsModRef/pr12351.ll | 4 +- .../ScalarEvolution/load-with-range-metadata.ll | 37 + test/Analysis/ScalarEvolution/nsw-offset-assume.ll | 83 + test/Analysis/ScalarEvolution/nsw.ll | 23 +- test/Analysis/ScalarEvolution/pr22179.ll | 28 + test/Analysis/ScalarEvolution/sext-iv-1.ll | 9 +- test/Analysis/ScopedNoAliasAA/basic-domains.ll | 57 + test/Analysis/ScopedNoAliasAA/basic.ll | 27 + test/Analysis/ScopedNoAliasAA/basic2.ll | 41 + test/Analysis/TypeBasedAliasAnalysis/PR17620.ll | 22 +- test/Analysis/TypeBasedAliasAnalysis/aliastest.ll | 24 +- .../TypeBasedAliasAnalysis/argument-promotion.ll | 10 +- test/Analysis/TypeBasedAliasAnalysis/dse.ll | 25 +- .../TypeBasedAliasAnalysis/dynamic-indices.ll | 24 +- .../TypeBasedAliasAnalysis/functionattrs.ll | 8 +- .../gvn-nonlocal-type-mismatch.ll | 32 +- test/Analysis/TypeBasedAliasAnalysis/intrinsics.ll | 10 +- test/Analysis/TypeBasedAliasAnalysis/licm.ll | 20 +- test/Analysis/TypeBasedAliasAnalysis/memcpyopt.ll | 14 +- .../TypeBasedAliasAnalysis/placement-tbaa.ll | 24 +- test/Analysis/TypeBasedAliasAnalysis/precedence.ll | 18 +- test/Analysis/TypeBasedAliasAnalysis/sink.ll | 14 +- test/Analysis/TypeBasedAliasAnalysis/tbaa-path.ll | 56 +- test/Assembler/2002-03-08-NameCollision.ll | 1 + test/Assembler/2002-03-08-NameCollision2.ll | 1 + test/Assembler/2002-04-07-HexFloatConstants.ll | 1 + test/Assembler/2002-04-07-InfConstant.ll | 1 + test/Assembler/2002-04-29-NameBinding.ll | 1 + test/Assembler/2002-05-02-InvalidForwardRef.ll | 1 + test/Assembler/2002-07-14-OpaqueType.ll | 1 + test/Assembler/2002-07-25-QuoteInString.ll | 1 + test/Assembler/2002-07-25-ReturnPtrFunction.ll | 1 + test/Assembler/2002-07-31-SlashInString.ll | 1 + test/Assembler/2002-08-15-CastAmbiguity.ll | 1 + test/Assembler/2002-08-15-ConstantExprProblem.ll | 1 + .../2002-08-15-UnresolvedGlobalReference.ll | 1 + test/Assembler/2002-08-16-ConstExprInlined.ll | 1 + test/Assembler/2002-08-19-BytecodeReader.ll | 1 + test/Assembler/2002-08-22-DominanceProblem.ll | 1 + test/Assembler/2002-10-08-LargeArrayPerformance.ll | 1 + .../2002-10-13-ConstantEncodingProblem.ll | 1 + test/Assembler/2002-12-15-GlobalResolve.ll | 1 + test/Assembler/2003-01-30-UnsignedString.ll | 1 + .../2003-04-25-UnresolvedGlobalReference.ll | 1 + test/Assembler/2003-05-03-BytecodeReaderProblem.ll | 1 + test/Assembler/2003-05-12-MinIntProblem.ll | 1 + test/Assembler/2003-05-15-AssemblerProblem.ll | 1 + test/Assembler/2003-05-15-SwitchBug.ll | 1 + test/Assembler/2003-05-21-ConstantShiftExpr.ll | 1 + test/Assembler/2003-05-21-EmptyStructTest.ll | 1 + test/Assembler/2003-08-20-ConstantExprGEP-Fold.ll | 1 + test/Assembler/2003-08-21-ConstantExprCast-Fold.ll | 1 + test/Assembler/2003-11-05-ConstantExprShift.ll | 1 + test/Assembler/2003-11-12-ConstantExprCast.ll | 1 + test/Assembler/2004-01-11-getelementptrfolding.ll | 1 + test/Assembler/2004-01-20-MaxLongLong.ll | 1 + test/Assembler/2004-02-01-NegativeZero.ll | 6 +- test/Assembler/2004-02-27-SelfUseAssertError.ll | 1 + .../2004-03-07-FunctionAddressAlignment.ll | 1 + .../2004-04-04-GetElementPtrIndexTypes.ll | 1 + test/Assembler/2004-06-07-VerifierBug.ll | 1 + test/Assembler/2004-10-22-BCWriterUndefBug.ll | 1 + test/Assembler/2004-11-28-InvalidTypeCrash.ll | 3 +- test/Assembler/2005-01-03-FPConstantDisassembly.ll | 4 +- .../2005-01-31-CallingAggregateFunction.ll | 1 + test/Assembler/2005-05-05-OpaqueUndefValues.ll | 1 + test/Assembler/2005-12-21-ZeroInitVector.ll | 1 + test/Assembler/2006-12-09-Cast-To-Bool.ll | 1 + test/Assembler/2007-01-02-Undefined-Arg-Type.ll | 4 +- test/Assembler/2007-01-05-Cmp-ConstExpr.ll | 1 + test/Assembler/2007-03-19-NegValue.ll | 4 +- test/Assembler/2007-04-20-AlignedLoad.ll | 1 + test/Assembler/2007-04-20-AlignedStore.ll | 1 + .../2007-04-25-AssemblerFoldExternWeak.ll | 5 +- test/Assembler/2007-05-21-Escape.ll | 1 + test/Assembler/2007-07-19-ParamAttrAmbiguity.ll | 1 + test/Assembler/2007-09-10-AliasFwdRef.ll | 3 +- test/Assembler/2007-09-29-GC.ll | 8 +- test/Assembler/2007-12-11-AddressSpaces.ll | 1 + test/Assembler/2008-01-11-VarargAttrs.ll | 1 + test/Assembler/2008-07-10-APInt.ll | 1 + test/Assembler/2008-09-02-FunctionNotes.ll | 1 + test/Assembler/2008-09-29-RetAttr.ll | 1 + test/Assembler/2008-10-14-QuoteInName.ll | 1 + test/Assembler/2009-02-01-UnnamedForwardRef.ll | 1 + test/Assembler/2009-02-28-CastOpc.ll | 1 + test/Assembler/2009-02-28-StripOpaqueName.ll | 1 + test/Assembler/2009-03-24-ZextConstantExpr.ll | 1 + test/Assembler/2009-07-24-ZeroArgGEP.ll | 1 + .../2010-02-05-FunctionLocalMetadataBecomesNull.ll | 31 +- test/Assembler/ConstantExprFold.ll | 1 + test/Assembler/ConstantExprFoldCast.ll | 1 + test/Assembler/ConstantExprFoldSelect.ll | 1 + test/Assembler/ConstantExprNoFold.ll | 24 + test/Assembler/MultipleReturnValueType.ll | 1 + test/Assembler/addrspacecast-alias.ll | 5 +- test/Assembler/aggregate-constant-values.ll | 1 + test/Assembler/aggregate-return-single-value.ll | 1 + test/Assembler/alias-use-list-order.ll | 11 + test/Assembler/align-inst.ll | 1 + test/Assembler/alignstack.ll | 1 + test/Assembler/anon-functions.ll | 1 + test/Assembler/atomic.ll | 1 + test/Assembler/auto_upgrade_intrinsics.ll | 1 + test/Assembler/bcwrap.ll | 1 + test/Assembler/comment.ll | 1 + test/Assembler/distinct-mdnode.ll | 28 + test/Assembler/externally-initialized.ll | 1 + test/Assembler/fast-math-flags.ll | 1 + test/Assembler/flags.ll | 1 + test/Assembler/functionlocal-metadata.ll | 67 +- test/Assembler/getelementptr.ll | 1 + test/Assembler/global-addrspace-forwardref.ll | 1 + test/Assembler/half-constprop.ll | 1 + test/Assembler/half-conv.ll | 1 + test/Assembler/half.ll | 1 + test/Assembler/huge-array.ll | 1 + test/Assembler/inalloca.ll | 3 +- test/Assembler/inline-asm-clobber.ll | 10 + test/Assembler/insertextractvalue.ll | 1 + test/Assembler/internal-hidden-alias.ll | 2 +- test/Assembler/internal-protected-alias.ll | 2 +- test/Assembler/invalid-attrgrp.ll | 4 + test/Assembler/invalid-comdat.ll | 2 +- test/Assembler/invalid-datalayout1.ll | 3 + test/Assembler/invalid-datalayout10.ll | 3 + test/Assembler/invalid-datalayout11.ll | 3 + test/Assembler/invalid-datalayout12.ll | 3 + test/Assembler/invalid-datalayout13.ll | 3 + test/Assembler/invalid-datalayout2.ll | 3 + test/Assembler/invalid-datalayout3.ll | 3 + test/Assembler/invalid-datalayout4.ll | 3 + test/Assembler/invalid-datalayout5.ll | 3 + test/Assembler/invalid-datalayout6.ll | 3 + test/Assembler/invalid-datalayout7.ll | 3 + test/Assembler/invalid-datalayout8.ll | 3 + test/Assembler/invalid-datalayout9.ll | 3 + test/Assembler/invalid-fwdref2.ll | 4 + test/Assembler/invalid-hexint.ll | 4 + test/Assembler/invalid-mdlocation-field-bad.ll | 4 + test/Assembler/invalid-mdlocation-field-twice.ll | 6 + .../invalid-mdlocation-overflow-column.ll | 9 + test/Assembler/invalid-mdlocation-overflow-line.ll | 9 + test/Assembler/invalid-mdnode-vector.ll | 4 + test/Assembler/invalid-mdnode-vector2.ll | 4 + .../invalid-metadata-attachment-has-type.ll | 8 + .../invalid-metadata-function-local-attachments.ll | 7 + .../invalid-metadata-function-local-complex-1.ll | 10 + .../invalid-metadata-function-local-complex-2.ll | 10 + .../invalid-metadata-function-local-complex-3.ll | 10 + test/Assembler/invalid-metadata-has-type.ll | 5 + test/Assembler/invalid-name.ll | Bin 117 -> 142 bytes test/Assembler/invalid-name2.ll | Bin 0 -> 120 bytes test/Assembler/invalid-specialized-mdnode.ll | 4 + ...invalid-uselistorder-function-between-blocks.ll | 37 + .../invalid-uselistorder-function-missing-named.ll | 6 + ...valid-uselistorder-function-missing-numbered.ll | 6 + .../invalid-uselistorder-global-missing.ll | 3 + .../invalid-uselistorder-indexes-duplicated.ll | 7 + .../invalid-uselistorder-indexes-empty.ll | 4 + test/Assembler/invalid-uselistorder-indexes-one.ll | 5 + .../invalid-uselistorder-indexes-ordered.ll | 7 + .../invalid-uselistorder-indexes-range.ll | 7 + .../invalid-uselistorder-indexes-toofew.ll | 7 + .../invalid-uselistorder-indexes-toomany.ll | 6 + test/Assembler/invalid-uselistorder-type.ll | 4 + .../invalid-uselistorder_bb-missing-bb.ll | 6 + .../invalid-uselistorder_bb-missing-body.ll | 4 + .../invalid-uselistorder_bb-missing-func.ll | 3 + test/Assembler/invalid-uselistorder_bb-not-bb.ll | 6 + test/Assembler/invalid-uselistorder_bb-not-func.ll | 4 + test/Assembler/invalid-uselistorder_bb-numbered.ll | 11 + test/Assembler/mdlocation.ll | 20 + test/Assembler/metadata.ll | 5 +- test/Assembler/musttail-invalid-1.ll | 14 + test/Assembler/musttail-invalid-2.ll | 13 + test/Assembler/musttail.ll | 14 + test/Assembler/named-metadata.ll | 7 +- test/Assembler/numbered-values.ll | 1 + test/Assembler/private-hidden-alias.ll | 2 +- test/Assembler/private-protected-alias.ll | 2 +- test/Assembler/select.ll | 1 + test/Assembler/short-hexpair.ll | 4 + test/Assembler/tls-models.ll | 1 + test/Assembler/unnamed-addr.ll | 1 + test/Assembler/unnamed-comdat.ll | 6 + test/Assembler/unnamed.ll | 1 + test/Assembler/upgrade-loop-metadata.ll | 17 +- test/Assembler/uselistorder.ll | 56 + test/Assembler/uselistorder_bb.ll | 42 + test/Assembler/vbool-cmp.ll | 1 + test/Assembler/vector-cmp.ll | 1 + test/Assembler/vector-select.ll | 1 + test/Assembler/vector-shift.ll | 1 + test/Assembler/x86mmx.ll | 1 + test/Bindings/Go/go.test | 3 + test/Bindings/Go/lit.local.cfg | 57 + test/Bindings/OCaml/analysis.ml | 54 + test/Bindings/OCaml/bitreader.ml | 79 + test/Bindings/OCaml/bitwriter.ml | 49 + test/Bindings/OCaml/core.ml | 1507 +++ test/Bindings/OCaml/executionengine.ml | 112 + test/Bindings/OCaml/ext_exc.ml | 22 + test/Bindings/OCaml/ipo.ml | 72 + test/Bindings/OCaml/irreader.ml | 59 + test/Bindings/OCaml/linker.ml | 63 + test/Bindings/OCaml/lit.local.cfg | 7 + test/Bindings/OCaml/passmgr_builder.ml | 64 + test/Bindings/OCaml/scalar_opts.ml | 92 + test/Bindings/OCaml/target.ml | 116 + test/Bindings/OCaml/transform_utils.ml | 21 + test/Bindings/OCaml/vectorize.ml | 56 + test/Bindings/Ocaml/analysis.ml | 54 - test/Bindings/Ocaml/bitreader.ml | 79 - test/Bindings/Ocaml/bitwriter.ml | 48 - test/Bindings/Ocaml/executionengine.ml | 118 - test/Bindings/Ocaml/ext_exc.ml | 20 - test/Bindings/Ocaml/ipo_opts.ml | 72 - test/Bindings/Ocaml/irreader.ml | 59 - test/Bindings/Ocaml/linker.ml | 63 - test/Bindings/Ocaml/lit.local.cfg | 5 - test/Bindings/Ocaml/passmgr_builder.ml | 64 - test/Bindings/Ocaml/scalar_opts.ml | 87 - test/Bindings/Ocaml/target.ml | 116 - test/Bindings/Ocaml/vectorize_opts.ml | 56 - test/Bindings/Ocaml/vmcore.ml | 1421 --- test/Bindings/llvm-c/disassemble.test | 26 +- test/Bindings/llvm-c/objectfile.ll | 2 + test/Bitcode/2006-12-11-Cast-ConstExpr.ll | 1 + .../2009-06-11-FirstClassAggregateConstant.ll | 1 + test/Bitcode/aggregateInstructions.3.2.ll | 67 +- test/Bitcode/arm32_neon_vcnt_upgrade.ll | 1 + test/Bitcode/atomic.ll | 3 +- test/Bitcode/attributes-3.3.ll | 1 + test/Bitcode/attributes.ll | 6 + test/Bitcode/binaryFloatInstructions.3.2.ll | 241 +- test/Bitcode/binaryIntInstructions.3.2.ll | 355 +- test/Bitcode/bitwiseInstructions.3.2.ll | 137 +- test/Bitcode/blockaddress.ll | 15 + test/Bitcode/calling-conventions.3.2.ll | 5 +- test/Bitcode/case-ranges-3.3.ll | 1 + test/Bitcode/cmpxchg-upgrade.ll | 3 +- test/Bitcode/constantsTest.3.2.ll | 124 + test/Bitcode/constantsTest.3.2.ll.bc | Bin 0 -> 900 bytes test/Bitcode/conversionInstructions.3.2.ll | 228 +- test/Bitcode/conversionInstructions.3.2.ll.bc | Bin 996 -> 1180 bytes ...eprecated-linker_private-linker_private_weak.ll | 17 - test/Bitcode/drop-debug-info.ll | 23 +- test/Bitcode/extractelement.ll | 1 + test/Bitcode/flags.ll | 1 + test/Bitcode/function-encoding-rel-operands.ll | 3 + test/Bitcode/function-local-metadata.3.5.ll | 35 + test/Bitcode/function-local-metadata.3.5.ll.bc | Bin 0 -> 396 bytes test/Bitcode/global-variables.3.2.ll | 1 + test/Bitcode/highLevelStructure.3.2.ll | 86 + test/Bitcode/highLevelStructure.3.2.ll.bc | Bin 0 -> 1220 bytes test/Bitcode/inalloca.ll | 1 + test/Bitcode/invalid.ll | 2 +- test/Bitcode/linkage-types-3.2.ll | 83 +- .../local-linkage-default-visibility.3.4.ll | 13 +- test/Bitcode/mdstring-high-bits.ll | 9 + test/Bitcode/memInstructions.3.2.ll | 657 +- test/Bitcode/metadata-2.ll | 5 +- test/Bitcode/metadata.3.5.ll | 26 + test/Bitcode/metadata.3.5.ll.bc | Bin 0 -> 432 bytes test/Bitcode/metadata.ll | 3 +- test/Bitcode/miscInstructions.3.2.ll | 312 +- test/Bitcode/miscInstructions.3.2.ll.bc | Bin 908 -> 1540 bytes test/Bitcode/old-aliases.ll | 1 + test/Bitcode/ptest-new.ll | 1 + test/Bitcode/ptest-old.ll | 1 + test/Bitcode/select.ll | 1 + test/Bitcode/shuffle.ll | 1 + test/Bitcode/ssse3_palignr.ll | 1 + test/Bitcode/standardCIntrinsic.3.2.ll | 16 + test/Bitcode/standardCIntrinsic.3.2.ll.bc | Bin 0 -> 444 bytes test/Bitcode/tailcall.ll | 1 + test/Bitcode/terminatorInstructions.3.2.ll | 123 +- test/Bitcode/terminatorInstructions.3.2.ll.bc | Bin 568 -> 816 bytes test/Bitcode/upgrade-global-ctors.ll | 4 +- test/Bitcode/upgrade-loop-metadata.ll | 7 +- test/Bitcode/upgrade-tbaa.ll | 19 +- test/Bitcode/use-list-order.ll | 168 + test/Bitcode/variableArgumentIntrinsic.3.2.ll | 67 +- test/Bitcode/vectorInstructions.3.2.ll | 67 +- test/Bitcode/visibility-styles.3.2.ll | 1 + test/Bitcode/weak-cmpxchg-upgrade.ll | 1 + test/BugPoint/metadata.ll | 38 +- test/CMakeLists.txt | 35 +- test/CodeGen/AArch64/PBQP-chain.ll | 104 + test/CodeGen/AArch64/PBQP-coalesce-benefit.ll | 14 + test/CodeGen/AArch64/PBQP-csr.ll | 91 + test/CodeGen/AArch64/PBQP.ll | 14 + test/CodeGen/AArch64/Redundantstore.ll | 25 + test/CodeGen/AArch64/a57-csel.ll | 11 + .../aarch64-2014-08-11-MachineCombinerCrash.ll | 106 + .../AArch64/aarch64-2014-12-02-combine-soften.ll | 16 + .../AArch64/aarch64-a57-fp-load-balancing.ll | 329 + test/CodeGen/AArch64/aarch64-be-bv.ll | 831 ++ .../AArch64/aarch64-fix-cortex-a53-835769.ll | 534 ++ test/CodeGen/AArch64/aarch64-gep-opt.ll | 163 + test/CodeGen/AArch64/aarch64-smull.ll | 332 + test/CodeGen/AArch64/aarch64-wide-shuffle.ll | 22 + test/CodeGen/AArch64/aarch64_f16_be.ll | 67 + test/CodeGen/AArch64/aarch64_tree_tests.ll | 42 + test/CodeGen/AArch64/adc.ll | 2 +- test/CodeGen/AArch64/analyze-branch.ll | 4 +- test/CodeGen/AArch64/analyzecmp.ll | 32 + test/CodeGen/AArch64/and-mask-removal.ll | 269 + test/CodeGen/AArch64/andandshift.ll | 28 + test/CodeGen/AArch64/argument-blocks.ll | 197 + .../AArch64/arm64-2011-03-17-AsmPrinterCrash.ll | 48 +- .../CodeGen/AArch64/arm64-2011-10-18-LdStOptBug.ll | 2 +- .../CodeGen/AArch64/arm64-2012-05-22-LdStOptBug.ll | 10 +- test/CodeGen/AArch64/arm64-2012-06-06-FPToUI.ll | 12 +- test/CodeGen/AArch64/arm64-AdvSIMD-Scalar.ll | 66 +- test/CodeGen/AArch64/arm64-EXT-undef-mask.ll | 2 +- test/CodeGen/AArch64/arm64-aapcs-be.ll | 40 + test/CodeGen/AArch64/arm64-aapcs.ll | 30 +- test/CodeGen/AArch64/arm64-abi.ll | 38 +- test/CodeGen/AArch64/arm64-abi_align.ll | 70 +- test/CodeGen/AArch64/arm64-addr-mode-folding.ll | 2 +- test/CodeGen/AArch64/arm64-addrmode.ll | 121 +- test/CodeGen/AArch64/arm64-atomic-128.ll | 24 +- test/CodeGen/AArch64/arm64-bcc.ll | 60 + .../AArch64/arm64-big-endian-bitconverts.ll | 4 +- test/CodeGen/AArch64/arm64-big-endian-eh.ll | 2 +- test/CodeGen/AArch64/arm64-big-endian-varargs.ll | 2 +- .../AArch64/arm64-big-endian-vector-callee.ll | 4 +- .../AArch64/arm64-big-endian-vector-caller.ll | 4 +- test/CodeGen/AArch64/arm64-ccmp-heuristics.ll | 8 +- test/CodeGen/AArch64/arm64-cse.ll | 2 +- .../AArch64/arm64-dagcombiner-dead-indexed-load.ll | 4 - .../AArch64/arm64-dagcombiner-indexed-load.ll | 46 - test/CodeGen/AArch64/arm64-extern-weak.ll | 19 +- .../CodeGen/AArch64/arm64-fast-isel-addr-offset.ll | 2 +- test/CodeGen/AArch64/arm64-fast-isel-alloca.ll | 7 +- test/CodeGen/AArch64/arm64-fast-isel-br.ll | 17 +- test/CodeGen/AArch64/arm64-fast-isel-call.ll | 231 +- test/CodeGen/AArch64/arm64-fast-isel-conversion.ll | 126 +- test/CodeGen/AArch64/arm64-fast-isel-fcmp.ll | 286 +- test/CodeGen/AArch64/arm64-fast-isel-gv.ll | 29 +- test/CodeGen/AArch64/arm64-fast-isel-icmp.ll | 179 +- test/CodeGen/AArch64/arm64-fast-isel-indirectbr.ll | 8 +- test/CodeGen/AArch64/arm64-fast-isel-intrinsic.ll | 4 +- .../CodeGen/AArch64/arm64-fast-isel-materialize.ll | 44 +- test/CodeGen/AArch64/arm64-fast-isel-noconvert.ll | 2 +- test/CodeGen/AArch64/arm64-fast-isel-rem.ll | 3 +- test/CodeGen/AArch64/arm64-fast-isel-ret.ll | 2 +- test/CodeGen/AArch64/arm64-fast-isel-select.ll | 63 - test/CodeGen/AArch64/arm64-fast-isel-store.ll | 30 + test/CodeGen/AArch64/arm64-fast-isel.ll | 8 +- test/CodeGen/AArch64/arm64-fastcc-tailcall.ll | 6 +- test/CodeGen/AArch64/arm64-fold-address.ll | 10 +- test/CodeGen/AArch64/arm64-frameaddr.ll | 15 - test/CodeGen/AArch64/arm64-indexed-memory.ll | 12 + .../CodeGen/AArch64/arm64-indexed-vector-ldst-2.ll | 8 +- test/CodeGen/AArch64/arm64-inline-asm.ll | 10 +- test/CodeGen/AArch64/arm64-named-reg-alloc.ll | 2 +- test/CodeGen/AArch64/arm64-named-reg-notareg.ll | 2 +- test/CodeGen/AArch64/arm64-neon-select_cc.ll | 15 + .../AArch64/arm64-patchpoint-scratch-regs.ll | 18 + .../AArch64/arm64-patchpoint-webkit_jscc.ll | 118 + test/CodeGen/AArch64/arm64-patchpoint.ll | 91 +- test/CodeGen/AArch64/arm64-popcnt.ll | 14 + test/CodeGen/AArch64/arm64-prefetch.ll | 63 +- test/CodeGen/AArch64/arm64-promote-const.ll | 15 +- test/CodeGen/AArch64/arm64-scaled_iv.ll | 2 +- test/CodeGen/AArch64/arm64-scvt.ll | 27 +- .../AArch64/arm64-setcc-int-to-fp-combine.ll | 22 +- test/CodeGen/AArch64/arm64-shifted-sext.ll | 4 +- test/CodeGen/AArch64/arm64-st1.ll | 192 + test/CodeGen/AArch64/arm64-stackmap-nops.ll | 15 + test/CodeGen/AArch64/arm64-stackmap.ll | 3 +- test/CodeGen/AArch64/arm64-stackpointer.ll | 2 +- test/CodeGen/AArch64/arm64-tls-dynamics.ll | 8 +- .../AArch64/arm64-triv-disjoint-mem-access.ll | 31 + test/CodeGen/AArch64/arm64-vabs.ll | 70 + test/CodeGen/AArch64/arm64-variadic-aapcs.ll | 16 +- test/CodeGen/AArch64/arm64-vector-ext.ll | 11 + test/CodeGen/AArch64/arm64-xaluo.ll | 305 +- test/CodeGen/AArch64/atomic-ops.ll | 8 +- test/CodeGen/AArch64/bitcast-v2i8.ll | 15 + test/CodeGen/AArch64/br-to-eh-lpad.ll | 78 + test/CodeGen/AArch64/br-undef-cond.ll | 26 + test/CodeGen/AArch64/cmp-const-max.ll | 36 + test/CodeGen/AArch64/cmpwithshort.ll | 46 + test/CodeGen/AArch64/combine-comparisons-by-cse.ll | 413 + test/CodeGen/AArch64/compiler-ident.ll | 2 +- test/CodeGen/AArch64/cond-sel.ll | 17 + test/CodeGen/AArch64/dag-combine-invaraints.ll | 36 + test/CodeGen/AArch64/dont-take-over-the-world.ll | 7 + test/CodeGen/AArch64/dp-3source.ll | 15 + test/CodeGen/AArch64/extern-weak.ll | 19 +- test/CodeGen/AArch64/fast-isel-addressing-modes.ll | 627 ++ .../CodeGen/AArch64/fast-isel-branch-cond-split.ll | 42 + test/CodeGen/AArch64/fast-isel-branch_weights.ll | 19 + test/CodeGen/AArch64/fast-isel-call-return.ll | 12 + test/CodeGen/AArch64/fast-isel-cbz.ll | 70 + test/CodeGen/AArch64/fast-isel-cmp-branch.ll | 293 + test/CodeGen/AArch64/fast-isel-folding.ll | 54 + test/CodeGen/AArch64/fast-isel-gep.ll | 49 + test/CodeGen/AArch64/fast-isel-int-ext.ll | 491 + test/CodeGen/AArch64/fast-isel-int-ext2.ll | 439 + test/CodeGen/AArch64/fast-isel-int-ext3.ll | 117 + test/CodeGen/AArch64/fast-isel-int-ext4.ll | 20 + test/CodeGen/AArch64/fast-isel-intrinsic.ll | 19 + test/CodeGen/AArch64/fast-isel-logic-op.ll | 362 + test/CodeGen/AArch64/fast-isel-memcpy.ll | 15 + test/CodeGen/AArch64/fast-isel-mul.ll | 60 +- test/CodeGen/AArch64/fast-isel-runtime-libcall.ll | 96 + test/CodeGen/AArch64/fast-isel-sdiv.ll | 56 + test/CodeGen/AArch64/fast-isel-select.ll | 316 + test/CodeGen/AArch64/fast-isel-shift.ll | 545 ++ test/CodeGen/AArch64/fast-isel-sqrt.ll | 20 + test/CodeGen/AArch64/fast-isel-switch-phi.ll | 25 + test/CodeGen/AArch64/fast-isel-tbz.ll | 295 + test/CodeGen/AArch64/fast-isel-trunc.ll | 12 + .../CodeGen/AArch64/fast-isel-vector-arithmetic.ll | 74 + test/CodeGen/AArch64/fast-isel-vret.ll | 9 + test/CodeGen/AArch64/fdiv-combine.ll | 94 + test/CodeGen/AArch64/fp16-instructions.ll | 109 + test/CodeGen/AArch64/fp16-v4-instructions.ll | 122 + test/CodeGen/AArch64/fp16-v8-instructions.ll | 255 + test/CodeGen/AArch64/fp16-vector-bitcast.ll | 203 + test/CodeGen/AArch64/fp16-vector-load-store.ll | 528 ++ test/CodeGen/AArch64/fp16-vector-shuffle.ll | 301 + test/CodeGen/AArch64/fpconv-vector-op-scalarize.ll | 44 + test/CodeGen/AArch64/fpimm.ll | 23 +- test/CodeGen/AArch64/frameaddr.ll | 29 +- test/CodeGen/AArch64/func-argpassing.ll | 10 +- test/CodeGen/AArch64/func-calls.ll | 14 +- test/CodeGen/AArch64/global-merge-1.ll | 1 + test/CodeGen/AArch64/global-merge-2.ll | 1 + test/CodeGen/AArch64/init-array.ll | 4 +- test/CodeGen/AArch64/jump-table.ll | 11 +- test/CodeGen/AArch64/legalize-bug-bogus-cpu.ll | 8 + test/CodeGen/AArch64/machine_cse.ll | 45 + .../AArch64/machine_cse_impdef_killflags.ll | 26 + test/CodeGen/AArch64/madd-combiner.ll | 37 + test/CodeGen/AArch64/madd-lohi.ll | 19 + test/CodeGen/AArch64/mul-lohi.ll | 13 +- test/CodeGen/AArch64/neon-perm.ll | 7 + test/CodeGen/AArch64/paired-load.ll | 16 + test/CodeGen/AArch64/pic-eh-stubs.ll | 2 +- test/CodeGen/AArch64/postra-mi-sched.ll | 31 + test/CodeGen/AArch64/ragreedy-csr.ll | 48 +- test/CodeGen/AArch64/remat.ll | 16 + test/CodeGen/AArch64/rm_redundant_cmp.ll | 254 + test/CodeGen/AArch64/sdivpow2.ll | 74 + test/CodeGen/AArch64/stack-guard-remat-bitcast.ll | 26 + test/CodeGen/AArch64/stack_guard_remat.ll | 48 + test/CodeGen/AArch64/tail-call.ll | 11 + test/CodeGen/AArch64/tailcall-fastisel.ll | 11 + test/CodeGen/AArch64/tbz-tbnz.ll | 258 + test/CodeGen/AArch64/trunc-v1i64.ll | 21 +- test/CodeGen/ARM/2007-05-07-tailmerge-1.ll | 11 +- test/CodeGen/ARM/2007-05-09-tailmerge-2.ll | 9 +- test/CodeGen/ARM/2007-05-22-tailmerge-3.ll | 23 +- test/CodeGen/ARM/2009-10-16-Scope.ll | 24 +- test/CodeGen/ARM/2009-10-21-InvalidFNeg.ll | 48 - test/CodeGen/ARM/2010-04-15-ScavengerDebugValue.ll | 36 +- .../ARM/2010-06-25-Thumb2ITInvalidIterator.ll | 64 +- test/CodeGen/ARM/2010-08-04-StackVariable.ll | 114 +- test/CodeGen/ARM/2010-11-15-SpillEarlyClobber.ll | 3 +- test/CodeGen/ARM/2011-01-19-MergedGlobalDbg.ll | 154 +- test/CodeGen/ARM/2011-04-12-AlignBug.ll | 5 +- test/CodeGen/ARM/2011-04-12-FastRegAlloc.ll | 2 +- .../ARM/2011-05-04-MultipleLandingPadSuccs.ll | 10 +- test/CodeGen/ARM/2011-08-02-MergedGlobalDbg.ll | 153 +- test/CodeGen/ARM/2012-04-24-SplitEHCriticalEdge.ll | 8 +- test/CodeGen/ARM/2012-08-04-DtripleSpillReload.ll | 2 +- .../ARM/2012-09-25-InlineAsmScalarToVectorConv.ll | 2 +- .../ARM/2012-09-25-InlineAsmScalarToVectorConv2.ll | 2 +- .../ARM/2014-07-18-earlyclobber-str-post.ll | 22 +- test/CodeGen/ARM/2014-08-04-muls-it.ll | 25 + test/CodeGen/ARM/aapcs-hfa-code.ll | 25 +- test/CodeGen/ARM/adv-copy-opt.ll | 38 + test/CodeGen/ARM/aliases.ll | 4 +- test/CodeGen/ARM/alloc-no-stack-realign.ll | 78 +- test/CodeGen/ARM/arm-abi-attr.ll | 10 +- test/CodeGen/ARM/arm32-round-conv.ll | 117 + test/CodeGen/ARM/arm32-rounding.ll | 118 + test/CodeGen/ARM/atomic-64bit.ll | 2 +- test/CodeGen/ARM/atomic-cmpxchg.ll | 7 +- test/CodeGen/ARM/atomic-load-store.ll | 23 + test/CodeGen/ARM/atomic-op.ll | 140 +- test/CodeGen/ARM/build-attributes-encoding.s | 2 +- test/CodeGen/ARM/build-attributes.ll | 606 +- test/CodeGen/ARM/carry.ll | 2 +- test/CodeGen/ARM/coalesce-dbgvalue.ll | 66 +- test/CodeGen/ARM/constant-islands.ll | 25 + test/CodeGen/ARM/copy-cpsr.ll | 41 + test/CodeGen/ARM/crc32.ll | 58 + test/CodeGen/ARM/cse-ldrlit.ll | 4 +- test/CodeGen/ARM/cse-libcalls.ll | 6 +- test/CodeGen/ARM/dagcombine-concatvector.ll | 2 +- test/CodeGen/ARM/darwin-eabi.ll | 6 +- test/CodeGen/ARM/dbg.ll | 13 + test/CodeGen/ARM/debug-frame-large-stack.ll | 21 +- test/CodeGen/ARM/debug-frame-vararg.ll | 68 +- test/CodeGen/ARM/debug-frame.ll | 70 +- test/CodeGen/ARM/debug-info-arg.ll | 82 +- test/CodeGen/ARM/debug-info-blocks.ll | 350 +- test/CodeGen/ARM/debug-info-branch-folding.ll | 122 +- test/CodeGen/ARM/debug-info-d16-reg.ll | 124 +- test/CodeGen/ARM/debug-info-qreg.ll | 124 +- test/CodeGen/ARM/debug-info-s16-reg.ll | 137 +- test/CodeGen/ARM/debug-info-sreg2.ll | 69 +- test/CodeGen/ARM/debug-segmented-stacks.ll | 70 +- test/CodeGen/ARM/dwarf-unwind.ll | 82 + test/CodeGen/ARM/emit-big-cst.ll | 2 +- test/CodeGen/ARM/fabs-neon.ll | 39 + test/CodeGen/ARM/fast-isel-call.ll | 21 +- test/CodeGen/ARM/fast-isel-deadcode.ll | 1 - test/CodeGen/ARM/fast-isel-intrinsic.ll | 4 - test/CodeGen/ARM/fast-isel-mvn.ll | 85 +- test/CodeGen/ARM/fast-isel-select.ll | 10 +- test/CodeGen/ARM/fast-isel-vararg.ll | 1 - test/CodeGen/ARM/fnegs.ll | 51 +- test/CodeGen/ARM/fold-stack-adjust.ll | 9 +- test/CodeGen/ARM/fp16.ll | 31 +- test/CodeGen/ARM/fpcmp-f64-neon-opt.ll | 12 + test/CodeGen/ARM/ghc-tcreturn-lowered.ll | 10 +- test/CodeGen/ARM/global-merge-1.ll | 10 +- test/CodeGen/ARM/globals.ll | 1 + test/CodeGen/ARM/ifcvt-branch-weight-bug.ll | 4 +- test/CodeGen/ARM/ifcvt-branch-weight.ll | 4 +- test/CodeGen/ARM/inline-diagnostics.ll | 2 +- test/CodeGen/ARM/inlineasm-global.ll | 13 + test/CodeGen/ARM/interrupt-attr.ll | 16 +- test/CodeGen/ARM/invalid-target.ll | 32 + test/CodeGen/ARM/isel-v8i32-crash.ll | 26 + test/CodeGen/ARM/jump_tables.ll | 32 - test/CodeGen/ARM/memcpy-inline.ll | 15 +- test/CodeGen/ARM/metadata-default.ll | 4 +- test/CodeGen/ARM/metadata-short-enums.ll | 4 +- test/CodeGen/ARM/metadata-short-wchar.ll | 4 +- test/CodeGen/ARM/named-reg-alloc.ll | 2 +- test/CodeGen/ARM/named-reg-notareg.ll | 2 +- test/CodeGen/ARM/negative-offset.ll | 17 + test/CodeGen/ARM/no-tail-call.ll | 84 + test/CodeGen/ARM/none-macho-v4t.ll | 25 + test/CodeGen/ARM/none-macho.ll | 2 +- test/CodeGen/ARM/out-of-registers.ll | 4 +- test/CodeGen/ARM/pr18364-movw.ll | 34 + test/CodeGen/ARM/preferred-align.ll | 21 + test/CodeGen/ARM/prefetch.ll | 2 +- test/CodeGen/ARM/sbfx.ll | 18 + test/CodeGen/ARM/select_xform.ll | 107 + test/CodeGen/ARM/smulw.ll | 26 + test/CodeGen/ARM/space-directive.ll | 19 + test/CodeGen/ARM/spill-q.ll | 2 +- test/CodeGen/ARM/stack-alignment.ll | 164 + test/CodeGen/ARM/stack_guard_remat.ll | 70 + test/CodeGen/ARM/stackpointer.ll | 2 +- test/CodeGen/ARM/swift-atomics.ll | 6 + test/CodeGen/ARM/sxt_rot.ll | 3 +- test/CodeGen/ARM/tail-call-weak.ll | 19 + test/CodeGen/ARM/tail-call.ll | 15 +- test/CodeGen/ARM/tail-merge-branch-weight.ll | 44 + test/CodeGen/ARM/taildup-branch-weight.ll | 4 +- test/CodeGen/ARM/thumb1-varalloc.ll | 105 +- test/CodeGen/ARM/thumb1_return_sequence.ll | 217 + test/CodeGen/ARM/thumb2-it-block.ll | 25 +- test/CodeGen/ARM/thumb2-size-opt.ll | 84 + test/CodeGen/ARM/thumb_indirect_calls.ll | 40 + test/CodeGen/ARM/tls1.ll | 14 +- test/CodeGen/ARM/vararg_no_start.ll | 10 + test/CodeGen/ARM/varargs-spill-stack-align-nacl.ll | 4 +- test/CodeGen/ARM/vargs_align.ll | 3 + test/CodeGen/ARM/vector-load.ll | 253 + test/CodeGen/ARM/vector-promotion.ll | 403 + test/CodeGen/ARM/vector-store.ll | 258 + test/CodeGen/ARM/vfp-regs-dwarf.ll | 20 +- test/CodeGen/ARM/vld1.ll | 9 + test/CodeGen/ARM/vldm-sched-a9.ll | 4 +- test/CodeGen/ARM/vminmaxnm.ll | 68 +- test/CodeGen/ARM/vst1.ll | 10 + test/CodeGen/ARM/wrong-t2stmia-size-opt.ll | 20 + test/CodeGen/Generic/2009-03-17-LSR-APInt.ll | 28 +- .../CodeGen/Generic/2011-07-07-ScheduleDAGCrash.ll | 3 - test/CodeGen/Generic/MachineBranchProb.ll | 2 +- test/CodeGen/Generic/PBQP.ll | 29 + test/CodeGen/Generic/assume.ll | 9 + test/CodeGen/Generic/dbg_value.ll | 6 +- test/CodeGen/Generic/empty-insertvalue.ll | 7 + test/CodeGen/Generic/empty-phi.ll | 19 + test/CodeGen/Generic/print-machineinstrs.ll | 2 +- test/CodeGen/Hexagon/BranchPredict.ll | 4 +- test/CodeGen/Hexagon/block-addr.ll | 2 +- test/CodeGen/Hexagon/cext-check.ll | 8 +- test/CodeGen/Hexagon/cmp-not.ll | 50 + test/CodeGen/Hexagon/ctor.ll | 14 + test/CodeGen/Hexagon/hwloop-dbg.ll | 62 +- test/CodeGen/Hexagon/idxload-with-zero-offset.ll | 12 +- test/CodeGen/Hexagon/newvaluestore.ll | 2 +- test/CodeGen/Hexagon/pred-absolute-store.ll | 2 +- test/CodeGen/Hexagon/struct_args_large.ll | 2 +- test/CodeGen/Inputs/DbgValueOtherTargets.ll | 34 +- test/CodeGen/MSP430/asm-clobbers.ll | 13 + test/CodeGen/MSP430/memset.ll | 22 + test/CodeGen/Mips/Fast-ISel/br1.ll | 34 + test/CodeGen/Mips/Fast-ISel/callabi.ll | 477 + test/CodeGen/Mips/Fast-ISel/fpcmpa.ll | 254 + test/CodeGen/Mips/Fast-ISel/fpext.ll | 21 + test/CodeGen/Mips/Fast-ISel/fpintconv.ll | 35 + test/CodeGen/Mips/Fast-ISel/fptrunc.ll | 20 + test/CodeGen/Mips/Fast-ISel/icmpa.ll | 210 + test/CodeGen/Mips/Fast-ISel/loadstore2.ll | 2 + test/CodeGen/Mips/Fast-ISel/loadstoreconv.ll | 179 + test/CodeGen/Mips/Fast-ISel/loadstrconst.ll | 21 + test/CodeGen/Mips/Fast-ISel/nullvoid.ll | 2 + test/CodeGen/Mips/Fast-ISel/shift.ll | 24 + test/CodeGen/Mips/Fast-ISel/simplestore.ll | 2 + test/CodeGen/Mips/Fast-ISel/simplestorefp1.ll | 34 +- test/CodeGen/Mips/Fast-ISel/simplestorei.ll | 2 + test/CodeGen/Mips/atomic.ll | 53 +- test/CodeGen/Mips/brsize3.ll | 2 +- test/CodeGen/Mips/brsize3a.ll | 2 +- test/CodeGen/Mips/ci2.ll | 2 +- test/CodeGen/Mips/cmov.ll | 27 +- test/CodeGen/Mips/const1.ll | 2 +- test/CodeGen/Mips/const4a.ll | 2 +- test/CodeGen/Mips/const6.ll | 2 +- test/CodeGen/Mips/const6a.ll | 2 +- test/CodeGen/Mips/ctlz-v.ll | 19 + test/CodeGen/Mips/cttz-v.ll | 39 + test/CodeGen/Mips/fp16instrinsmc.ll | 2 +- test/CodeGen/Mips/fptr2.ll | 20 - test/CodeGen/Mips/gpreg-lazy-binding.ll | 8 + test/CodeGen/Mips/hfptrcall.ll | 4 +- test/CodeGen/Mips/init-array.ll | 2 +- .../CodeGen/Mips/inlineasm-assembler-directives.ll | 23 + test/CodeGen/Mips/inlineasm-cnstrnt-reg.ll | 6 +- test/CodeGen/Mips/inlineasmmemop.ll | 35 +- test/CodeGen/Mips/lcb2.ll | 22 +- test/CodeGen/Mips/lcb3c.ll | 4 +- test/CodeGen/Mips/lcb4a.ll | 16 +- test/CodeGen/Mips/lcb5.ll | 36 +- test/CodeGen/Mips/llvm-ir/mul.ll | 181 + test/CodeGen/Mips/llvm-ir/select.ll | 702 ++ test/CodeGen/Mips/longbranch.ll | 2 +- test/CodeGen/Mips/mbrsize4a.ll | 2 +- test/CodeGen/Mips/micromips-addiu.ll | 32 + test/CodeGen/Mips/micromips-andi.ll | 25 + test/CodeGen/Mips/micromips-atomic.ll | 2 +- test/CodeGen/Mips/micromips-atomic1.ll | 29 + test/CodeGen/Mips/micromips-compact-branches.ll | 19 + test/CodeGen/Mips/micromips-delay-slot-jr.ll | 48 + test/CodeGen/Mips/micromips-delay-slot.ll | 18 + test/CodeGen/Mips/micromips-li.ll | 18 + test/CodeGen/Mips/micromips-rdhwr-directives.ll | 15 + test/CodeGen/Mips/micromips-shift.ll | 44 + test/CodeGen/Mips/mips16-hf-attr-2.ll | 45 + test/CodeGen/Mips/mips16-hf-attr.ll | 12 +- test/CodeGen/Mips/mips64-f128.ll | 2 +- test/CodeGen/Mips/msa/arithmetic_float.ll | 10 +- test/CodeGen/Mips/named-register-n32.ll | 18 + test/CodeGen/Mips/named-register-n64.ll | 17 + test/CodeGen/Mips/named-register-o32.ll | 17 + test/CodeGen/Mips/nomips16.ll | 4 +- test/CodeGen/Mips/octeon.ll | 66 + test/CodeGen/Mips/powif64_16.ll | 8 +- test/CodeGen/Mips/prevent-hoisting.ll | 11 +- test/CodeGen/Mips/seleq.ll | 2 +- test/CodeGen/Mips/small-section-reserve-gp.ll | 2 +- test/CodeGen/Mips/start-asm-file.ll | 3 - test/CodeGen/NVPTX/annotations.ll | 29 +- test/CodeGen/NVPTX/bug21465.ll | 24 + test/CodeGen/NVPTX/call-with-alloca-buffer.ll | 2 +- test/CodeGen/NVPTX/calling-conv.ll | 2 +- test/CodeGen/NVPTX/fma-assoc.ll | 25 + test/CodeGen/NVPTX/fma.ll | 25 + test/CodeGen/NVPTX/generic-to-nvvm.ll | 2 +- test/CodeGen/NVPTX/i1-global.ll | 2 +- test/CodeGen/NVPTX/i1-param.ll | 2 +- test/CodeGen/NVPTX/ldu-i8.ll | 6 +- test/CodeGen/NVPTX/ldu-ldg.ll | 20 +- test/CodeGen/NVPTX/ldu-reg-plus-offset.ll | 8 +- test/CodeGen/NVPTX/machine-sink.ll | 40 + test/CodeGen/NVPTX/managed.ll | 2 +- test/CodeGen/NVPTX/mulwide.ll | 44 + test/CodeGen/NVPTX/noduplicate-syncthreads.ll | 4 +- test/CodeGen/NVPTX/nvcl-param-align.ll | 16 + test/CodeGen/NVPTX/refl1.ll | 2 +- test/CodeGen/NVPTX/simple-call.ll | 2 +- test/CodeGen/NVPTX/surf-read-cuda.ll | 6 +- test/CodeGen/NVPTX/surf-read.ll | 4 +- test/CodeGen/NVPTX/surf-write-cuda.ll | 6 +- test/CodeGen/NVPTX/surf-write.ll | 4 +- test/CodeGen/NVPTX/tex-read-cuda.ll | 6 +- test/CodeGen/NVPTX/tex-read.ll | 6 +- test/CodeGen/NVPTX/texsurf-queries.ll | 4 +- test/CodeGen/NVPTX/vector-global.ll | 9 + test/CodeGen/NVPTX/vector-return.ll | 14 + test/CodeGen/NVPTX/weak-linkage.ll | 8 +- test/CodeGen/PowerPC/2007-03-24-cntlzd.ll | 10 +- test/CodeGen/PowerPC/2007-09-08-unaligned.ll | 8 +- test/CodeGen/PowerPC/2011-12-05-NoSpillDupCR.ll | 2 +- .../PowerPC/2011-12-06-SpillAndRestoreCR.ll | 2 +- test/CodeGen/PowerPC/2012-10-12-bitcast.ll | 7 +- test/CodeGen/PowerPC/Atomics-32.ll | 715 -- test/CodeGen/PowerPC/Frames-large.ll | 9 +- test/CodeGen/PowerPC/aa-tbaa.ll | 6 +- test/CodeGen/PowerPC/add-fi.ll | 24 + test/CodeGen/PowerPC/addi-licm.ll | 55 + test/CodeGen/PowerPC/arr-fp-arg-no-copy.ll | 23 + test/CodeGen/PowerPC/asm-Zy.ll | 2 +- test/CodeGen/PowerPC/asm-constraints.ll | 45 + test/CodeGen/PowerPC/atomic-2.ll | 11 +- test/CodeGen/PowerPC/atomics-fences.ll | 29 + test/CodeGen/PowerPC/atomics-indexed.ll | 81 + test/CodeGen/PowerPC/atomics.ll | 137 + test/CodeGen/PowerPC/bperm.ll | 279 + test/CodeGen/PowerPC/buildvec_canonicalize.ll | 2 +- test/CodeGen/PowerPC/byval-aliased.ll | 30 + test/CodeGen/PowerPC/cmpb-ppc32.ll | 50 + test/CodeGen/PowerPC/cmpb.ll | 204 + test/CodeGen/PowerPC/code-align.ll | 104 + test/CodeGen/PowerPC/complex-return.ll | 4 +- test/CodeGen/PowerPC/constants-i64.ll | 84 + test/CodeGen/PowerPC/copysignl.ll | 18 +- test/CodeGen/PowerPC/crsave.ll | 4 +- test/CodeGen/PowerPC/ctrloops.ll | 25 +- test/CodeGen/PowerPC/cttz-ctlz-spec.ll | 41 + test/CodeGen/PowerPC/dbg.ll | 46 +- test/CodeGen/PowerPC/early-ret2.ll | 2 +- test/CodeGen/PowerPC/empty-functions.ll | 43 +- test/CodeGen/PowerPC/fabs.ll | 2 +- test/CodeGen/PowerPC/fast-isel-call.ll | 12 +- test/CodeGen/PowerPC/fast-isel-cmp-imm.ll | 7 +- test/CodeGen/PowerPC/fast-isel-const.ll | 27 + test/CodeGen/PowerPC/fast-isel-conversion.ll | 10 +- test/CodeGen/PowerPC/fast-isel-load-store.ll | 6 +- test/CodeGen/PowerPC/fast-isel-ret.ll | 6 +- test/CodeGen/PowerPC/fcpsgn.ll | 15 +- test/CodeGen/PowerPC/fdiv-combine.ll | 39 + test/CodeGen/PowerPC/fma-assoc.ll | 79 + test/CodeGen/PowerPC/fma-ext.ll | 93 + test/CodeGen/PowerPC/fma-mutate.ll | 21 + test/CodeGen/PowerPC/fma.ll | 59 +- test/CodeGen/PowerPC/fmaxnum.ll | 86 + test/CodeGen/PowerPC/fminnum.ll | 86 + test/CodeGen/PowerPC/fnabs.ll | 2 +- test/CodeGen/PowerPC/fp-branch.ll | 2 +- test/CodeGen/PowerPC/fp-to-int-ext.ll | 69 + test/CodeGen/PowerPC/fp-to-int-to-fp.ll | 70 + test/CodeGen/PowerPC/fp_to_uint.ll | 3 +- test/CodeGen/PowerPC/fsel.ll | 47 +- test/CodeGen/PowerPC/fsqrt.ll | 8 +- test/CodeGen/PowerPC/glob-comp-aa-crash.ll | 14 +- test/CodeGen/PowerPC/i1-ext-fold.ll | 54 + test/CodeGen/PowerPC/i64_fp.ll | 16 +- test/CodeGen/PowerPC/ia-neg-const.ll | 4 +- test/CodeGen/PowerPC/in-asm-f64-reg.ll | 2 +- test/CodeGen/PowerPC/inlineasm-i64-reg.ll | 2 +- test/CodeGen/PowerPC/lbz-from-ld-shift.ll | 18 + test/CodeGen/PowerPC/ld-st-upd.ll | 19 + test/CodeGen/PowerPC/mcm-10.ll | 3 +- test/CodeGen/PowerPC/mcm-12.ll | 10 +- test/CodeGen/PowerPC/mcm-2.ll | 6 +- test/CodeGen/PowerPC/mcm-4.ll | 20 +- test/CodeGen/PowerPC/mult-alt-generic-powerpc.ll | 2 +- test/CodeGen/PowerPC/mult-alt-generic-powerpc64.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r0.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r1-64.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r1.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r13-64.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r13.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r2-64.ll | 2 +- test/CodeGen/PowerPC/named-reg-alloc-r2.ll | 2 +- test/CodeGen/PowerPC/no-extra-fp-conv-ldst.ll | 96 + test/CodeGen/PowerPC/post-ra-ec.ll | 47 + test/CodeGen/PowerPC/ppc32-cyclecounter.ll | 20 + test/CodeGen/PowerPC/ppc32-lshrti3.ll | 2 +- test/CodeGen/PowerPC/ppc32-pic-large.ll | 29 + test/CodeGen/PowerPC/ppc32-pic.ll | 35 +- test/CodeGen/PowerPC/ppc440-msync.ll | 1 + test/CodeGen/PowerPC/ppc64-align-long-double.ll | 12 +- test/CodeGen/PowerPC/ppc64-anyregcc-crash.ll | 19 + test/CodeGen/PowerPC/ppc64-anyregcc.ll | 367 + test/CodeGen/PowerPC/ppc64-calls.ll | 19 +- test/CodeGen/PowerPC/ppc64-elf-abi.ll | 10 + test/CodeGen/PowerPC/ppc64-gep-opt.ll | 157 + test/CodeGen/PowerPC/ppc64-nonfunc-calls.ll | 69 + test/CodeGen/PowerPC/ppc64-patchpoint.ll | 93 + test/CodeGen/PowerPC/ppc64-prefetch.ll | 25 +- test/CodeGen/PowerPC/ppc64-stackmap-nops.ll | 24 + test/CodeGen/PowerPC/ppc64-stackmap.ll | 289 + test/CodeGen/PowerPC/ppc64-vaarg-int.ll | 2 +- test/CodeGen/PowerPC/ppc64le-aggregates.ll | 6 +- test/CodeGen/PowerPC/ppcf128-1.ll | 2 +- test/CodeGen/PowerPC/ppcf128-endian.ll | 2 +- test/CodeGen/PowerPC/pr15630.ll | 3 +- test/CodeGen/PowerPC/pr17168.ll | 934 +- test/CodeGen/PowerPC/recipest.ll | 124 +- test/CodeGen/PowerPC/retaddr2.ll | 25 + test/CodeGen/PowerPC/rlwimi-and.ll | 6 +- test/CodeGen/PowerPC/rlwimi2.ll | 4 +- test/CodeGen/PowerPC/rm-zext.ll | 89 + test/CodeGen/PowerPC/rounding-ops.ll | 19 +- test/CodeGen/PowerPC/sdiv-pow2.ll | 67 + test/CodeGen/PowerPC/sections.ll | 5 - test/CodeGen/PowerPC/split-index-tc.ll | 82 + test/CodeGen/PowerPC/subsumes-pred-regs.ll | 2 +- test/CodeGen/PowerPC/toc-load-sched-bug.ll | 96 +- test/CodeGen/PowerPC/unal-altivec-wint.ll | 48 + test/CodeGen/PowerPC/unal4-std.ll | 6 +- test/CodeGen/PowerPC/unaligned.ll | 34 +- test/CodeGen/PowerPC/unsafe-math.ll | 4 +- test/CodeGen/PowerPC/unwind-dw2-g.ll | 24 +- test/CodeGen/PowerPC/vec-abi-align.ll | 21 +- test/CodeGen/PowerPC/vec_misaligned.ll | 4 +- test/CodeGen/PowerPC/vec_mul.ll | 33 +- test/CodeGen/PowerPC/vec_shuffle_le.ll | 2 +- test/CodeGen/PowerPC/vrspill.ll | 10 +- test/CodeGen/PowerPC/vsx-args.ll | 1 + test/CodeGen/PowerPC/vsx-div.ll | 29 + test/CodeGen/PowerPC/vsx-fma-m.ll | 122 +- test/CodeGen/PowerPC/vsx-ldst-builtin-le.ll | 172 + test/CodeGen/PowerPC/vsx-ldst.ll | 46 + test/CodeGen/PowerPC/vsx-minmax.ll | 98 + test/CodeGen/PowerPC/vsx-p8.ll | 55 + test/CodeGen/PowerPC/vsx-self-copy.ll | 1 + test/CodeGen/PowerPC/vsx-spill.ll | 31 +- test/CodeGen/PowerPC/vsx.ll | 531 +- test/CodeGen/PowerPC/vsx_insert_extract_le.ll | 52 + test/CodeGen/PowerPC/vsx_shuffle_le.ll | 207 + test/CodeGen/PowerPC/zext-free.ll | 37 + test/CodeGen/R600/128bit-kernel-args.ll | 16 +- test/CodeGen/R600/32-bit-local-address-space.ll | 90 +- test/CodeGen/R600/64bit-kernel-args.ll | 10 +- test/CodeGen/R600/add-debug.ll | 23 + test/CodeGen/R600/add.ll | 98 +- test/CodeGen/R600/add_i64.ll | 54 +- test/CodeGen/R600/address-space.ll | 12 +- test/CodeGen/R600/and.ll | 97 +- test/CodeGen/R600/anyext.ll | 6 +- test/CodeGen/R600/array-ptr-calc-i32.ll | 14 +- test/CodeGen/R600/array-ptr-calc-i64.ll | 13 +- test/CodeGen/R600/atomic_cmp_swap_local.ll | 88 +- test/CodeGen/R600/atomic_load_add.ll | 18 +- test/CodeGen/R600/atomic_load_sub.ll | 18 +- test/CodeGen/R600/basic-branch.ll | 4 +- test/CodeGen/R600/basic-loop.ll | 4 +- test/CodeGen/R600/bfe_uint.ll | 4 +- test/CodeGen/R600/bfi_int.ll | 16 +- test/CodeGen/R600/big_alu.ll | 1 - test/CodeGen/R600/bitcast.ll | 18 +- test/CodeGen/R600/bswap.ll | 66 +- test/CodeGen/R600/build_vector.ll | 26 +- test/CodeGen/R600/call.ll | 4 +- test/CodeGen/R600/call_fs.ll | 4 +- test/CodeGen/R600/cayman-loop-bug.ll | 2 +- test/CodeGen/R600/cf-stack-bug.ll | 8 +- test/CodeGen/R600/codegen-prepare-addrmode-sext.ll | 11 +- test/CodeGen/R600/combine_vloads.ll | 2 +- test/CodeGen/R600/commute_modifiers.ll | 181 + test/CodeGen/R600/complex-folding.ll | 2 +- test/CodeGen/R600/concat_vectors.ll | 161 +- test/CodeGen/R600/copy-illegal-type.ll | 180 +- test/CodeGen/R600/copy-to-reg.ll | 26 + test/CodeGen/R600/ctlz_zero_undef.ll | 52 +- test/CodeGen/R600/ctpop.ll | 231 +- test/CodeGen/R600/ctpop64.ll | 111 +- test/CodeGen/R600/cttz-ctlz.ll | 224 + test/CodeGen/R600/cttz_zero_undef.ll | 52 +- test/CodeGen/R600/cvt_f32_ubyte.ll | 188 +- .../R600/dagcombiner-bug-illegal-vec4-int-to-fp.ll | 4 +- test/CodeGen/R600/default-fp-mode.ll | 16 +- .../CodeGen/R600/disconnected-predset-break-bug.ll | 2 +- test/CodeGen/R600/dot4-folding.ll | 2 +- .../ds-negative-offset-addressing-mode-loop.ll | 69 + test/CodeGen/R600/ds_read2.ll | 515 ++ test/CodeGen/R600/ds_read2_offset_order.ll | 44 + test/CodeGen/R600/ds_read2st64.ll | 272 + test/CodeGen/R600/ds_write2.ll | 425 + test/CodeGen/R600/ds_write2st64.ll | 119 + test/CodeGen/R600/elf.ll | 10 +- test/CodeGen/R600/empty-function.ll | 20 + test/CodeGen/R600/extload.ll | 79 +- test/CodeGen/R600/extract_vector_elt_i16.ll | 22 +- test/CodeGen/R600/fabs.f64.ll | 97 + test/CodeGen/R600/fabs.ll | 123 +- test/CodeGen/R600/fadd.ll | 93 +- test/CodeGen/R600/fadd64.ll | 6 +- test/CodeGen/R600/fceil.ll | 82 +- test/CodeGen/R600/fceil64.ll | 121 +- test/CodeGen/R600/fcmp.ll | 4 +- test/CodeGen/R600/fcmp64.ll | 56 +- test/CodeGen/R600/fconst64.ll | 8 +- test/CodeGen/R600/fcopysign.f32.ll | 28 +- test/CodeGen/R600/fcopysign.f64.ll | 30 +- test/CodeGen/R600/fdiv.ll | 36 +- test/CodeGen/R600/fdiv64.ll | 8 +- test/CodeGen/R600/fetch-limits.r600.ll | 2 +- test/CodeGen/R600/fetch-limits.r700+.ll | 2 +- test/CodeGen/R600/ffloor.ll | 121 +- test/CodeGen/R600/flat-address-space.ll | 182 + test/CodeGen/R600/fma.f64.ll | 46 + test/CodeGen/R600/fma.ll | 137 +- test/CodeGen/R600/fmax3.ll | 38 + test/CodeGen/R600/fmax_legacy.f64.ll | 67 + test/CodeGen/R600/fmax_legacy.ll | 116 + test/CodeGen/R600/fmaxnum.f64.ll | 75 + test/CodeGen/R600/fmaxnum.ll | 191 + test/CodeGen/R600/fmin3.ll | 38 + test/CodeGen/R600/fmin_legacy.f64.ll | 77 + test/CodeGen/R600/fmin_legacy.ll | 123 + test/CodeGen/R600/fminnum.f64.ll | 75 + test/CodeGen/R600/fminnum.ll | 189 + test/CodeGen/R600/fmul.ll | 70 +- test/CodeGen/R600/fmul64.ll | 33 +- test/CodeGen/R600/fmuladd.ll | 184 +- test/CodeGen/R600/fnearbyint.ll | 4 +- test/CodeGen/R600/fneg-fabs.f64.ll | 101 + test/CodeGen/R600/fneg-fabs.ll | 162 +- test/CodeGen/R600/fneg.f64.ll | 59 + test/CodeGen/R600/fneg.ll | 102 +- test/CodeGen/R600/fp-classify.ll | 130 + test/CodeGen/R600/fp16_to_fp.ll | 20 +- test/CodeGen/R600/fp32_to_fp16.ll | 10 +- test/CodeGen/R600/fp64_to_sint.ll | 9 - test/CodeGen/R600/fp_to_sint.f64.ll | 56 + test/CodeGen/R600/fp_to_sint.ll | 68 +- test/CodeGen/R600/fp_to_uint.f64.ll | 67 +- test/CodeGen/R600/fp_to_uint.ll | 83 +- test/CodeGen/R600/fpext.ll | 6 +- test/CodeGen/R600/fptrunc.ll | 6 +- test/CodeGen/R600/frem.ll | 103 + test/CodeGen/R600/fsqrt.ll | 13 +- test/CodeGen/R600/fsub.ll | 93 +- test/CodeGen/R600/fsub64.ll | 6 +- test/CodeGen/R600/ftrunc.f64.ll | 110 + test/CodeGen/R600/ftrunc.ll | 82 +- test/CodeGen/R600/gep-address-space.ll | 34 +- test/CodeGen/R600/global-directive.ll | 14 + test/CodeGen/R600/global-extload-i1.ll | 301 + test/CodeGen/R600/global-extload-i16.ll | 301 + test/CodeGen/R600/global-extload-i32.ll | 456 + test/CodeGen/R600/global-extload-i8.ll | 298 + test/CodeGen/R600/global-zero-initializer.ll | 12 + test/CodeGen/R600/global_atomics.ll | 801 ++ test/CodeGen/R600/gv-const-addrspace-fail.ll | 23 +- test/CodeGen/R600/gv-const-addrspace.ll | 24 +- test/CodeGen/R600/half.ll | 34 +- test/CodeGen/R600/hsa.ll | 12 + test/CodeGen/R600/i1-copy-implicit-def.ll | 21 + test/CodeGen/R600/i1-copy-phi.ll | 29 + test/CodeGen/R600/icmp64.ll | 42 +- test/CodeGen/R600/imm.ll | 479 +- test/CodeGen/R600/indirect-addressing-si.ll | 18 +- test/CodeGen/R600/indirect-private-64.ll | 68 +- test/CodeGen/R600/infinite-loop.ll | 12 +- test/CodeGen/R600/inline-asm.ll | 11 + test/CodeGen/R600/inline-calls.ll | 24 + test/CodeGen/R600/input-mods.ll | 4 +- test/CodeGen/R600/insert_subreg.ll | 15 + test/CodeGen/R600/insert_vector_elt.ll | 152 +- test/CodeGen/R600/insert_vector_elt_f64.ll | 36 - test/CodeGen/R600/kcache-fold.ll | 4 +- test/CodeGen/R600/kernel-args.ll | 286 +- test/CodeGen/R600/large-alloca.ll | 2 +- test/CodeGen/R600/large-constant-initializer.ll | 4 +- test/CodeGen/R600/lds-initializer.ll | 12 + test/CodeGen/R600/lds-oqap-crash.ll | 2 +- test/CodeGen/R600/lds-output-queue.ll | 6 +- test/CodeGen/R600/lds-size.ll | 4 +- test/CodeGen/R600/lds-zero-initializer.ll | 12 + test/CodeGen/R600/legalizedag-bug-expand-setcc.ll | 2 +- test/CodeGen/R600/literals.ll | 8 +- test/CodeGen/R600/llvm.AMDGPU.abs.ll | 26 +- test/CodeGen/R600/llvm.AMDGPU.barrier.global.ll | 8 +- test/CodeGen/R600/llvm.AMDGPU.barrier.local.ll | 9 +- test/CodeGen/R600/llvm.AMDGPU.bfe.i32.ll | 335 +- test/CodeGen/R600/llvm.AMDGPU.bfe.u32.ll | 432 +- test/CodeGen/R600/llvm.AMDGPU.bfi.ll | 18 +- test/CodeGen/R600/llvm.AMDGPU.bfm.ll | 18 +- test/CodeGen/R600/llvm.AMDGPU.brev.ll | 24 +- test/CodeGen/R600/llvm.AMDGPU.clamp.ll | 58 +- test/CodeGen/R600/llvm.AMDGPU.class.ll | 497 + test/CodeGen/R600/llvm.AMDGPU.cube.ll | 2 +- test/CodeGen/R600/llvm.AMDGPU.cvt_f32_ubyte.ll | 18 +- test/CodeGen/R600/llvm.AMDGPU.div_fixup.ll | 24 +- test/CodeGen/R600/llvm.AMDGPU.div_fmas.ll | 36 +- test/CodeGen/R600/llvm.AMDGPU.div_scale.ll | 273 +- test/CodeGen/R600/llvm.AMDGPU.fract.ll | 10 +- test/CodeGen/R600/llvm.AMDGPU.imad24.ll | 6 +- test/CodeGen/R600/llvm.AMDGPU.imax.ll | 12 +- test/CodeGen/R600/llvm.AMDGPU.imin.ll | 12 +- test/CodeGen/R600/llvm.AMDGPU.imul24.ll | 6 +- test/CodeGen/R600/llvm.AMDGPU.kill.ll | 10 +- test/CodeGen/R600/llvm.AMDGPU.ldexp.ll | 22 + test/CodeGen/R600/llvm.AMDGPU.legacy.rsq.ll | 6 +- test/CodeGen/R600/llvm.AMDGPU.rcp.f64.ll | 16 +- test/CodeGen/R600/llvm.AMDGPU.rcp.ll | 58 +- test/CodeGen/R600/llvm.AMDGPU.rsq.clamped.f64.ll | 6 +- test/CodeGen/R600/llvm.AMDGPU.rsq.clamped.ll | 6 +- test/CodeGen/R600/llvm.AMDGPU.rsq.ll | 25 +- test/CodeGen/R600/llvm.AMDGPU.trig_preop.ll | 24 +- test/CodeGen/R600/llvm.AMDGPU.trunc.ll | 8 +- test/CodeGen/R600/llvm.AMDGPU.umad24.ll | 25 +- test/CodeGen/R600/llvm.AMDGPU.umax.ll | 22 +- test/CodeGen/R600/llvm.AMDGPU.umin.ll | 22 +- test/CodeGen/R600/llvm.AMDGPU.umul24.ll | 6 +- test/CodeGen/R600/llvm.SI.fs.interp.constant.ll | 6 +- test/CodeGen/R600/llvm.SI.gather4.ll | 142 +- test/CodeGen/R600/llvm.SI.getlod.ll | 14 +- test/CodeGen/R600/llvm.SI.image.ll | 14 +- test/CodeGen/R600/llvm.SI.image.sample.ll | 82 +- test/CodeGen/R600/llvm.SI.image.sample.o.ll | 82 +- test/CodeGen/R600/llvm.SI.imageload.ll | 30 +- test/CodeGen/R600/llvm.SI.load.dword.ll | 14 +- test/CodeGen/R600/llvm.SI.resinfo.ll | 34 +- test/CodeGen/R600/llvm.SI.sample-masked.ll | 30 +- test/CodeGen/R600/llvm.SI.sample.ll | 38 +- test/CodeGen/R600/llvm.SI.sampled.ll | 34 +- test/CodeGen/R600/llvm.SI.sendmsg.ll | 12 +- test/CodeGen/R600/llvm.SI.tbuffer.store.ll | 18 +- test/CodeGen/R600/llvm.SI.tid.ll | 6 +- test/CodeGen/R600/llvm.amdgpu.kilp.ll | 8 +- test/CodeGen/R600/llvm.amdgpu.lrp.ll | 8 +- test/CodeGen/R600/llvm.cos.ll | 16 +- test/CodeGen/R600/llvm.exp2.ll | 22 +- test/CodeGen/R600/llvm.floor.ll | 28 +- test/CodeGen/R600/llvm.log2.ll | 22 +- test/CodeGen/R600/llvm.memcpy.ll | 364 + test/CodeGen/R600/llvm.rint.f64.ll | 36 +- test/CodeGen/R600/llvm.rint.ll | 26 +- test/CodeGen/R600/llvm.round.ll | 16 +- test/CodeGen/R600/llvm.sin.ll | 111 +- test/CodeGen/R600/llvm.sqrt.ll | 26 +- test/CodeGen/R600/llvm.trunc.ll | 2 +- test/CodeGen/R600/load-i1.ll | 127 +- test/CodeGen/R600/load-input-fold.ll | 1 - test/CodeGen/R600/load.ll | 372 +- test/CodeGen/R600/load.vec.ll | 14 +- test/CodeGen/R600/load64.ll | 20 +- test/CodeGen/R600/local-64.ll | 130 +- test/CodeGen/R600/local-atomics.ll | 478 +- test/CodeGen/R600/local-atomics64.ll | 392 +- test/CodeGen/R600/local-memory-two-objects.ll | 21 +- test/CodeGen/R600/local-memory.ll | 40 +- test/CodeGen/R600/loop-address.ll | 8 +- test/CodeGen/R600/loop-idiom.ll | 14 +- test/CodeGen/R600/lshl.ll | 4 +- test/CodeGen/R600/lshr.ll | 4 +- test/CodeGen/R600/m0-spill.ll | 34 + test/CodeGen/R600/mad-sub.ll | 215 + test/CodeGen/R600/mad_int24.ll | 19 +- test/CodeGen/R600/mad_uint24.ll | 22 +- test/CodeGen/R600/max-literals.ll | 4 +- test/CodeGen/R600/max.ll | 99 + test/CodeGen/R600/max3.ll | 41 + test/CodeGen/R600/min.ll | 120 + test/CodeGen/R600/min3.ll | 111 + test/CodeGen/R600/missing-store.ll | 26 + test/CodeGen/R600/mubuf.ll | 107 +- test/CodeGen/R600/mul.ll | 166 +- test/CodeGen/R600/mul_int24.ll | 8 +- test/CodeGen/R600/mul_uint24.ll | 24 +- test/CodeGen/R600/mulhu.ll | 8 +- .../R600/no-initializer-constant-addrspace.ll | 6 +- test/CodeGen/R600/no-shrink-extloads.ll | 191 + test/CodeGen/R600/operand-folding.ll | 113 + test/CodeGen/R600/operand-spacing.ll | 15 + test/CodeGen/R600/or.ll | 116 +- test/CodeGen/R600/packetizer.ll | 2 +- test/CodeGen/R600/parallelandifcollapse.ll | 3 +- test/CodeGen/R600/predicate-dp4.ll | 2 +- test/CodeGen/R600/predicates.ll | 8 +- test/CodeGen/R600/private-memory-atomics.ll | 2 +- test/CodeGen/R600/private-memory-broken.ll | 2 +- test/CodeGen/R600/private-memory.ll | 70 +- test/CodeGen/R600/pv.ll | 4 +- test/CodeGen/R600/r600-encoding.ll | 4 +- test/CodeGen/R600/r600-export-fix.ll | 4 +- ...-infinite-loop-bug-while-reorganizing-vector.ll | 1 - test/CodeGen/R600/r600cfg.ll | 1 - test/CodeGen/R600/register-count-comments.ll | 11 +- test/CodeGen/R600/reorder-stores.ll | 116 +- test/CodeGen/R600/rotl.i64.ll | 26 +- test/CodeGen/R600/rotl.ll | 40 +- test/CodeGen/R600/rotr.i64.ll | 28 +- test/CodeGen/R600/rotr.ll | 22 +- test/CodeGen/R600/rsq.ll | 64 +- test/CodeGen/R600/s_movk_i32.ll | 184 + test/CodeGen/R600/saddo.ll | 16 +- test/CodeGen/R600/salu-to-valu.ll | 50 +- test/CodeGen/R600/scalar_to_vector.ll | 34 +- test/CodeGen/R600/schedule-global-loads.ll | 41 + test/CodeGen/R600/schedule-kernel-arg-loads.ll | 12 + .../R600/schedule-vs-if-nested-loop-failure.ll | 4 +- test/CodeGen/R600/sdiv.ll | 26 +- test/CodeGen/R600/sdivrem24.ll | 238 + test/CodeGen/R600/select-i1.ll | 8 +- test/CodeGen/R600/select-vectors.ll | 148 +- test/CodeGen/R600/select.ll | 2 +- test/CodeGen/R600/select64.ll | 28 +- test/CodeGen/R600/selectcc-opt.ll | 18 +- test/CodeGen/R600/selectcc.ll | 10 +- test/CodeGen/R600/set-dx10.ll | 24 +- test/CodeGen/R600/setcc-equivalent.ll | 7 +- test/CodeGen/R600/setcc-opt.ll | 234 +- test/CodeGen/R600/setcc.ll | 184 +- test/CodeGen/R600/setcc64.ll | 129 +- test/CodeGen/R600/seto.ll | 8 +- test/CodeGen/R600/setuo.ll | 8 +- test/CodeGen/R600/sext-eliminate.ll | 26 + test/CodeGen/R600/sext-in-reg.ll | 383 +- test/CodeGen/R600/sgpr-control-flow.ll | 84 +- test/CodeGen/R600/sgpr-copy-duplicate-operand.ll | 6 +- test/CodeGen/R600/sgpr-copy.ll | 91 +- test/CodeGen/R600/shared-op-cycle.ll | 2 +- test/CodeGen/R600/shl.ll | 48 +- test/CodeGen/R600/shl_add_constant.ll | 90 + test/CodeGen/R600/shl_add_ptr.ll | 283 + test/CodeGen/R600/si-annotate-cf-assertion.ll | 4 +- test/CodeGen/R600/si-lod-bias.ll | 10 +- test/CodeGen/R600/si-sgpr-spill.ll | 14 +- test/CodeGen/R600/si-triv-disjoint-mem-access.ll | 238 + test/CodeGen/R600/si-vector-hang.ll | 38 +- test/CodeGen/R600/sign_extend.ll | 40 +- .../R600/simplify-demanded-bits-build-pair.ll | 10 +- test/CodeGen/R600/sint_to_fp.f64.ll | 60 + test/CodeGen/R600/sint_to_fp.ll | 66 +- test/CodeGen/R600/sint_to_fp64.ll | 35 - test/CodeGen/R600/smrd.ll | 53 +- test/CodeGen/R600/split-scalar-i64-add.ll | 48 + test/CodeGen/R600/sra.ll | 54 +- test/CodeGen/R600/srem.ll | 2 +- test/CodeGen/R600/srl.ll | 260 +- test/CodeGen/R600/ssubo.ll | 20 +- test/CodeGen/R600/store-barrier.ll | 42 + test/CodeGen/R600/store-v3i32.ll | 6 +- test/CodeGen/R600/store-v3i64.ll | 14 +- test/CodeGen/R600/store-vector-ptrs.ll | 10 +- test/CodeGen/R600/store.ll | 215 +- test/CodeGen/R600/store.r600.ll | 4 +- test/CodeGen/R600/structurize.ll | 2 +- test/CodeGen/R600/structurize1.ll | 2 +- test/CodeGen/R600/sub.ll | 99 +- test/CodeGen/R600/subreg-coalescer-crash.ll | 45 + test/CodeGen/R600/swizzle-export.ll | 6 +- test/CodeGen/R600/trunc-cmp-constant.ll | 169 + test/CodeGen/R600/trunc-store-i1.ll | 26 +- .../R600/trunc-vector-store-assertion-failure.ll | 2 +- test/CodeGen/R600/trunc.ll | 56 +- test/CodeGen/R600/uaddo.ll | 30 +- test/CodeGen/R600/udiv.ll | 16 +- test/CodeGen/R600/udivrem.ll | 336 +- test/CodeGen/R600/udivrem24.ll | 244 + test/CodeGen/R600/udivrem64.ll | 10 +- test/CodeGen/R600/uint_to_fp.f64.ll | 101 +- test/CodeGen/R600/uint_to_fp.ll | 71 +- test/CodeGen/R600/unaligned-load-store.ll | 105 +- .../R600/unhandled-loop-condition-assertion.ll | 12 +- test/CodeGen/R600/unsupported-cc.ll | 20 +- test/CodeGen/R600/urecip.ll | 4 +- test/CodeGen/R600/urem.ll | 84 +- test/CodeGen/R600/use-sgpr-multiple-times.ll | 96 + test/CodeGen/R600/usubo.ll | 24 +- test/CodeGen/R600/v1i64-kernel-arg.ll | 4 +- test/CodeGen/R600/v_cndmask.ll | 42 +- test/CodeGen/R600/valu-i1.ll | 158 +- test/CodeGen/R600/vector-alloca.ll | 10 +- test/CodeGen/R600/vertex-fetch-encoding.ll | 6 +- test/CodeGen/R600/vop-shrink.ll | 27 +- test/CodeGen/R600/vselect.ll | 32 +- test/CodeGen/R600/vselect64.ll | 2 +- test/CodeGen/R600/vtx-fetch-branch.ll | 2 +- test/CodeGen/R600/vtx-schedule.ll | 2 +- test/CodeGen/R600/wait.ll | 60 +- test/CodeGen/R600/work-item-intrinsics.ll | 179 +- test/CodeGen/R600/wrong-transalu-pos-fix.ll | 8 +- test/CodeGen/R600/xor.ll | 108 +- test/CodeGen/R600/zero_extend.ll | 24 +- .../SPARC/2008-10-10-InlineAsmMemoryOperand.ll | 2 +- test/CodeGen/SPARC/empty-functions.ll | 32 + test/CodeGen/SPARC/inlineasm.ll | 2 +- test/CodeGen/SPARC/mult-alt-generic-sparc.ll | 2 +- test/CodeGen/SPARC/setjmp.ll | 10 +- test/CodeGen/SystemZ/alias-01.ll | 6 +- test/CodeGen/SystemZ/and-08.ll | 10 +- test/CodeGen/SystemZ/asm-01.ll | 2 +- test/CodeGen/SystemZ/asm-02.ll | 2 +- test/CodeGen/SystemZ/asm-03.ll | 2 +- test/CodeGen/SystemZ/asm-04.ll | 2 +- test/CodeGen/SystemZ/asm-05.ll | 2 +- test/CodeGen/SystemZ/asm-06.ll | 2 +- test/CodeGen/SystemZ/asm-07.ll | 2 +- test/CodeGen/SystemZ/asm-08.ll | 2 +- test/CodeGen/SystemZ/asm-09.ll | 2 +- test/CodeGen/SystemZ/asm-10.ll | 2 +- test/CodeGen/SystemZ/asm-11.ll | 2 +- test/CodeGen/SystemZ/asm-12.ll | 2 +- test/CodeGen/SystemZ/asm-13.ll | 2 +- test/CodeGen/SystemZ/asm-14.ll | 2 +- test/CodeGen/SystemZ/asm-15.ll | 2 +- test/CodeGen/SystemZ/asm-16.ll | 2 +- test/CodeGen/SystemZ/asm-17.ll | 2 +- test/CodeGen/SystemZ/asm-18.ll | 2 +- test/CodeGen/SystemZ/fp-cmp-04.ll | 2 +- test/CodeGen/SystemZ/int-cmp-44.ll | 2 +- test/CodeGen/SystemZ/int-cmp-45.ll | 2 +- test/CodeGen/SystemZ/memchr-02.ll | 2 +- test/CodeGen/SystemZ/memcpy-02.ll | 10 +- test/CodeGen/Thumb/2010-07-15-debugOrdering.ll | 216 +- test/CodeGen/Thumb/2012-04-26-M0ISelBug.ll | 2 +- .../Thumb/2014-06-10-thumb1-ldst-opt-bug.ll | 7 +- test/CodeGen/Thumb/copy_thumb.ll | 38 + test/CodeGen/Thumb/dyn-stackalloc.ll | 7 +- test/CodeGen/Thumb/fastcc.ll | 2 +- test/CodeGen/Thumb/iabs.ll | 2 +- test/CodeGen/Thumb/inlineasm-thumb.ll | 13 +- test/CodeGen/Thumb/large-stack.ll | 69 +- test/CodeGen/Thumb/ldm-merge-call.ll | 24 + test/CodeGen/Thumb/ldm-merge-struct.ll | 21 + test/CodeGen/Thumb/ldm-stm-base-materialization.ll | 29 + test/CodeGen/Thumb/pop.ll | 6 +- test/CodeGen/Thumb/stack_guard_remat.ll | 46 + test/CodeGen/Thumb/stm-merge.ll | 40 + test/CodeGen/Thumb/thumb-ldm.ll | 3 +- test/CodeGen/Thumb/thumb-memcpy-ldm-stm.ll | 38 +- test/CodeGen/Thumb2/2009-08-06-SpDecBug.ll | 3 + test/CodeGen/Thumb2/2009-12-01-LoopIVUsers.ll | 2 +- test/CodeGen/Thumb2/aapcs.ll | 50 + test/CodeGen/Thumb2/aligned-spill.ll | 8 +- test/CodeGen/Thumb2/constant-islands-jump-table.ll | 47 + .../Thumb2/constant-islands-new-island-padding.ll | 42 + test/CodeGen/Thumb2/constant-islands-new-island.ll | 31 + test/CodeGen/Thumb2/cortex-fp.ll | 9 +- test/CodeGen/Thumb2/float-cmp.ll | 301 + test/CodeGen/Thumb2/float-intrinsics-double.ll | 228 + test/CodeGen/Thumb2/float-intrinsics-float.ll | 221 + test/CodeGen/Thumb2/float-ops.ll | 293 + test/CodeGen/Thumb2/stack_guard_remat.ll | 43 + test/CodeGen/Thumb2/thumb2-cmn.ll | 2 +- test/CodeGen/Thumb2/thumb2-spill-q.ll | 2 +- test/CodeGen/Thumb2/thumb2-sxt_rot.ll | 22 +- test/CodeGen/Thumb2/thumb2-uxt_rot.ll | 26 +- test/CodeGen/X86/2007-09-06-ExtWeakAliasee.ll | 2 +- test/CodeGen/X86/2008-06-18-BadShuffle.ll | 10 - test/CodeGen/X86/2009-02-12-DebugInfoVLA.ll | 44 +- test/CodeGen/X86/2009-02-26-MachineLICMBug.ll | 2 +- test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll | 30 - test/CodeGen/X86/2009-06-05-VZextByteShort.ll | 28 +- test/CodeGen/X86/2009-10-16-Scope.ll | 24 +- test/CodeGen/X86/2010-01-18-DbgValue.ll | 48 +- test/CodeGen/X86/2010-02-01-DbgValueCrash.ll | 38 +- test/CodeGen/X86/2010-02-11-NonTemporal.ll | 2 +- test/CodeGen/X86/2010-04-23-mmx-movdq2q.ll | 6 +- .../X86/2010-05-05-LocalAllocEarlyClobber.ll | 2 +- test/CodeGen/X86/2010-05-25-DotDebugLoc.ll | 147 +- test/CodeGen/X86/2010-05-26-DotDebugLoc.ll | 94 +- test/CodeGen/X86/2010-05-28-Crash.ll | 50 +- test/CodeGen/X86/2010-06-01-DeadArg-DbgInfo.ll | 76 +- .../X86/2010-06-15-FastAllocEarlyCLobber.ll | 2 +- test/CodeGen/X86/2010-06-25-asm-RA-crash.ll | 2 +- .../CodeGen/X86/2010-06-28-FastAllocTiedOperand.ll | 2 +- test/CodeGen/X86/2010-07-06-DbgCrash.ll | 38 +- test/CodeGen/X86/2010-08-04-StackVariable.ll | 114 +- test/CodeGen/X86/2010-09-16-EmptyFilename.ll | 36 +- test/CodeGen/X86/2010-09-16-asmcrash.ll | 2 +- test/CodeGen/X86/2010-11-02-DbgParameter.ll | 44 +- test/CodeGen/X86/2011-01-24-DbgValue-Before-Use.ll | 80 +- test/CodeGen/X86/2011-06-14-mmx-inlineasm.ll | 4 +- test/CodeGen/X86/2011-08-29-InitOrder.ll | 2 +- test/CodeGen/X86/2012-01-16-mfence-nosse-flags.ll | 2 +- test/CodeGen/X86/2012-04-26-sdglue.ll | 2 +- test/CodeGen/X86/2012-05-19-avx2-store.ll | 13 - test/CodeGen/X86/2012-07-15-broadcastfold.ll | 1 + test/CodeGen/X86/2012-10-02-DAGCycle.ll | 4 +- test/CodeGen/X86/2012-11-30-handlemove-dbg.ll | 26 +- test/CodeGen/X86/2012-11-30-misched-dbg.ll | 63 +- test/CodeGen/X86/2012-11-30-regpres-dbg.ll | 22 +- .../X86/2013-10-14-FastISel-incorrect-vreg.ll | 8 +- test/CodeGen/X86/2014-08-29-CompactUnwind.ll | 46 + test/CodeGen/X86/MachineBranchProb.ll | 2 +- test/CodeGen/X86/MachineSink-DbgValue.ll | 54 +- test/CodeGen/X86/MergeConsecutiveStores.ll | 74 +- test/CodeGen/X86/StackColoring-dbg.ll | 16 +- test/CodeGen/X86/SwizzleShuff.ll | 2 +- test/CodeGen/X86/TruncAssertZext.ll | 16 + test/CodeGen/X86/add_shl_constant.ll | 49 + test/CodeGen/X86/addr-mode-matcher.ll | 62 + test/CodeGen/X86/adx-intrinsics.ll | 77 + test/CodeGen/X86/aliases.ll | 6 +- test/CodeGen/X86/aligned-variadic.ll | 30 + test/CodeGen/X86/alloca-align-rounding.ll | 19 +- test/CodeGen/X86/asm-block-labels.ll | 2 +- test/CodeGen/X86/asm-label.ll | 6 +- test/CodeGen/X86/atomic-load-store-wide.ll | 10 +- test/CodeGen/X86/atomic16.ll | 24 +- test/CodeGen/X86/atomic_add.ll | 17 + test/CodeGen/X86/atomic_idempotent.ll | 56 + test/CodeGen/X86/atomic_mi.ll | 525 ++ test/CodeGen/X86/avoid_complex_am.ll | 2 +- test/CodeGen/X86/avx-basic.ll | 40 - test/CodeGen/X86/avx-blend.ll | 202 - test/CodeGen/X86/avx-intel-ocl.ll | 32 +- test/CodeGen/X86/avx-intrinsics-x86-upgrade.ll | 26 + test/CodeGen/X86/avx-intrinsics-x86.ll | 52 +- test/CodeGen/X86/avx-movdup.ll | 34 - test/CodeGen/X86/avx-sext.ll | 199 - test/CodeGen/X86/avx-shuffle.ll | 336 - test/CodeGen/X86/avx-splat.ll | 17 +- test/CodeGen/X86/avx-vmovddup.ll | 14 - test/CodeGen/X86/avx-vperm2f128.ll | 69 - test/CodeGen/X86/avx-vperm2x128.ll | 193 + test/CodeGen/X86/avx-vpermil.ll | 54 - test/CodeGen/X86/avx-vshufp.ll | 157 - test/CodeGen/X86/avx-zext.ll | 41 - test/CodeGen/X86/avx.ll | 2 +- test/CodeGen/X86/avx1-stack-reload-folding.ll | 83 + test/CodeGen/X86/avx2-blend.ll | 11 - test/CodeGen/X86/avx2-intrinsics-x86-upgrade.ll | 33 + test/CodeGen/X86/avx2-intrinsics-x86.ll | 24 +- test/CodeGen/X86/avx2-nontemporal.ll | 2 +- test/CodeGen/X86/avx2-palignr.ll | 57 - test/CodeGen/X86/avx2-pmovx-256-old-shuffle.ll | 29 + test/CodeGen/X86/avx2-pmovxrm-intrinsics.ll | 110 + test/CodeGen/X86/avx2-shuffle.ll | 127 - test/CodeGen/X86/avx2-unpack.ll | 86 - test/CodeGen/X86/avx2-vbroadcast.ll | 2 +- test/CodeGen/X86/avx2-vperm2i128.ll | 47 - test/CodeGen/X86/avx512-arith.ll | 514 +- test/CodeGen/X86/avx512-build-vector.ll | 35 +- test/CodeGen/X86/avx512-cmp.ll | 19 +- test/CodeGen/X86/avx512-cvt.ll | 53 + test/CodeGen/X86/avx512-fma-intrinsics.ll | 137 +- test/CodeGen/X86/avx512-i1test.ll | 45 + test/CodeGen/X86/avx512-insert-extract.ll | 25 +- test/CodeGen/X86/avx512-intrinsics.ll | 844 +- test/CodeGen/X86/avx512-logic.ll | 101 + test/CodeGen/X86/avx512-mask-op.ll | 42 +- test/CodeGen/X86/avx512-mov.ll | 298 +- test/CodeGen/X86/avx512-nontemporal.ll | 2 +- test/CodeGen/X86/avx512-select.ll | 53 + test/CodeGen/X86/avx512-shuffle.ll | 314 - test/CodeGen/X86/avx512-trunc-ext.ll | 34 +- test/CodeGen/X86/avx512-vbroadcast.ll | 272 +- test/CodeGen/X86/avx512-vec-cmp.ll | 346 +- test/CodeGen/X86/avx512-zext-load-crash.ll | 14 - test/CodeGen/X86/avx512bw-arith.ll | 102 + test/CodeGen/X86/avx512bw-intrinsics.ll | 353 + test/CodeGen/X86/avx512bw-mask-op.ll | 99 + test/CodeGen/X86/avx512bw-mov.ll | 81 + test/CodeGen/X86/avx512bw-vec-cmp.ll | 135 + test/CodeGen/X86/avx512bwvl-arith.ll | 206 + test/CodeGen/X86/avx512bwvl-intrinsics.ll | 998 ++ test/CodeGen/X86/avx512bwvl-mov.ll | 162 + test/CodeGen/X86/avx512bwvl-vec-cmp.ll | 269 + test/CodeGen/X86/avx512dq-mask-op.ll | 38 + test/CodeGen/X86/avx512er-intrinsics.ll | 116 + test/CodeGen/X86/avx512vl-arith.ll | 794 ++ test/CodeGen/X86/avx512vl-intrinsics.ll | 864 ++ test/CodeGen/X86/avx512vl-logic.ll | 137 + test/CodeGen/X86/avx512vl-mov.ll | 642 ++ test/CodeGen/X86/avx512vl-nontemporal.ll | 34 + test/CodeGen/X86/avx512vl-vec-cmp.ll | 381 + test/CodeGen/X86/blend-msb.ll | 40 - test/CodeGen/X86/block-placement.ll | 44 +- test/CodeGen/X86/break-avx-dep.ll | 29 - test/CodeGen/X86/break-false-dep.ll | 201 + test/CodeGen/X86/break-sse-dep.ll | 62 - test/CodeGen/X86/byval-callee-cleanup.ll | 27 + test/CodeGen/X86/cfi_enforcing.ll | 34 + test/CodeGen/X86/cfi_invoke.ll | 35 + test/CodeGen/X86/cfi_non_default_function.ll | 27 + test/CodeGen/X86/cfi_simple_indirect_call.ll | 43 + test/CodeGen/X86/chain_order.ll | 16 +- test/CodeGen/X86/clobber-fi0.ll | 2 +- test/CodeGen/X86/cmov.ll | 2 +- test/CodeGen/X86/cmpxchg-clobber-flags.ll | 87 + test/CodeGen/X86/coalesce_commute_subreg.ll | 51 + test/CodeGen/X86/coalescer-dce.ll | 2 +- test/CodeGen/X86/codegen-prepare-addrmode-sext.ll | 213 +- test/CodeGen/X86/codegen-prepare-extload.ll | 348 +- test/CodeGen/X86/coff-comdat.ll | 48 +- test/CodeGen/X86/coff-comdat2.ll | 4 +- test/CodeGen/X86/coff-comdat3.ll | 2 +- test/CodeGen/X86/combine-and.ll | 164 + test/CodeGen/X86/combine-or.ll | 199 +- test/CodeGen/X86/combine-vec-shuffle-2.ll | 253 - test/CodeGen/X86/combine-vec-shuffle-3.ll | 380 - test/CodeGen/X86/combine-vec-shuffle-4.ll | 237 - test/CodeGen/X86/combine-vec-shuffle-5.ll | 257 - test/CodeGen/X86/combine-vec-shuffle.ll | 253 - test/CodeGen/X86/commute-blend-avx2.ll | 89 + test/CodeGen/X86/commute-blend-sse41.ll | 34 + test/CodeGen/X86/commuted-blend-mask.ll | 13 + test/CodeGen/X86/compact-unwind.ll | 88 +- test/CodeGen/X86/constructor.ll | 12 +- test/CodeGen/X86/copysign-constant-magnitude.ll | 105 + test/CodeGen/X86/copysign-zero.ll | 14 - test/CodeGen/X86/cpus.ll | 35 + test/CodeGen/X86/crash-O0.ll | 22 +- test/CodeGen/X86/crash.ll | 4 +- test/CodeGen/X86/critical-anti-dep-breaker.ll | 28 + test/CodeGen/X86/cttz-ctlz.ll | 422 + .../X86/dbg-changes-codegen-branch-folding.ll | 169 +- test/CodeGen/X86/dbg-changes-codegen.ll | 16 +- test/CodeGen/X86/divide-by-constant.ll | 8 +- test/CodeGen/X86/divrem8_ext.ll | 100 + test/CodeGen/X86/dllexport-x86_64.ll | 2 +- test/CodeGen/X86/dllexport.ll | 2 +- test/CodeGen/X86/dllimport-x86_64.ll | 2 +- test/CodeGen/X86/dllimport.ll | 2 +- .../X86/dont-trunc-store-double-to-float.ll | 20 + test/CodeGen/X86/dwarf-comp-dir.ll | 14 +- test/CodeGen/X86/dynamic-alloca-lifetime.ll | 44 + test/CodeGen/X86/elf-comdat.ll | 4 +- test/CodeGen/X86/elf-comdat2.ll | 2 +- test/CodeGen/X86/empty-functions.ll | 31 +- test/CodeGen/X86/equiv_with_fndef.ll | 10 + test/CodeGen/X86/equiv_with_vardef.ll | 8 + test/CodeGen/X86/exedepsfix-broadcast.ll | 9 +- test/CodeGen/X86/extractelement-load.ll | 39 + test/CodeGen/X86/fast-isel-args-fail.ll | 1 - test/CodeGen/X86/fast-isel-branch_weights.ll | 2 +- test/CodeGen/X86/fast-isel-call-bool.ll | 18 + test/CodeGen/X86/fast-isel-cmp-branch.ll | 2 +- test/CodeGen/X86/fast-isel-cmp-branch3.ll | 10 +- test/CodeGen/X86/fast-isel-constpool.ll | 36 +- test/CodeGen/X86/fast-isel-gep.ll | 2 +- test/CodeGen/X86/fast-isel-mem.ll | 4 +- test/CodeGen/X86/fast-isel-tls.ll | 2 +- test/CodeGen/X86/fast-isel-x32.ll | 14 + test/CodeGen/X86/fast-isel-x86-64.ll | 20 +- test/CodeGen/X86/fast-isel-x86.ll | 18 + test/CodeGen/X86/fastmath-optnone.ll | 35 + test/CodeGen/X86/fma-intrinsics-x86_64.ll | 278 + test/CodeGen/X86/fma-phi-213-to-231.ll | 246 + .../X86/fma4-intrinsics-x86_64-folded-load.ll | 84 + test/CodeGen/X86/fma4-intrinsics-x86_64.ll | 316 - test/CodeGen/X86/fma_patterns.ll | 4 +- test/CodeGen/X86/fmaxnum.ll | 50 + test/CodeGen/X86/fminnum.ll | 95 + test/CodeGen/X86/fmul-combines.ll | 147 + test/CodeGen/X86/fnabs.ll | 77 + test/CodeGen/X86/fold-pcmpeqd-0.ll | 117 - test/CodeGen/X86/fold-tied-op.ll | 84 + test/CodeGen/X86/force-align-stack-alloca.ll | 4 +- test/CodeGen/X86/fp-load-trunc.ll | 96 +- test/CodeGen/X86/fp-trunc.ll | 90 +- test/CodeGen/X86/fpstack-debuginstr-kill.ll | 71 + test/CodeGen/X86/frameaddr.ll | 26 + test/CodeGen/X86/frameallocate.ll | 39 + test/CodeGen/X86/gather-addresses.ll | 83 +- test/CodeGen/X86/gcc_except_table_functions.ll | 53 + test/CodeGen/X86/ghc-cc.ll | 10 +- test/CodeGen/X86/ghc-cc64.ll | 10 +- test/CodeGen/X86/global-sections.ll | 29 +- test/CodeGen/X86/hoist-invariant-load.ll | 2 +- test/CodeGen/X86/i8-umulo.ll | 24 - test/CodeGen/X86/ident-metadata.ll | 4 +- test/CodeGen/X86/inalloca-ctor.ll | 8 +- test/CodeGen/X86/inalloca-invoke.ll | 2 +- test/CodeGen/X86/inalloca-regparm.ll | 15 + test/CodeGen/X86/inalloca-stdcall.ll | 2 +- test/CodeGen/X86/inline-asm-flag-clobber.ll | 2 +- test/CodeGen/X86/inline-asm-fpstack.ll | 62 + test/CodeGen/X86/jump_sign.ll | 2 +- test/CodeGen/X86/jump_table_alias.ll | 3 +- test/CodeGen/X86/jump_table_align.ll | 29 + test/CodeGen/X86/jump_table_bitcast.ll | 9 +- test/CodeGen/X86/jump_tables.ll | 45 +- test/CodeGen/X86/large-code-model-isel.ll | 13 + test/CodeGen/X86/lea-2.ll | 7 +- test/CodeGen/X86/lea-3.ll | 2 + test/CodeGen/X86/lea-4.ll | 5 +- test/CodeGen/X86/lea-5.ll | 59 + test/CodeGen/X86/lea.ll | 2 + test/CodeGen/X86/long-extend.ll | 18 - test/CodeGen/X86/loop-strength-reduce8.ll | 5 +- test/CodeGen/X86/lower-bitcast.ll | 4 +- test/CodeGen/X86/lower-vec-shift-2.ll | 149 + test/CodeGen/X86/lzcnt-tzcnt.ll | 131 + test/CodeGen/X86/macho-comdat.ll | 2 +- test/CodeGen/X86/masked_memop.ll | 217 + test/CodeGen/X86/mem-intrin-base-reg.ll | 100 + test/CodeGen/X86/mem-promote-integers.ll | 4 +- .../X86/misched-code-difference-with-debug.ll | 90 + test/CodeGen/X86/misched-copy.ll | 8 +- test/CodeGen/X86/misched-crash.ll | 2 +- test/CodeGen/X86/misched-matmul.ll | 2 +- test/CodeGen/X86/movgs.ll | 86 +- test/CodeGen/X86/movntdq-no-avx.ll | 2 +- test/CodeGen/X86/movtopush.ll | 112 + test/CodeGen/X86/ms-inline-asm.ll | 11 +- test/CodeGen/X86/musttail-fastcall.ll | 109 + test/CodeGen/X86/musttail-varargs.ll | 140 + test/CodeGen/X86/named-reg-alloc.ll | 2 +- test/CodeGen/X86/named-reg-notareg.ll | 2 +- test/CodeGen/X86/nancvt.ll | 2 +- test/CodeGen/X86/narrow-shl-load.ll | 34 - test/CodeGen/X86/no-compact-unwind.ll | 64 - test/CodeGen/X86/nonconst-static-ev.ll | 1 - test/CodeGen/X86/nonconst-static-iv.ll | 1 - test/CodeGen/X86/nontemporal-2.ll | 31 + test/CodeGen/X86/nontemporal.ll | 2 +- test/CodeGen/X86/norex-subreg.ll | 4 +- test/CodeGen/X86/null-streamer.ll | 26 +- test/CodeGen/X86/objc-gc-module-flags.ll | 8 +- test/CodeGen/X86/object-size.ll | 6 +- test/CodeGen/X86/osx-private-labels.ll | 17 + test/CodeGen/X86/palignr.ll | 104 +- test/CodeGen/X86/patchpoint-invoke.ll | 63 + test/CodeGen/X86/patchpoint-webkit_jscc.ll | 88 + test/CodeGen/X86/patchpoint.ll | 69 +- test/CodeGen/X86/peep-test-2.ll | 2 +- test/CodeGen/X86/peep-vector-extract-concat.ll | 11 - test/CodeGen/X86/peep-vector-extract-insert.ll | 12 - test/CodeGen/X86/peephole-fold-movsd.ll | 31 + test/CodeGen/X86/phys_subreg_coalesce-3.ll | 2 +- test/CodeGen/X86/pmul.ll | 100 +- test/CodeGen/X86/pr11334.ll | 8 +- test/CodeGen/X86/pr11468.ll | 2 +- test/CodeGen/X86/pr12359.ll | 10 - test/CodeGen/X86/pr12360.ll | 2 +- test/CodeGen/X86/pr14161.ll | 23 +- test/CodeGen/X86/pr15267.ll | 33 +- test/CodeGen/X86/pr18846.ll | 139 + test/CodeGen/X86/pr21099.ll | 10 + test/CodeGen/X86/pr21529.ll | 15 + test/CodeGen/X86/pr22019.ll | 23 + test/CodeGen/X86/pr22103.ll | 19 + test/CodeGen/X86/pre-ra-sched.ll | 2 +- test/CodeGen/X86/prefixdata.ll | 9 +- test/CodeGen/X86/prologuedata.ll | 17 + test/CodeGen/X86/pshufb-mask-comments.ll | 40 + test/CodeGen/X86/ragreedy-bug.ll | 48 +- test/CodeGen/X86/ragreedy-hoist-spill.ll | 19 +- .../CodeGen/X86/ragreedy-last-chance-recoloring.ll | 6 +- test/CodeGen/X86/recip-fastmath.ll | 109 + .../CodeGen/X86/regalloc-reconcile-broken-hints.ll | 145 + test/CodeGen/X86/remat-phys-dead.ll | 2 +- test/CodeGen/X86/return_zeroext_i2.ll | 7 + test/CodeGen/X86/scev-interchange.ll | 2 +- test/CodeGen/X86/segmented-stacks-dynamic.ll | 22 + test/CodeGen/X86/segmented-stacks.ll | 178 + test/CodeGen/X86/seh-basic.ll | 175 + test/CodeGen/X86/seh-safe-div.ll | 196 + test/CodeGen/X86/select.ll | 38 +- test/CodeGen/X86/sext-i1.ll | 33 + test/CodeGen/X86/shrink-compare.ll | 148 + test/CodeGen/X86/sibcall-4.ll | 4 +- test/CodeGen/X86/sibcall-5.ll | 2 +- test/CodeGen/X86/sincos-opt.ll | 3 +- test/CodeGen/X86/sink-blockfreq.ll | 45 + test/CodeGen/X86/sink-hoist.ll | 2 +- test/CodeGen/X86/sink-out-of-loop.ll | 23 +- test/CodeGen/X86/sjlj-baseptr.ll | 37 + test/CodeGen/X86/slow-div.ll | 28 + test/CodeGen/X86/slow-incdec.ll | 80 + test/CodeGen/X86/small-byval-memcpy.ll | 41 +- test/CodeGen/X86/splat-for-size.ll | 141 + test/CodeGen/X86/splat-scalar-load.ll | 17 - test/CodeGen/X86/sqrt-fastmath.ll | 76 +- test/CodeGen/X86/sse-align-12.ll | 34 +- test/CodeGen/X86/sse-domains.ll | 42 - test/CodeGen/X86/sse-minmax.ll | 200 +- test/CodeGen/X86/sse-scalar-fp-arith-2.ll | 423 - test/CodeGen/X86/sse-scalar-fp-arith.ll | 840 +- test/CodeGen/X86/sse1.ll | 36 +- test/CodeGen/X86/sse2-blend.ll | 57 - test/CodeGen/X86/sse2-intrinsics-x86.ll | 8 +- test/CodeGen/X86/sse2-mul.ll | 14 - test/CodeGen/X86/sse2.ll | 255 +- test/CodeGen/X86/sse3-avx-addsub-2.ll | 2 +- test/CodeGen/X86/sse3-avx-addsub.ll | 155 +- test/CodeGen/X86/sse3.ll | 259 +- test/CodeGen/X86/sse41-blend.ll | 140 - test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll | 61 + test/CodeGen/X86/sse41-intrinsics-x86.ll | 28 +- test/CodeGen/X86/sse41-pmovxrm-intrinsics.ll | 123 + test/CodeGen/X86/sse41.ll | 1096 ++- test/CodeGen/X86/sse_partial_update.ll | 43 +- test/CodeGen/X86/stack-probe-size.ll | 78 + test/CodeGen/X86/stack-protector-dbginfo.ll | 146 +- test/CodeGen/X86/stack-protector-weight.ll | 36 + test/CodeGen/X86/stack_guard_remat.ll | 28 + test/CodeGen/X86/stackmap-fast-isel.ll | 4 +- test/CodeGen/X86/stackmap-large-constants.ll | 83 + test/CodeGen/X86/stackmap-liveness.ll | 4 +- test/CodeGen/X86/stackmap-nops.ll | 6 +- test/CodeGen/X86/stackmap-shadow-optimization.ll | 28 + test/CodeGen/X86/stackmap.ll | 25 +- test/CodeGen/X86/stackpointer.ll | 2 +- test/CodeGen/X86/statepoint-call-lowering.ll | 90 + test/CodeGen/X86/statepoint-forward.ll | 107 + test/CodeGen/X86/statepoint-stack-usage.ll | 60 + test/CodeGen/X86/statepoint-stackmap-format.ll | 109 + test/CodeGen/X86/store-narrow.ll | 12 +- test/CodeGen/X86/switch-default-only.ll | 14 + test/CodeGen/X86/switch-jump-table.ll | 52 + test/CodeGen/X86/swizzle-2.ll | 427 +- test/CodeGen/X86/swizzle.ll | 19 - test/CodeGen/X86/tailcall-multiret.ll | 16 + test/CodeGen/X86/tailcall-returndup-void.ll | 10 +- test/CodeGen/X86/tls-addr-non-leaf-function.ll | 37 + test/CodeGen/X86/tls-models.ll | 8 + test/CodeGen/X86/trunc-ext-ld-st.ll | 8 +- test/CodeGen/X86/uint_to_fp-2.ll | 46 +- test/CodeGen/X86/unaligned-32-byte-memops.ll | 279 + test/CodeGen/X86/unknown-location.ll | 26 +- test/CodeGen/X86/utf16-cfstrings.ll | 8 +- test/CodeGen/X86/v-binop-widen.ll | 11 - test/CodeGen/X86/v-binop-widen2.ll | 47 - test/CodeGen/X86/v2f32.ll | 139 +- test/CodeGen/X86/vaargs.ll | 2 +- test/CodeGen/X86/vararg-callee-cleanup.ll | 54 + test/CodeGen/X86/vararg_no_start.ll | 9 + test/CodeGen/X86/vastart-defs-eflags.ll | 2 + test/CodeGen/X86/vec-loadsingles-alignment.ll | 35 + test/CodeGen/X86/vec_cast2.ll | 190 +- test/CodeGen/X86/vec_compare-2.ll | 30 - test/CodeGen/X86/vec_ctbits.ll | 51 +- test/CodeGen/X86/vec_extract-avx.ll | 82 + test/CodeGen/X86/vec_extract-sse4.ll | 41 +- test/CodeGen/X86/vec_extract.ll | 48 +- test/CodeGen/X86/vec_fabs.ll | 47 +- test/CodeGen/X86/vec_fneg.ll | 44 +- test/CodeGen/X86/vec_insert-5.ll | 95 +- test/CodeGen/X86/vec_insert-6.ll | 9 - test/CodeGen/X86/vec_insert.ll | 19 - test/CodeGen/X86/vec_loadsingles.ll | 153 +- test/CodeGen/X86/vec_set-3.ll | 44 +- test/CodeGen/X86/vec_set-5.ll | 28 - test/CodeGen/X86/vec_set-9.ll | 14 - test/CodeGen/X86/vec_set-E.ll | 9 - test/CodeGen/X86/vec_set-G.ll | 9 - test/CodeGen/X86/vec_set-I.ll | 13 - test/CodeGen/X86/vec_set-J.ll | 10 - test/CodeGen/X86/vec_setcc.ll | 6 +- test/CodeGen/X86/vec_sext.ll | 69 - test/CodeGen/X86/vec_shuffle-11.ll | 11 - test/CodeGen/X86/vec_shuffle-14.ll | 70 - test/CodeGen/X86/vec_shuffle-15.ll | 81 - test/CodeGen/X86/vec_shuffle-16.ll | 43 - test/CodeGen/X86/vec_shuffle-17.ll | 16 - test/CodeGen/X86/vec_shuffle-18.ll | 25 - test/CodeGen/X86/vec_shuffle-19.ll | 9 - test/CodeGen/X86/vec_shuffle-20.ll | 8 - test/CodeGen/X86/vec_shuffle-22.ll | 15 - test/CodeGen/X86/vec_shuffle-23.ll | 18 - test/CodeGen/X86/vec_shuffle-24.ll | 18 - test/CodeGen/X86/vec_shuffle-25.ll | 34 - test/CodeGen/X86/vec_shuffle-26.ll | 68 - test/CodeGen/X86/vec_shuffle-27.ll | 38 - test/CodeGen/X86/vec_shuffle-28.ll | 14 - test/CodeGen/X86/vec_shuffle-30.ll | 26 - test/CodeGen/X86/vec_shuffle-31.ll | 8 - test/CodeGen/X86/vec_shuffle-34.ll | 7 - test/CodeGen/X86/vec_shuffle-35.ll | 20 - test/CodeGen/X86/vec_shuffle-36.ll | 16 - test/CodeGen/X86/vec_shuffle-37.ll | 47 - test/CodeGen/X86/vec_shuffle-38.ll | 77 - test/CodeGen/X86/vec_shuffle-39.ll | 86 - test/CodeGen/X86/vec_shuffle-40.ll | 22 - test/CodeGen/X86/vec_shuffle-41.ll | 21 - test/CodeGen/X86/vec_shuffle.ll | 50 - test/CodeGen/X86/vec_splat-2.ll | 33 - test/CodeGen/X86/vec_splat-3.ll | 230 - test/CodeGen/X86/vec_splat.ll | 50 - test/CodeGen/X86/vec_trunc_sext.ll | 30 + test/CodeGen/X86/vec_uint_to_fp.ll | 164 +- test/CodeGen/X86/vec_unsafe-fp-math.ll | 23 + test/CodeGen/X86/vec_zext.ll | 69 - test/CodeGen/X86/vector-blend.ll | 801 ++ test/CodeGen/X86/vector-ctpop.ll | 159 + test/CodeGen/X86/vector-idiv.ll | 1345 ++- test/CodeGen/X86/vector-sext.ll | 942 ++ test/CodeGen/X86/vector-shuffle-128-v16.ll | 1128 ++- test/CodeGen/X86/vector-shuffle-128-v2.ll | 1113 ++- test/CodeGen/X86/vector-shuffle-128-v4.ll | 1343 ++- test/CodeGen/X86/vector-shuffle-128-v8.ll | 1998 +++- test/CodeGen/X86/vector-shuffle-256-v16.ll | 1364 +++ test/CodeGen/X86/vector-shuffle-256-v32.ll | 1656 ++++ test/CodeGen/X86/vector-shuffle-256-v4.ll | 888 ++ test/CodeGen/X86/vector-shuffle-256-v8.ll | 1851 ++++ test/CodeGen/X86/vector-shuffle-512-v16.ll | 40 + test/CodeGen/X86/vector-shuffle-512-v8.ll | 1456 +++ test/CodeGen/X86/vector-shuffle-combining.ll | 2552 +++++- test/CodeGen/X86/vector-shuffle-sse1.ll | 235 + test/CodeGen/X86/vector-trunc.ll | 90 + test/CodeGen/X86/vector-zext.ll | 360 + test/CodeGen/X86/vector-zmov.ll | 37 + test/CodeGen/X86/vectorcall.ll | 93 + test/CodeGen/X86/vselect-2.ll | 53 +- test/CodeGen/X86/vselect-avx.ll | 85 + test/CodeGen/X86/vselect-minmax.ll | 2790 ++++++ test/CodeGen/X86/vselect.ll | 278 +- test/CodeGen/X86/vshift-4.ll | 2 +- test/CodeGen/X86/widen_cast-1.ll | 4 +- test/CodeGen/X86/widen_conv-1.ll | 2 +- test/CodeGen/X86/widen_conversions.ll | 2 +- test/CodeGen/X86/widen_load-2.ll | 192 +- test/CodeGen/X86/widen_shuffle-1.ll | 57 +- test/CodeGen/X86/win32-pic-jumptable.ll | 36 + test/CodeGen/X86/win64_call_epi.ll | 65 + test/CodeGen/X86/win64_eh.ll | 2 +- test/CodeGen/X86/win64_vararg.ll | 19 + test/CodeGen/X86/windows-itanium-alloca.ll | 16 + test/CodeGen/X86/x32-function_pointer-1.ll | 20 + test/CodeGen/X86/x32-function_pointer-2.ll | 21 + test/CodeGen/X86/x32-function_pointer-3.ll | 30 + test/CodeGen/X86/x86-64-call.ll | 15 + test/CodeGen/X86/x86-64-pic-10.ll | 2 +- test/CodeGen/X86/x86-64-stack-and-frame-ptr.ll | 34 + test/CodeGen/X86/x86-64-tls-1.ll | 9 +- test/CodeGen/X86/x86-inline-asm-validation.ll | 34 + test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll | 35 + test/CodeGen/X86/x86-setcc-int-to-fp-combine.ll | 26 +- test/CodeGen/X86/xaluo.ll | 479 +- test/CodeGen/XCore/atomic.ll | 5 +- test/CodeGen/XCore/dwarf_debug.ll | 30 +- test/CodeGen/XCore/exception.ll | 15 +- test/DebugInfo/2009-10-16-Phi.ll | 2 +- test/DebugInfo/2009-11-03-InsertExtractValue.ll | 14 +- test/DebugInfo/2009-11-05-DeadGlobalVariable.ll | 28 +- .../DebugInfo/2009-11-06-NamelessGlobalVariable.ll | 16 +- test/DebugInfo/2009-11-10-CurrentFn.ll | 34 +- test/DebugInfo/2010-01-05-DbgScope.ll | 24 +- test/DebugInfo/2010-03-12-llc-crash.ll | 26 +- test/DebugInfo/2010-03-19-DbgDeclare.ll | 18 +- test/DebugInfo/2010-03-24-MemberFn.ll | 64 +- test/DebugInfo/2010-03-30-InvalidDbgInfoCrash.ll | 50 +- test/DebugInfo/2010-04-06-NestedFnDbgInfo.ll | 94 +- test/DebugInfo/2010-04-19-FramePtr.ll | 26 +- test/DebugInfo/2010-05-03-DisableFramePtr.ll | 44 +- test/DebugInfo/2010-05-03-OriginDIE.ll | 98 +- test/DebugInfo/2010-05-10-MultipleCU.ll | 44 +- test/DebugInfo/2010-06-29-InlinedFnLocalVar.ll | 68 +- test/DebugInfo/2010-07-19-Crash.ll | 32 +- test/DebugInfo/2010-10-01-crash.ll | 22 +- test/DebugInfo/AArch64/big-endian-dump.ll | 16 + test/DebugInfo/AArch64/big-endian.ll | 22 + test/DebugInfo/AArch64/cfi-eof-prologue.ll | 112 + test/DebugInfo/AArch64/coalescing.ll | 65 + test/DebugInfo/AArch64/dwarfdump.ll | 22 +- test/DebugInfo/AArch64/little-endian-dump.ll | 16 + test/DebugInfo/AArch64/processes-relocations.ll | 15 + test/DebugInfo/AArch64/struct_by_value.ll | 46 +- test/DebugInfo/ARM/PR16736.ll | 58 +- test/DebugInfo/ARM/big-endian-dump.ll | 18 + test/DebugInfo/ARM/cfi-eof-prologue.ll | 115 + test/DebugInfo/ARM/little-endian-dump.ll | 18 + test/DebugInfo/ARM/lowerbdgdeclare_vla.ll | 86 +- test/DebugInfo/ARM/processes-relocations.ll | 15 + test/DebugInfo/ARM/s-super-register.ll | 63 + test/DebugInfo/ARM/sectionorder.ll | 9 +- test/DebugInfo/ARM/selectiondag-deadcode.ll | 16 +- test/DebugInfo/ARM/tls.ll | 20 +- test/DebugInfo/COFF/asan-module-ctor.ll | 25 +- .../COFF/asan-module-without-functions.ll | 12 +- test/DebugInfo/COFF/asm.ll | 130 +- test/DebugInfo/COFF/cpp-mangling.ll | 43 + test/DebugInfo/COFF/multifile.ll | 154 +- test/DebugInfo/COFF/multifunction.ll | 344 +- test/DebugInfo/COFF/simple.ll | 124 +- .../COFF/tail-call-without-lexical-scopes.ll | 34 +- test/DebugInfo/Inputs/cross-cu-inlining.c | 18 + .../Inputs/cross-cu-inlining.x86_64-macho.o | Bin 0 -> 2648 bytes .../DebugInfo/Inputs/dwarfdump-inl-test.elf-x86-64 | Bin 9024 -> 9192 bytes test/DebugInfo/Inputs/dwarfdump-objc.m | 16 + test/DebugInfo/Inputs/dwarfdump-objc.x86_64.o | Bin 0 -> 11512 bytes test/DebugInfo/Inputs/gmlt.ll | 153 + test/DebugInfo/Inputs/split-dwarf-test | Bin 0 -> 9379 bytes test/DebugInfo/Inputs/split-dwarf-test.cc | 17 + test/DebugInfo/Inputs/split-dwarf-test.dwo | Bin 0 -> 1609 bytes test/DebugInfo/Mips/delay-slot.ll | 44 +- test/DebugInfo/Mips/processes-relocations.ll | 17 + test/DebugInfo/PR20038.ll | 114 +- test/DebugInfo/PowerPC/processes-relocations.ll | 17 + test/DebugInfo/PowerPC/tls-fission.ll | 18 +- test/DebugInfo/PowerPC/tls.ll | 18 +- test/DebugInfo/Sparc/gnu-window-save.ll | 28 +- test/DebugInfo/Sparc/processes-relocations.ll | 17 + test/DebugInfo/SystemZ/processes-relocations.ll | 15 + test/DebugInfo/SystemZ/variable-loc.ll | 62 +- test/DebugInfo/X86/2010-04-13-PubType.ll | 48 +- test/DebugInfo/X86/2010-08-10-DbgConstant.ll | 30 +- test/DebugInfo/X86/2011-09-26-GlobalVarContext.ll | 46 +- test/DebugInfo/X86/2011-12-16-BadStructRef.ll | 174 +- test/DebugInfo/X86/DW_AT_byte_size.ll | 40 +- test/DebugInfo/X86/DW_AT_linkage_name.ll | 86 +- test/DebugInfo/X86/DW_AT_location-reference.ll | 54 +- test/DebugInfo/X86/DW_AT_object_pointer.ll | 84 +- test/DebugInfo/X86/DW_AT_specification.ll | 44 +- test/DebugInfo/X86/DW_AT_stmt_list_sec_offset.ll | 24 +- test/DebugInfo/X86/DW_TAG_friend.ll | 56 +- test/DebugInfo/X86/aligned_stack_var.ll | 32 +- test/DebugInfo/X86/arange.ll | 30 +- test/DebugInfo/X86/arguments.ll | 56 +- test/DebugInfo/X86/array.ll | 92 +- test/DebugInfo/X86/array2.ll | 76 +- test/DebugInfo/X86/asm-macro-line-number.s | 20 + test/DebugInfo/X86/block-capture.ll | 226 +- test/DebugInfo/X86/byvalstruct.ll | 90 +- test/DebugInfo/X86/c-type-units.ll | 20 +- test/DebugInfo/X86/coff_debug_info_type.ll | 34 +- test/DebugInfo/X86/coff_relative_names.ll | 24 +- test/DebugInfo/X86/concrete_out_of_line.ll | 142 +- test/DebugInfo/X86/constant-aggregate.ll | 118 + test/DebugInfo/X86/cu-ranges-odr.ll | 72 +- test/DebugInfo/X86/cu-ranges.ll | 46 +- test/DebugInfo/X86/data_member_location.ll | 34 +- test/DebugInfo/X86/dbg-asm.s | 8 + test/DebugInfo/X86/dbg-at-specficiation.ll | 22 +- test/DebugInfo/X86/dbg-byval-parameter.ll | 48 +- test/DebugInfo/X86/dbg-const-int.ll | 36 +- test/DebugInfo/X86/dbg-const.ll | 42 +- test/DebugInfo/X86/dbg-declare-arg.ll | 118 +- test/DebugInfo/X86/dbg-declare.ll | 54 +- test/DebugInfo/X86/dbg-file-name.ll | 20 +- test/DebugInfo/X86/dbg-i128-const.ll | 38 +- test/DebugInfo/X86/dbg-merge-loc-entry.ll | 74 +- test/DebugInfo/X86/dbg-prolog-end.ll | 50 +- test/DebugInfo/X86/dbg-subrange.ll | 38 +- test/DebugInfo/X86/dbg-value-const-byref.ll | 62 +- test/DebugInfo/X86/dbg-value-dag-combine.ll | 56 +- test/DebugInfo/X86/dbg-value-inlined-parameter.ll | 110 +- test/DebugInfo/X86/dbg-value-isel.ll | 58 +- test/DebugInfo/X86/dbg-value-location.ll | 60 +- test/DebugInfo/X86/dbg-value-range.ll | 54 +- test/DebugInfo/X86/dbg-value-terminator.ll | 40 +- test/DebugInfo/X86/dbg_value_direct.ll | 64 +- test/DebugInfo/X86/debug-dead-local-var.ll | 44 +- test/DebugInfo/X86/debug-info-access.ll | 150 + .../X86/debug-info-block-captured-self.ll | 66 +- test/DebugInfo/X86/debug-info-blocks.ll | 250 +- test/DebugInfo/X86/debug-info-static-member.ll | 134 +- test/DebugInfo/X86/debug-loc-asan.ll | 50 +- test/DebugInfo/X86/debug-loc-offset.ll | 78 +- test/DebugInfo/X86/debug-ranges-offset.ll | 84 +- test/DebugInfo/X86/debug_frame.ll | 16 +- test/DebugInfo/X86/decl-derived-member.ll | 108 +- test/DebugInfo/X86/discriminator.ll | 34 +- .../DebugInfo/X86/dwarf-aranges-no-dwarf-labels.ll | 60 +- test/DebugInfo/X86/dwarf-aranges.ll | 43 +- test/DebugInfo/X86/dwarf-public-names.ll | 83 +- test/DebugInfo/X86/dwarf-pubnames-split.ll | 24 +- test/DebugInfo/X86/earlydup-crash.ll | 100 +- test/DebugInfo/X86/elf-names.ll | 104 +- test/DebugInfo/X86/empty-and-one-elem-array.ll | 81 +- test/DebugInfo/X86/empty-array.ll | 42 +- test/DebugInfo/X86/ending-run.ll | 40 +- test/DebugInfo/X86/enum-class.ll | 42 +- test/DebugInfo/X86/enum-fwd-decl.ll | 16 +- test/DebugInfo/X86/fission-cu.ll | 20 +- test/DebugInfo/X86/fission-hash.ll | 10 +- test/DebugInfo/X86/fission-inline.ll | 119 + test/DebugInfo/X86/fission-ranges.ll | 110 +- test/DebugInfo/X86/formal_parameter.ll | 52 +- test/DebugInfo/X86/generate-odr-hash.ll | 155 +- test/DebugInfo/X86/ghost-sdnode-dbgvalues.ll | 105 + test/DebugInfo/X86/gmlt.test | 2 + test/DebugInfo/X86/gnu-public-names-empty.ll | 10 +- test/DebugInfo/X86/gnu-public-names.ll | 173 +- test/DebugInfo/X86/inline-member-function.ll | 71 +- test/DebugInfo/X86/inline-seldag-test.ll | 58 +- test/DebugInfo/X86/instcombine-instrinsics.ll | 54 +- test/DebugInfo/X86/lexical_block.ll | 52 +- test/DebugInfo/X86/line-info.ll | 44 +- test/DebugInfo/X86/linkage-name.ll | 52 +- test/DebugInfo/X86/low-pc-cu.ll | 44 +- test/DebugInfo/X86/memberfnptr.ll | 44 + test/DebugInfo/X86/misched-dbg-value.ll | 178 +- test/DebugInfo/X86/multiple-aranges.ll | 34 +- test/DebugInfo/X86/multiple-at-const-val.ll | 60 +- test/DebugInfo/X86/nodebug_with_debug_loc.ll | 139 + test/DebugInfo/X86/nondefault-subrange-array.ll | 44 +- test/DebugInfo/X86/objc-fwd-decl.ll | 26 +- test/DebugInfo/X86/objc-property-void.ll | 66 +- test/DebugInfo/X86/op_deref.ll | 69 +- test/DebugInfo/X86/parameters.ll | 76 +- test/DebugInfo/X86/pieces-1.ll | 79 + test/DebugInfo/X86/pieces-2.ll | 91 + test/DebugInfo/X86/pieces-3.ll | 106 + test/DebugInfo/X86/pointer-type-size.ll | 26 +- test/DebugInfo/X86/pr11300.ll | 70 +- test/DebugInfo/X86/pr12831.ll | 336 +- test/DebugInfo/X86/pr13303.ll | 24 +- test/DebugInfo/X86/pr19307.ll | 130 +- test/DebugInfo/X86/processes-relocations.ll | 21 + test/DebugInfo/X86/prologue-stack.ll | 26 +- test/DebugInfo/X86/recursive_inlining.ll | 275 + test/DebugInfo/X86/ref_addr_relocation.ll | 36 +- test/DebugInfo/X86/reference-argument.ll | 144 +- test/DebugInfo/X86/rvalue-ref.ll | 36 +- test/DebugInfo/X86/sret.ll | 296 +- .../X86/stmt-list-multiple-compile-units.ll | 52 +- test/DebugInfo/X86/stmt-list.ll | 16 +- test/DebugInfo/X86/stringpool.ll | 16 +- test/DebugInfo/X86/struct-loc.ll | 22 +- test/DebugInfo/X86/subrange-type.ll | 38 +- test/DebugInfo/X86/subreg.ll | 31 +- test/DebugInfo/X86/subregisters.ll | 84 +- test/DebugInfo/X86/template.ll | 122 +- test/DebugInfo/X86/tls.ll | 38 +- test/DebugInfo/X86/type_units_with_addresses.ll | 74 +- test/DebugInfo/X86/union-template.ll | 64 +- test/DebugInfo/X86/vector.ll | 24 +- test/DebugInfo/X86/vla.ll | 70 +- test/DebugInfo/array.ll | 38 +- test/DebugInfo/block-asan.ll | 87 + test/DebugInfo/bug_null_debuginfo.ll | 6 +- test/DebugInfo/constant-pointers.ll | 38 +- test/DebugInfo/cross-cu-inlining.ll | 80 +- test/DebugInfo/cross-cu-linkonce-distinct.ll | 95 + test/DebugInfo/cross-cu-linkonce.ll | 50 +- test/DebugInfo/cu-line-tables.ll | 51 - test/DebugInfo/cu-range-hole.ll | 40 +- test/DebugInfo/cu-ranges.ll | 44 +- test/DebugInfo/dead-argument-order.ll | 50 +- test/DebugInfo/debug-info-always-inline.ll | 143 + test/DebugInfo/debug-info-qualifiers.ll | 82 +- test/DebugInfo/debuginfofinder-multiple-cu.ll | 34 +- test/DebugInfo/duplicate_inline.ll | 117 + test/DebugInfo/dwarf-public-names.ll | 82 +- test/DebugInfo/dwarfdump-accel.test | 63 + test/DebugInfo/dwarfdump-objc.test | 40 + test/DebugInfo/dwarfdump-ranges.test | 14 + test/DebugInfo/empty.ll | 10 +- test/DebugInfo/enum-types.ll | 78 + test/DebugInfo/enum.ll | 54 +- test/DebugInfo/global.ll | 28 +- test/DebugInfo/gmlt.test | 5 + test/DebugInfo/incorrect-variable-debugloc.ll | 116 +- test/DebugInfo/incorrect-variable-debugloc1.ll | 77 + test/DebugInfo/inheritance.ll | 104 +- test/DebugInfo/inline-debug-info-multiret.ll | 76 +- test/DebugInfo/inline-debug-info.ll | 76 +- test/DebugInfo/inline-no-debug-info.ll | 30 +- test/DebugInfo/inline-scopes.ll | 72 +- test/DebugInfo/inlined-arguments.ll | 64 +- test/DebugInfo/inlined-vars.ll | 54 +- test/DebugInfo/llvm-symbolizer.test | 25 +- test/DebugInfo/lto-comp-dir.ll | 44 +- test/DebugInfo/member-order.ll | 46 +- test/DebugInfo/member-pointers.ll | 30 +- test/DebugInfo/member-pointers.o | 0 test/DebugInfo/missing-abstract-variable.ll | 127 +- test/DebugInfo/missing-abstract-variable.o | 0 test/DebugInfo/multiline.ll | 82 + test/DebugInfo/namespace.ll | 342 +- test/DebugInfo/namespace_function_definition.ll | 24 +- .../namespace_inline_function_definition.ll | 54 +- test/DebugInfo/nodebug.ll | 51 + test/DebugInfo/restrict.ll | 36 +- test/DebugInfo/sugared-constants.ll | 68 +- test/DebugInfo/template-recursive-void.ll | 76 +- test/DebugInfo/tu-composite.ll | 136 +- test/DebugInfo/tu-member-pointer.ll | 24 +- test/DebugInfo/two-cus-from-same-file.ll | 66 +- test/DebugInfo/typedef.ll | 22 +- test/DebugInfo/unconditional-branch.ll | 45 +- test/DebugInfo/varargs.ll | 69 +- test/DebugInfo/version.ll | 24 +- test/ExecutionEngine/2002-12-16-ArgTest.ll | 1 - test/ExecutionEngine/2003-01-04-ArgumentBug.ll | 1 - test/ExecutionEngine/2003-01-04-LoopTest.ll | 1 - test/ExecutionEngine/2003-01-15-AlignmentTest.ll | 1 - test/ExecutionEngine/2003-05-06-LivenessClobber.ll | 1 - test/ExecutionEngine/2003-05-07-ArgumentTest.ll | 1 - test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll | 15 - test/ExecutionEngine/2003-06-04-bzip2-bug.ll | 19 - test/ExecutionEngine/2003-06-05-PHIBug.ll | 17 - test/ExecutionEngine/2003-08-15-AllocaAssertion.ll | 1 - test/ExecutionEngine/2003-08-21-EnvironmentTest.ll | 1 - .../2003-08-23-RegisterAllocatePhysReg.ll | 1 - ...-10-18-PHINode-ConstantExpr-CondCode-Failure.ll | 1 - test/ExecutionEngine/2005-12-02-TailCallBug.ll | 1 - test/ExecutionEngine/Interpreter/intrinsics.ll | 35 + test/ExecutionEngine/Interpreter/lit.local.cfg | 3 + test/ExecutionEngine/MCJIT/2002-12-16-ArgTest.ll | 2 +- .../MCJIT/2003-01-04-ArgumentBug.ll | 2 +- test/ExecutionEngine/MCJIT/2003-01-04-LoopTest.ll | 2 +- test/ExecutionEngine/MCJIT/2003-01-04-PhiTest.ll | 2 +- test/ExecutionEngine/MCJIT/2003-01-09-SARTest.ll | 2 +- test/ExecutionEngine/MCJIT/2003-01-10-FUCOM.ll | 2 +- .../MCJIT/2003-01-15-AlignmentTest.ll | 2 +- .../MCJIT/2003-05-06-LivenessClobber.ll | 2 +- .../MCJIT/2003-05-07-ArgumentTest.ll | 2 +- .../MCJIT/2003-05-11-PHIRegAllocBug.ll | 4 +- test/ExecutionEngine/MCJIT/2003-06-04-bzip2-bug.ll | 4 +- test/ExecutionEngine/MCJIT/2003-06-05-PHIBug.ll | 4 +- .../MCJIT/2003-08-15-AllocaAssertion.ll | 2 +- .../MCJIT/2003-08-21-EnvironmentTest.ll | 2 +- .../MCJIT/2003-08-23-RegisterAllocatePhysReg.ll | 2 +- ...-10-18-PHINode-ConstantExpr-CondCode-Failure.ll | 2 +- .../MCJIT/2005-12-02-TailCallBug.ll | 2 +- .../MCJIT/2007-12-10-APIntLoadStore.ll | 2 +- .../MCJIT/2008-06-05-APInt-OverAShr.ll | 2 +- .../ExecutionEngine/MCJIT/2010-01-15-UndefValue.ll | 2 +- .../MCJIT/2013-04-04-RelocAddend.ll | 2 +- test/ExecutionEngine/MCJIT/cross-module-a.ll | 2 +- .../ExecutionEngine/MCJIT/cross-module-sm-pic-a.ll | 4 +- test/ExecutionEngine/MCJIT/eh-lg-pic.ll | 4 +- test/ExecutionEngine/MCJIT/eh-sm-pic.ll | 4 +- test/ExecutionEngine/MCJIT/eh.ll | 4 +- test/ExecutionEngine/MCJIT/fpbitcast.ll | 2 +- test/ExecutionEngine/MCJIT/hello-sm-pic.ll | 2 +- test/ExecutionEngine/MCJIT/hello.ll | 2 +- test/ExecutionEngine/MCJIT/hello2.ll | 2 +- test/ExecutionEngine/MCJIT/load-object-a.ll | 6 +- test/ExecutionEngine/MCJIT/multi-module-a.ll | 2 +- test/ExecutionEngine/MCJIT/multi-module-eh-a.ll | 4 +- .../ExecutionEngine/MCJIT/multi-module-sm-pic-a.ll | 4 +- .../MCJIT/non-extern-addend-smallcodemodel.ll | 25 - test/ExecutionEngine/MCJIT/non-extern-addend.ll | 2 +- test/ExecutionEngine/MCJIT/pr13727.ll | 2 +- .../ExecutionEngine/MCJIT/remote/cross-module-a.ll | 2 +- .../MCJIT/remote/cross-module-sm-pic-a.ll | 2 +- .../ExecutionEngine/MCJIT/remote/multi-module-a.ll | 2 +- .../MCJIT/remote/multi-module-sm-pic-a.ll | 2 +- .../MCJIT/remote/simpletest-remote.ll | 2 +- test/ExecutionEngine/MCJIT/remote/stubs-remote.ll | 2 +- test/ExecutionEngine/MCJIT/remote/stubs-sm-pic.ll | 2 +- .../MCJIT/remote/test-common-symbols-remote.ll | 2 +- .../MCJIT/remote/test-data-align-remote.ll | 2 +- .../remote/test-fp-no-external-funcs-remote.ll | 2 +- .../remote/test-global-init-nonzero-remote.ll | 2 +- .../remote/test-global-init-nonzero-sm-pic.ll | 2 +- .../MCJIT/remote/test-ptr-reloc-remote.ll | 2 +- .../MCJIT/remote/test-ptr-reloc-sm-pic.ll | 2 +- test/ExecutionEngine/MCJIT/simplesttest.ll | 2 +- test/ExecutionEngine/MCJIT/simpletest.ll | 2 +- test/ExecutionEngine/MCJIT/stubs-sm-pic.ll | 2 +- test/ExecutionEngine/MCJIT/stubs.ll | 2 +- test/ExecutionEngine/MCJIT/test-arith.ll | 2 +- test/ExecutionEngine/MCJIT/test-branch.ll | 2 +- .../MCJIT/test-call-no-external-funcs.ll | 2 +- test/ExecutionEngine/MCJIT/test-call.ll | 2 +- test/ExecutionEngine/MCJIT/test-cast.ll | 2 +- .../MCJIT/test-common-symbols-alignment.ll | 2 +- test/ExecutionEngine/MCJIT/test-common-symbols.ll | 2 +- test/ExecutionEngine/MCJIT/test-constantexpr.ll | 2 +- test/ExecutionEngine/MCJIT/test-data-align.ll | 2 +- .../MCJIT/test-fp-no-external-funcs.ll | 2 +- test/ExecutionEngine/MCJIT/test-fp.ll | 2 +- test/ExecutionEngine/MCJIT/test-global-ctors.ll | 2 +- .../MCJIT/test-global-init-nonzero-sm-pic.ll | 2 +- .../MCJIT/test-global-init-nonzero.ll | 2 +- test/ExecutionEngine/MCJIT/test-global.ll | 2 +- test/ExecutionEngine/MCJIT/test-loadstore.ll | 2 +- test/ExecutionEngine/MCJIT/test-local.ll | 2 +- test/ExecutionEngine/MCJIT/test-logical.ll | 2 +- test/ExecutionEngine/MCJIT/test-loop.ll | 2 +- test/ExecutionEngine/MCJIT/test-phi.ll | 2 +- .../ExecutionEngine/MCJIT/test-ptr-reloc-sm-pic.ll | 2 +- test/ExecutionEngine/MCJIT/test-ptr-reloc.ll | 2 +- test/ExecutionEngine/MCJIT/test-ret.ll | 2 +- test/ExecutionEngine/MCJIT/test-return.ll | 2 +- test/ExecutionEngine/MCJIT/test-setcond-fp.ll | 2 +- test/ExecutionEngine/MCJIT/test-setcond-int.ll | 2 +- test/ExecutionEngine/MCJIT/test-shift.ll | 2 +- .../RuntimeDyld/AArch64/MachO_ARM64_relocations.s | 67 + .../RuntimeDyld/AArch64/lit.local.cfg | 3 + .../RuntimeDyld/ARM/MachO_ARM_PIC_relocations.s | 58 +- .../X86/MachO_i386_DynNoPIC_relocations.s | 45 + .../RuntimeDyld/X86/MachO_i386_eh_frame.s | 30 + .../RuntimeDyld/X86/MachO_x86-64_PIC_relocations.s | 18 +- test/ExecutionEngine/frem.ll | 20 + test/ExecutionEngine/hello.ll | 1 - test/ExecutionEngine/hello2.ll | 1 - test/ExecutionEngine/mov64zext32.ll | 1 - test/ExecutionEngine/simpletest.ll | 1 - test/ExecutionEngine/stubs.ll | 1 - .../ExecutionEngine/test-call-no-external-funcs.ll | 1 - test/ExecutionEngine/test-call.ll | 1 - test/ExecutionEngine/test-common-symbols.ll | 1 - test/ExecutionEngine/test-fp-no-external-funcs.ll | 1 - test/ExecutionEngine/test-fp.ll | 1 - test/ExecutionEngine/test-global-init-nonzero.ll | 1 - test/ExecutionEngine/test-global.ll | 1 - test/ExecutionEngine/test-loadstore.ll | 1 - test/ExecutionEngine/test-local.ll | 1 - test/Feature/NamedMDNode.ll | 4 +- test/Feature/NamedMDNode2.ll | 2 +- test/Feature/aliases.ll | 4 +- test/Feature/callingconventions.ll | 7 + test/Feature/comdat.ll | 10 +- test/Feature/md_on_instruction.ll | 14 +- test/Feature/metadata.ll | 14 +- test/Feature/optnone-llc.ll | 2 +- test/Feature/prologuedata.ll | 18 + test/Feature/weak_constant.ll | 2 +- test/FileCheck/check-empty.txt | 11 + test/FileCheck/validate-check-prefix.txt | 1 + .../AddressSanitizer/X86/asm_cfi.ll | 54 + .../Instrumentation/AddressSanitizer/X86/asm_cfi.s | 52 + .../AddressSanitizer/X86/asm_mov.ll | 24 +- .../Instrumentation/AddressSanitizer/X86/asm_mov.s | 12 +- .../X86/asm_mov_no_instrumentation.s | 2 + .../AddressSanitizer/X86/asm_rep_movs.ll | 87 + .../AddressSanitizer/X86/asm_rsp_mem_op.s | 45 + .../AddressSanitizer/X86/asm_swap_intel.s | 14 +- .../AddressSanitizer/X86/bug_11395.ll | 14 +- test/Instrumentation/AddressSanitizer/basic.ll | 4 +- .../AddressSanitizer/coverage-dbg.ll | 67 - test/Instrumentation/AddressSanitizer/coverage.ll | 60 - .../Instrumentation/AddressSanitizer/debug_info.ll | 48 +- .../AddressSanitizer/do-not-instrument-cstring.ll | 8 + .../AddressSanitizer/do-not-touch-comdat-global.ll | 2 +- .../AddressSanitizer/global_metadata.ll | 44 +- .../AddressSanitizer/instrument-dynamic-allocas.ll | 24 + .../AddressSanitizer/instrument_global.ll | 2 +- .../instrument_initializer_metadata.ll | 28 +- .../keep-instrumented_functions.ll | 23 - .../AddressSanitizer/stack_dynamic_alloca.ll | 42 + .../AddressSanitizer/stack_layout.ll | 20 +- test/Instrumentation/AddressSanitizer/ubsan.ll | 2 +- .../undecidable-dynamic-alloca-1.ll | 23 + .../DataFlowSanitizer/Inputs/debuglist.txt | 2 + test/Instrumentation/DataFlowSanitizer/abilist.ll | 55 +- .../DataFlowSanitizer/args-unreachable-bb.ll | 1 + test/Instrumentation/DataFlowSanitizer/arith.ll | 1 + test/Instrumentation/DataFlowSanitizer/call.ll | 1 + .../DataFlowSanitizer/debug-nonzero-labels.ll | 14 +- test/Instrumentation/DataFlowSanitizer/debug.ll | 36 + test/Instrumentation/DataFlowSanitizer/load.ll | 15 +- test/Instrumentation/DataFlowSanitizer/memset.ll | 1 + .../DataFlowSanitizer/prefix-rename.ll | 1 + test/Instrumentation/DataFlowSanitizer/store.ll | 14 + .../DataFlowSanitizer/union-large.ll | 3014 ++++++ test/Instrumentation/DataFlowSanitizer/union.ll | 1 + test/Instrumentation/InstrProfiling/no-counters.ll | 10 + test/Instrumentation/InstrProfiling/noruntime.ll | 16 + test/Instrumentation/InstrProfiling/platform.ll | 29 + test/Instrumentation/InstrProfiling/profiling.ll | 38 + .../Instrumentation/MemorySanitizer/array_types.ll | 89 + .../MemorySanitizer/byval-alignment.ll | 20 + .../MemorySanitizer/check-constant-shadow.ll | 15 + .../MemorySanitizer/do-not-emit-module-limits.ll | 21 - .../MemorySanitizer/missing_origin.ll | 14 + .../MemorySanitizer/origin-alignment.ll | 73 + .../MemorySanitizer/store-origin.ll | 52 +- .../MemorySanitizer/wrap_indirect_calls.ll | 60 - .../SanitizerCoverage/coverage-dbg.ll | 67 + test/Instrumentation/SanitizerCoverage/coverage.ll | 93 + .../SanitizerCoverage/coverage2-dbg.ll | 75 + test/Instrumentation/SanitizerCoverage/tracing.ll | 33 + .../ThreadSanitizer/read_from_global.ll | 6 +- test/Instrumentation/ThreadSanitizer/vptr_read.ll | 6 +- .../Instrumentation/ThreadSanitizer/vptr_update.ll | 6 +- test/JitListener/lit.local.cfg | 2 +- test/JitListener/multiple.ll | 167 + test/JitListener/simple.ll | 54 + test/JitListener/test-common-symbols.ll | 113 - test/JitListener/test-inline.ll | 212 - test/JitListener/test-parameters.ll | 211 - test/LTO/Inputs/bcsection.macho.s | 2 + test/LTO/Inputs/bcsection.s | 2 + test/LTO/Inputs/invalid.ll.bc | Bin 0 -> 332 bytes test/LTO/Inputs/list-symbols.ll | 4 + test/LTO/bcsection.ll | 21 + test/LTO/cfi_endproc.ll | 5 + test/LTO/diagnostic-handler-remarks.ll | 40 + test/LTO/invalid.ll | 4 + test/LTO/jump-table-type.ll | 4 +- test/LTO/linkonce_odr_func.ll | 10 + test/LTO/list-symbols.ll | 15 + test/Linker/2003-01-30-LinkerRename.ll | 19 +- test/Linker/2003-05-31-LinkerRename.ll | 29 +- test/Linker/2006-06-15-GlobalVarAlignment.ll | 8 - test/Linker/2008-03-05-AliasReference.ll | 2 +- test/Linker/2009-09-03-mdnode.ll | 5 +- test/Linker/2009-09-03-mdnode2.ll | 5 +- test/Linker/2011-08-04-DebugLoc.ll | 24 +- test/Linker/2011-08-04-DebugLoc2.ll | 24 +- test/Linker/2011-08-04-Metadata.ll | 27 +- test/Linker/2011-08-04-Metadata2.ll | 24 +- test/Linker/2011-08-18-unique-class-type.ll | 40 +- test/Linker/2011-08-18-unique-class-type2.ll | 40 +- test/Linker/2011-08-18-unique-debug-type.ll | 28 +- test/Linker/2011-08-18-unique-debug-type2.ll | 26 +- test/Linker/2011-08-22-ResolveAlias.ll | 52 +- test/Linker/2011-08-22-ResolveAlias2.ll | 52 +- test/Linker/ConstantGlobals.ll | 8 + test/Linker/ConstantGlobals1.ll | 10 - test/Linker/ConstantGlobals2.ll | 10 - test/Linker/ConstantGlobals3.ll | 9 - test/Linker/DbgDeclare.ll | 58 +- test/Linker/DbgDeclare2.ll | 62 +- test/Linker/Inputs/2003-01-30-LinkerRename.ll | 4 + test/Linker/Inputs/2003-05-31-LinkerRename.ll | 5 + test/Linker/Inputs/ConstantGlobals.ll | 2 + test/Linker/Inputs/alignment.ll | 12 + test/Linker/Inputs/comdat.ll | 12 +- test/Linker/Inputs/comdat2.ll | 2 +- test/Linker/Inputs/comdat3.ll | 2 +- test/Linker/Inputs/comdat4.ll | 2 +- test/Linker/Inputs/comdat5.ll | 16 +- test/Linker/Inputs/comdat8.ll | 4 + test/Linker/Inputs/constructor-comdat.ll | 7 + test/Linker/Inputs/ctors.ll | 6 + test/Linker/Inputs/distinct.ll | 13 + test/Linker/Inputs/ident.a.ll | 3 + test/Linker/Inputs/ident.b.ll | 2 + test/Linker/Inputs/linkage2.ll | 7 + test/Linker/Inputs/mdlocation.ll | 13 + .../Inputs/module-flags-dont-change-others.ll | 8 + test/Linker/Inputs/module-flags-pic-1-b.ll | 1 + test/Linker/Inputs/module-flags-pic-2-b.ll | 3 + test/Linker/Inputs/opaque.ll | 13 + test/Linker/Inputs/pr21374.ll | 4 + test/Linker/Inputs/redefinition.ll | 1 + .../replaced-function-matches-first-subprogram.ll | 27 + test/Linker/Inputs/testlink.ll | 56 + test/Linker/Inputs/type-unique-alias.ll | 4 + test/Linker/Inputs/type-unique-dst-types2.ll | 3 + test/Linker/Inputs/type-unique-dst-types3.ll | 2 + test/Linker/Inputs/type-unique-inheritance-a.ll | 58 +- test/Linker/Inputs/type-unique-inheritance-b.ll | 86 +- test/Linker/Inputs/type-unique-name.ll | 5 + test/Linker/Inputs/type-unique-opaque.ll | 6 + test/Linker/Inputs/type-unique-simple2-a.ll | 52 +- test/Linker/Inputs/type-unique-simple2-b.ll | 64 +- test/Linker/Inputs/type-unique-unrelated2.ll | 7 + test/Linker/Inputs/type-unique-unrelated3.ll | 7 + test/Linker/Inputs/unique-fwd-decl-b.ll | 3 + test/Linker/Inputs/unique-fwd-decl-order.ll | 6 + test/Linker/Inputs/visibility.ll | 26 + test/Linker/alignment.ll | 22 + test/Linker/comdat.ll | 20 +- test/Linker/comdat2.ll | 2 +- test/Linker/comdat3.ll | 2 +- test/Linker/comdat4.ll | 2 +- test/Linker/comdat5.ll | 2 +- test/Linker/comdat6.ll | 15 +- test/Linker/comdat7.ll | 9 +- test/Linker/comdat8.ll | 14 +- test/Linker/comdat9.ll | 19 + test/Linker/constructor-comdat.ll | 13 + test/Linker/ctors.ll | 15 + test/Linker/debug-info-version-a.ll | 10 +- test/Linker/debug-info-version-b.ll | 8 +- test/Linker/distinct.ll | 37 + test/Linker/global_ctors.ll | 1 + test/Linker/ident.ll | 9 + test/Linker/link-messages.ll | 10 - test/Linker/linkage2.ll | 14 + test/Linker/linkmdnode.ll | 2 +- test/Linker/linkmdnode2.ll | 4 +- test/Linker/linknamedmdnode.ll | 2 +- test/Linker/linknamedmdnode2.ll | 2 +- test/Linker/lto-attributes.ll | 10 + test/Linker/mdlocation.ll | 34 + test/Linker/metadata-a.ll | 12 +- test/Linker/metadata-b.ll | 4 +- test/Linker/module-flags-1-a.ll | 16 +- test/Linker/module-flags-1-b.ll | 6 +- test/Linker/module-flags-2-a.ll | 4 +- test/Linker/module-flags-2-b.ll | 2 +- test/Linker/module-flags-3-a.ll | 12 +- test/Linker/module-flags-3-b.ll | 4 +- test/Linker/module-flags-4-a.ll | 4 +- test/Linker/module-flags-4-b.ll | 4 +- test/Linker/module-flags-5-a.ll | 2 +- test/Linker/module-flags-5-b.ll | 2 +- test/Linker/module-flags-6-a.ll | 2 +- test/Linker/module-flags-6-b.ll | 2 +- test/Linker/module-flags-7-a.ll | 2 +- test/Linker/module-flags-7-b.ll | 2 +- test/Linker/module-flags-8-a.ll | 12 +- test/Linker/module-flags-8-b.ll | 4 +- test/Linker/module-flags-dont-change-others.ll | 26 + test/Linker/module-flags-pic-1-a.ll | 9 + test/Linker/module-flags-pic-2-a.ll | 10 + test/Linker/opaque.ll | 21 + test/Linker/pr21374.ll | 20 + test/Linker/pr21494.ll | 23 + test/Linker/prefixdata.ll | 9 - test/Linker/prologuedata.ll | 21 + test/Linker/redefinition.ll | 11 +- .../replaced-function-matches-first-subprogram.ll | 75 + test/Linker/targettriple.ll | 3 + test/Linker/testlink.ll | 104 + test/Linker/testlink1.ll | 101 - test/Linker/testlink2.ll | 58 - test/Linker/type-unique-alias.ll | 10 + test/Linker/type-unique-dst-types.ll | 19 + test/Linker/type-unique-name.ll | 13 + test/Linker/type-unique-odr-a.ll | 60 +- test/Linker/type-unique-odr-b.ll | 64 +- test/Linker/type-unique-opaque.ll | 16 + test/Linker/type-unique-simple-a.ll | 48 +- test/Linker/type-unique-simple-b.ll | 60 +- test/Linker/type-unique-simple2-a.ll | 102 +- test/Linker/type-unique-simple2-b.ll | 84 +- test/Linker/type-unique-src-type.ll | 24 + test/Linker/type-unique-type-array-a.ll | 129 + test/Linker/type-unique-type-array-b.ll | 108 + test/Linker/type-unique-unrelated.ll | 31 + test/Linker/unique-fwd-decl-a.ll | 9 + test/Linker/unique-fwd-decl-order.ll | 20 + test/Linker/unnamed-addr1-b.ll | 4 +- test/Linker/visibility.ll | 51 + test/Linker/visibility1.ll | 46 - test/Linker/visibility2.ll | 27 - test/Linker/weakextern.ll | 2 +- test/MC/AArch64/adrp-relocation.s | 2 +- test/MC/AArch64/arm64-be-datalayout.s | 2 +- test/MC/AArch64/arm64-elf-relocs.s | 2 +- test/MC/AArch64/arm64-system-encoding.s | 4 + test/MC/AArch64/arm64-tls-relocs.s | 2 +- test/MC/AArch64/basic-a64-diagnostics.s | 16 +- test/MC/AArch64/basic-a64-instructions.s | 20 +- test/MC/AArch64/elf_osabi_flags.s | 5 + test/MC/AArch64/inline-asm-modifiers.s | 2 +- test/MC/AArch64/inst-directive-diagnostic.s | 19 + test/MC/AArch64/inst-directive.s | 24 + test/MC/AArch64/single-slash.s | 6 + test/MC/AArch64/tls-relocs.s | 2 +- test/MC/ARM/arm-elf-relocation-diagnostics.s | 27 + test/MC/ARM/arm-elf-relocations.s | 37 + test/MC/ARM/arm-load-store-multiple-deprecated.s | 222 + test/MC/ARM/arm_instructions.s | 2 +- test/MC/ARM/basic-arm-instructions.s | 596 +- test/MC/ARM/coff-debugging-secrel.ll | 28 +- test/MC/ARM/coff-file.s | 6 +- test/MC/ARM/coproc-diag.s | 10 + test/MC/ARM/cps.s | 17 + test/MC/ARM/cpu-test.s | 13 + test/MC/ARM/d16.s | 24 + test/MC/ARM/diagnostics.s | 210 + test/MC/ARM/directive-arch-iwmmxt.s | 2 +- test/MC/ARM/directive-arch-iwmmxt2.s | 2 +- test/MC/ARM/directive-arch_extension-crc.s | 12 +- test/MC/ARM/directive-arch_extension-fp.s | 191 +- test/MC/ARM/directive-arch_extension-idiv.s | 4 +- test/MC/ARM/directive-arch_extension-mode-switch.s | 17 + test/MC/ARM/directive-arch_extension-simd.s | 152 +- test/MC/ARM/directive-arch_extension-toggle.s | 8 + test/MC/ARM/directive-cpu.s | 3 +- test/MC/ARM/directive-eabi_attribute-2.s | 98 - test/MC/ARM/directive-eabi_attribute-diagnostics.s | 5 + test/MC/ARM/directive-eabi_attribute-overwrite.s | 4 +- test/MC/ARM/directive-eabi_attribute.s | 302 +- test/MC/ARM/directive-fpu-instrs.s | 16 + test/MC/ARM/directive-thumb_func.s | 22 + test/MC/ARM/directive-unsupported.s | 68 + test/MC/ARM/dwarf-asm-multiple-sections-dwarf-2.s | 66 + test/MC/ARM/dwarf-asm-multiple-sections.s | 6 +- test/MC/ARM/ldr-pseudo-parse-errors.s | 2 +- test/MC/ARM/move-banked-regs.s | 220 + test/MC/ARM/neon-bitwise-encoding.s | 57 +- test/MC/ARM/neon-mov-vfp.s | 32 + test/MC/ARM/symbol-variants.s | 4 +- test/MC/ARM/thumb-diagnostics.s | 71 +- test/MC/ARM/thumb-load-store-multiple.s | 100 + test/MC/ARM/thumb-not-mclass.s | 26 + test/MC/ARM/thumb2-bxj.s | 10 + test/MC/ARM/thumb2-exception-return-mclass.s | 15 + test/MC/ARM/thumb2-ldrb-ldrh.s | 51 + test/MC/ARM/thumb2-ldrexd-strexd.s | 14 + test/MC/ARM/thumb2-mclass.s | 46 +- test/MC/ARM/thumb_rewrites.s | 52 + test/MC/ARM/thumbv7em.s | 53 + test/MC/ARM/v8_IT_manual.s | 7 +- test/MC/ARM/vfp4.s | 12 +- test/MC/ARM/virtexts-arm.s | 42 + test/MC/ARM/virtexts-thumb.s | 59 + test/MC/ARM/vorr-vbic-illegal-cases.s | 47 +- test/MC/AsmParser/comments-x86-darwin.s | 14 + test/MC/AsmParser/directive-warning.s | 26 + test/MC/AsmParser/directive_set.s | 4 +- test/MC/AsmParser/macro-exitm.s | 64 + test/MC/AsmParser/macros-darwin-vararg.s | 92 +- test/MC/COFF/alias.s | 9 +- test/MC/COFF/basic-coff-64.s | 3 +- test/MC/COFF/basic-coff.s | 3 +- test/MC/COFF/bigobj.py | 26 + test/MC/COFF/bss_section.ll | 2 +- test/MC/COFF/comm-align.s | 57 + test/MC/COFF/comm.ll | 4 +- test/MC/COFF/comm.s | 16 +- test/MC/COFF/const-gv-with-rel-init.ll | 11 + test/MC/COFF/feat00.s | 2 +- test/MC/COFF/file.s | 6 +- test/MC/COFF/ir-to-imgrel.ll | 2 +- test/MC/COFF/linker-options.ll | 11 +- test/MC/COFF/secidx.s | 2 + test/MC/COFF/section-invalid-flags.s | 3 + test/MC/COFF/section-name-encoding.s | 27 +- test/MC/COFF/section-passthru-flags.s | 7 + test/MC/COFF/seh-linkonce.s | 85 + test/MC/COFF/seh-section.s | 74 +- test/MC/COFF/simple-fixups.s | 7 +- test/MC/COFF/symbol-fragment-offset-64.s | 6 +- test/MC/COFF/symbol-fragment-offset.s | 6 +- test/MC/COFF/weak.s | 8 +- test/MC/Disassembler/ARM/arm-tests.txt | 4 +- .../MC/Disassembler/ARM/basic-arm-instructions.txt | 110 +- test/MC/Disassembler/ARM/d16.txt | 23 + .../Disassembler/ARM/invalid-thumb-MSR-MClass.txt | 35 + test/MC/Disassembler/ARM/invalid-virtexts.arm.txt | 10 + test/MC/Disassembler/ARM/move-banked-regs-arm.txt | 150 + .../MC/Disassembler/ARM/move-banked-regs-thumb.txt | 153 + test/MC/Disassembler/ARM/thumb-MSR-MClass.txt | 95 +- test/MC/Disassembler/ARM/thumb-tests.txt | 2 +- test/MC/Disassembler/ARM/thumb2-preloads.txt | 69 + test/MC/Disassembler/ARM/virtexts-arm.txt | 41 + test/MC/Disassembler/ARM/virtexts-thumb.txt | 61 + test/MC/Disassembler/Hexagon/alu32_alu.txt | 44 + test/MC/Disassembler/Hexagon/alu32_perm.txt | 32 + test/MC/Disassembler/Hexagon/alu32_pred.txt | 70 + test/MC/Disassembler/Hexagon/cr.txt | 66 + test/MC/Disassembler/Hexagon/j.txt | 156 + test/MC/Disassembler/Hexagon/jr.txt | 26 + test/MC/Disassembler/Hexagon/ld.txt | 292 + test/MC/Disassembler/Hexagon/lit.local.cfg | 3 + test/MC/Disassembler/Hexagon/memop.txt | 50 + test/MC/Disassembler/Hexagon/nv_j.txt | 134 + test/MC/Disassembler/Hexagon/nv_st.txt | 166 + test/MC/Disassembler/Hexagon/st.txt | 274 + test/MC/Disassembler/Hexagon/system_user.txt | 12 + test/MC/Disassembler/Hexagon/xtype_alu.txt | 164 + test/MC/Disassembler/Hexagon/xtype_bit.txt | 92 + test/MC/Disassembler/Hexagon/xtype_fp.txt | 110 + test/MC/Disassembler/Hexagon/xtype_mpy.txt | 202 + test/MC/Disassembler/Hexagon/xtype_perm.txt | 14 + test/MC/Disassembler/Hexagon/xtype_pred.txt | 66 + test/MC/Disassembler/Hexagon/xtype_shift.txt | 188 + test/MC/Disassembler/Mips/micromips.txt | 180 + test/MC/Disassembler/Mips/micromips_le.txt | 180 + test/MC/Disassembler/Mips/mips1/valid-mips1-el.txt | 116 + test/MC/Disassembler/Mips/mips1/valid-mips1.txt | 116 + test/MC/Disassembler/Mips/mips1/valid-xfail.txt | 5 + test/MC/Disassembler/Mips/mips2/valid-mips2-el.txt | 159 + test/MC/Disassembler/Mips/mips2/valid-mips2.txt | 159 + test/MC/Disassembler/Mips/mips3/valid-mips3-el.txt | 209 + test/MC/Disassembler/Mips/mips3/valid-mips3.txt | 209 + .../Disassembler/Mips/mips32/valid-mips32-el.txt | 294 + test/MC/Disassembler/Mips/mips32/valid-mips32.txt | 294 + .../Mips/mips32/valid-xfail-mips32.txt | 30 + test/MC/Disassembler/Mips/mips32r2.txt | 3 + .../Mips/mips32r2/valid-mips32r2-le.txt | 337 + .../Disassembler/Mips/mips32r2/valid-mips32r2.txt | 337 + .../Mips/mips32r2/valid-xfail-mips32r2.txt | 83 + test/MC/Disassembler/Mips/mips32r2_le.txt | 3 + test/MC/Disassembler/Mips/mips4/valid-mips4-el.txt | 229 + test/MC/Disassembler/Mips/mips4/valid-mips4.txt | 229 + .../Disassembler/Mips/mips4/valid-xfail-mips4.txt | 42 + .../MC/Disassembler/PowerPC/ppc64-encoding-4xx.txt | 26 + .../MC/Disassembler/PowerPC/ppc64-encoding-6xx.txt | 6 + .../Disassembler/PowerPC/ppc64-encoding-bookII.txt | 6 + .../PowerPC/ppc64-encoding-bookIII.txt | 20 + .../Disassembler/PowerPC/ppc64-encoding-e500.txt | 7 + .../MC/Disassembler/PowerPC/ppc64-encoding-ext.txt | 44 + test/MC/Disassembler/PowerPC/ppc64-encoding.txt | 7 + test/MC/Disassembler/X86/avx-512.txt | 9 +- test/MC/Disassembler/X86/intel-syntax-32.txt | 12 + test/MC/Disassembler/X86/intel-syntax.txt | 20 + test/MC/Disassembler/X86/invalid-cmp-imm.txt | 10 - test/MC/Disassembler/X86/moffs.txt | 106 +- test/MC/Disassembler/X86/prefixes.txt | 15 +- test/MC/Disassembler/X86/simple-tests.txt | 15 + test/MC/Disassembler/X86/x86-32.txt | 29 + test/MC/Disassembler/X86/x86-64.txt | 15 + test/MC/ELF/alias.s | 13 + test/MC/ELF/cfi-large-model.s | 27 + test/MC/ELF/cfi-version.ll | 26 +- test/MC/ELF/comdat.s | 4 +- test/MC/ELF/reloc-same-name-section.s | 31 + test/MC/ELF/section-sym-err.s | 6 + test/MC/ELF/section-sym.s | 91 + test/MC/ELF/section-sym2.s | 28 + test/MC/Hexagon/basic.ll | 7 + test/MC/Hexagon/inst_add.ll | 10 + test/MC/Hexagon/inst_add64.ll | 10 + test/MC/Hexagon/inst_and.ll | 10 + test/MC/Hexagon/inst_and64.ll | 10 + test/MC/Hexagon/inst_aslh.ll | 10 + test/MC/Hexagon/inst_asrh.ll | 10 + test/MC/Hexagon/inst_cmp_eq.ll | 10 + test/MC/Hexagon/inst_cmp_eqi.ll | 10 + test/MC/Hexagon/inst_cmp_gt.ll | 10 + test/MC/Hexagon/inst_cmp_gti.ll | 10 + test/MC/Hexagon/inst_cmp_lt.ll | 10 + test/MC/Hexagon/inst_cmp_ugt.ll | 10 + test/MC/Hexagon/inst_cmp_ugti.ll | 10 + test/MC/Hexagon/inst_cmp_ult.ll | 10 + test/MC/Hexagon/inst_or.ll | 10 + test/MC/Hexagon/inst_or64.ll | 10 + test/MC/Hexagon/inst_select.ll | 10 + test/MC/Hexagon/inst_sub.ll | 10 + test/MC/Hexagon/inst_sub64.ll | 10 + test/MC/Hexagon/inst_sxtb.ll | 10 + test/MC/Hexagon/inst_sxth.ll | 10 + test/MC/Hexagon/inst_xor.ll | 10 + test/MC/Hexagon/inst_xor64.ll | 10 + test/MC/Hexagon/inst_zxtb.ll | 10 + test/MC/Hexagon/inst_zxth.ll | 10 + test/MC/Hexagon/lit.local.cfg | 3 + test/MC/MachO/AArch64/darwin-ARM64-reloc.s | 355 +- test/MC/MachO/AArch64/mergeable.s | 59 + test/MC/MachO/AArch64/reloc-crash.s | 27 + test/MC/MachO/AArch64/reloc-crash2.s | 24 + test/MC/MachO/ARM/aliased-symbols.s | 4 +- test/MC/MachO/ARM/darwin-ARM-reloc.s | 6 +- test/MC/MachO/ARM/ios-version-min-load-command.s | 2 +- test/MC/MachO/ARM/static-movt-relocs.s | 57 +- test/MC/MachO/absolute.s | 18 +- test/MC/MachO/absolutize.s | 10 +- test/MC/MachO/bad-darwin-x86_64-reloc-expr1.s | 6 + test/MC/MachO/bad-darwin-x86_64-reloc-expr2.s | 6 + test/MC/MachO/comm-1.s | 10 +- test/MC/MachO/darwin-complex-difference.s | 6 +- test/MC/MachO/darwin-x86_64-diff-reloc-assign-2.s | 36 +- test/MC/MachO/darwin-x86_64-diff-relocs.s | 10 +- test/MC/MachO/darwin-x86_64-reloc.s | 679 +- test/MC/MachO/empty-dwarf-lines.s | 25 - test/MC/MachO/file.s | 41 +- test/MC/MachO/gen-dwarf.s | 14 +- test/MC/MachO/indirect-symbols.s | 12 +- test/MC/MachO/lcomm-attributes.s | 10 +- test/MC/MachO/linker-options.ll | 6 +- test/MC/MachO/osx-version-min-load-command.s | 2 +- test/MC/MachO/reloc.s | 400 +- test/MC/MachO/section-align-2.s | 6 +- test/MC/MachO/string-table.s | 6 +- test/MC/MachO/symbol-diff.s | 6 +- test/MC/MachO/symbol-flags.s | 50 +- test/MC/MachO/symbol-indirect.s | 20 +- test/MC/MachO/symbols-1.s | 40 +- test/MC/MachO/tbss.s | 6 +- test/MC/MachO/tls.s | 20 +- test/MC/MachO/tlv-reloc.s | 10 +- test/MC/MachO/variable-exprs.s | 40 +- test/MC/MachO/x86_32-symbols.s | 82 +- test/MC/MachO/x86_64-mergeable.s | 59 + test/MC/MachO/x86_64-symbols.s | 1246 +-- test/MC/MachO/zerofill-3.s | 10 +- test/MC/Mips/cpload-bad.s | 14 +- test/MC/Mips/cpload.s | 41 +- test/MC/Mips/elf-objdump.s | 11 - test/MC/Mips/micromips-16-bit-instructions.s | 126 +- test/MC/Mips/micromips-bad-branches.s | 8 + test/MC/Mips/micromips-branch-instructions.s | 10 + test/MC/Mips/micromips-branch7.s | 27 + test/MC/Mips/micromips-control-instructions.s | 42 + test/MC/Mips/micromips-fpu-instructions.s | 6 + test/MC/Mips/micromips-func-addr.s | 16 + test/MC/Mips/micromips-invalid.s | 68 + test/MC/Mips/micromips-jump-instructions.s | 10 + test/MC/Mips/micromips-label-test-sections.s | 35 + test/MC/Mips/micromips-label-test.s | 54 + test/MC/Mips/micromips-loadstore-instructions.s | 89 +- test/MC/Mips/mips-expansions-bad.s | 4 +- test/MC/Mips/mips-expansions.s | 20 + test/MC/Mips/mips-hwr-register-names.s | 199 + test/MC/Mips/mips-jump-delay-slots.s | 122 + test/MC/Mips/mips-noat.s | 4 +- test/MC/Mips/mips-pdr-bad.s | 42 + test/MC/Mips/mips-pdr.s | 64 + test/MC/Mips/mips1/invalid-mips2.s | 24 + test/MC/Mips/mips1/invalid-mips3.s | 4 + test/MC/Mips/mips1/invalid-mips32r2.s | 11 + test/MC/Mips/mips1/invalid-mips4-wrong-error.s | 2 + test/MC/Mips/mips1/invalid-mips5-wrong-error.s | 76 +- test/MC/Mips/mips1/valid.s | 5 + test/MC/Mips/mips2/invalid-mips3.s | 4 + test/MC/Mips/mips2/invalid-mips32r2.s | 2 + test/MC/Mips/mips2/invalid-mips4-wrong-error.s | 2 + test/MC/Mips/mips2/invalid-mips5-wrong-error.s | 76 +- test/MC/Mips/mips2/valid.s | 29 + test/MC/Mips/mips3/invalid-mips32r2.s | 11 + test/MC/Mips/mips3/invalid-mips4-wrong-error.s | 10 + test/MC/Mips/mips3/invalid-mips5-wrong-error.s | 76 +- test/MC/Mips/mips3/valid.s | 33 + test/MC/Mips/mips32/invalid-mips32r2.s | 2 + test/MC/Mips/mips32/valid.s | 31 + test/MC/Mips/mips32r2/valid-xfail.s | 1 - test/MC/Mips/mips32r2/valid.s | 45 +- test/MC/Mips/mips32r6/invalid-mips1-wrong-error.s | 12 +- test/MC/Mips/mips32r6/invalid-mips1.s | 4 + test/MC/Mips/mips32r6/invalid-mips2-wrong-error.s | 14 +- test/MC/Mips/mips32r6/invalid-mips2.s | 12 + test/MC/Mips/mips32r6/invalid-mips32-wrong-error.s | 20 +- test/MC/Mips/mips32r6/invalid-mips32.s | 2 + test/MC/Mips/mips32r6/invalid-mips4-wrong-error.s | 16 +- test/MC/Mips/mips32r6/invalid-mips4.s | 2 + test/MC/Mips/mips32r6/invalid-mips5-wrong-error.s | 8 +- test/MC/Mips/mips32r6/valid.s | 23 + test/MC/Mips/mips4/invalid-mips32r2.s | 11 + test/MC/Mips/mips4/invalid-mips5-wrong-error.s | 76 +- test/MC/Mips/mips4/valid.s | 35 + test/MC/Mips/mips5/invalid-mips32r2.s | 11 + test/MC/Mips/mips5/valid.s | 35 + test/MC/Mips/mips64-register-names-n32-n64.s | 26 +- test/MC/Mips/mips64/invalid-mips32r2.s | 11 + test/MC/Mips/mips64/valid.s | 35 + test/MC/Mips/mips64r2/valid-xfail.s | 1 - test/MC/Mips/mips64r2/valid.s | 48 +- test/MC/Mips/mips64r6/invalid-mips1-wrong-error.s | 12 +- test/MC/Mips/mips64r6/invalid-mips1.s | 4 + test/MC/Mips/mips64r6/invalid-mips2.s | 12 + test/MC/Mips/mips64r6/invalid-mips3-wrong-error.s | 16 +- test/MC/Mips/mips64r6/invalid-mips32-wrong-error.s | 20 +- test/MC/Mips/mips64r6/invalid-mips4-wrong-error.s | 16 +- test/MC/Mips/mips64r6/invalid-mips4.s | 2 + test/MC/Mips/mips64r6/invalid-mips5-wrong-error.s | 82 +- test/MC/Mips/mips64r6/valid.s | 27 + test/MC/Mips/mips_directives_bad.s | 20 +- test/MC/Mips/msa/set-msa-directive-bad.s | 11 + test/MC/Mips/msa/set-msa-directive.s | 22 + test/MC/Mips/nacl-mask.s | 9 +- test/MC/Mips/octeon-instructions.s | 8 + test/MC/Mips/set-arch.s | 55 + test/MC/Mips/set-at-directive-explicit-at.s | 10 +- test/MC/Mips/set-mips-directives-bad.s | 30 + test/MC/Mips/set-mips-directives.s | 51 + test/MC/Mips/set-mips0-directive.s | 27 + test/MC/Mips/set-mips16-directive.s | 10 + test/MC/Mips/set-nodsp.s | 12 + test/MC/Mips/set-push-pop-directives-bad.s | 14 + test/MC/Mips/set-push-pop-directives.s | 53 + test/MC/Mips/unaligned-nops.s | 4 + test/MC/PowerPC/lcomm.s | 21 + test/MC/PowerPC/ppc-reloc.s | 2 + test/MC/PowerPC/ppc32-ba.s | 6 + test/MC/PowerPC/ppc64-encoding-4xx.s | 167 + test/MC/PowerPC/ppc64-encoding-6xx.s | 109 + test/MC/PowerPC/ppc64-encoding-bookII.s | 18 + test/MC/PowerPC/ppc64-encoding-bookIII.s | 138 +- test/MC/PowerPC/ppc64-encoding-e500.s | 11 + test/MC/PowerPC/ppc64-encoding-ext.s | 201 + test/MC/PowerPC/ppc64-encoding-spe.s | 622 ++ test/MC/PowerPC/ppc64-encoding.s | 18 +- test/MC/PowerPC/ppc64-fixup-apply.s | 20 +- test/MC/PowerPC/ppc64-fixups.s | 12 + test/MC/PowerPC/vsx.s | 42 +- test/MC/R600/lit.local.cfg | 2 + test/MC/R600/sopp.s | 52 + test/MC/SystemZ/lit.local.cfg | 3 + test/MC/X86/AlignedBundling/labeloffset.s | 83 + test/MC/X86/AlignedBundling/long-nop-pad.s | 2 +- test/MC/X86/AlignedBundling/nesting.s | 67 + test/MC/X86/avx512-encodings.s | 1632 ++++ test/MC/X86/avx512bw-encoding.s | 73 + test/MC/X86/avx512vl-encoding.s | 449 + test/MC/X86/compact-unwind.s | 72 + test/MC/X86/intel-syntax-2.s | 8 + test/MC/X86/intel-syntax-ambiguous.s | 47 + test/MC/X86/intel-syntax-error.s | 13 + test/MC/X86/intel-syntax-ptr-sized.s | 20 + test/MC/X86/intel-syntax-unsized-memory.s | 29 + test/MC/X86/intel-syntax.s | 61 +- test/MC/X86/macho-uleb.s | 7 + test/MC/X86/reloc-macho.s | 9 + test/MC/X86/sgx-encoding.s | 9 + test/MC/X86/shuffle-comments.s | 5 + test/MC/X86/stackmap-nops.ll | 4 + test/MC/X86/validate-inst-att.s | 7 + test/MC/X86/validate-inst-intel.s | 9 + test/MC/X86/x86-32-coverage.s | 18 +- test/MC/X86/x86-32-ms-inline-asm.s | 4 + test/MC/X86/x86-64-avx512bw.s | 1021 +++ test/MC/X86/x86-64-avx512bw_vl.s | 1785 ++++ test/MC/X86/x86-64-avx512dq.s | 129 + test/MC/X86/x86-64-avx512dq_vl.s | 113 + test/MC/X86/x86-64-avx512f_vl.s | 6653 ++++++++++++++ test/MC/X86/x86_errors.s | 4 + test/MC/X86/x86_operands.s | 5 + test/Makefile | 23 +- test/Object/AArch64/yaml2obj-elf-aarch64-rel.yaml | 55 + test/Object/ARM/macho-data-in-code.test | 2 +- test/Object/Inputs/COFF/long-section-name.yaml | 11 + test/Object/Inputs/COFF/section-aux-symbol.yaml | 167 + test/Object/Inputs/macho-archive-unsorted-x86_64.a | Bin 0 -> 1304 bytes test/Object/Inputs/macho-no-exports.dylib | Bin 0 -> 4208 bytes test/Object/Inputs/macho-rpath-x86_64 | Bin 0 -> 4296 bytes test/Object/Inputs/macho-zero-ncmds | Bin 0 -> 32 bytes test/Object/Inputs/micro-mips.elf-mipsel | Bin 0 -> 2394 bytes test/Object/Inputs/mri-crlf.mri | 2 + test/Object/Inputs/thin.a | Bin 0 -> 474 bytes test/Object/Inputs/trivial-label-test.elf-x86-64 | Bin 0 -> 741 bytes test/Object/Mips/objdump-micro-mips.test | 12 + test/Object/X86/nm-ir.ll | 2 +- test/Object/X86/objdump-cfg-invalid-opcode.yaml | 58 - test/Object/X86/objdump-cfg-textatomsize.yaml | 39 - test/Object/X86/objdump-cfg.yaml | 86 - .../objdump-disassembly-inline-relocations.test | 6 +- test/Object/X86/objdump-disassembly-symbolic.test | 68 - test/Object/X86/objdump-label.test | 10 + test/Object/archive-error-tmp.txt | 2 - test/Object/archive-symtab.test | 1 + test/Object/archive-toc.test | 8 + test/Object/coff-archive-short.test | 2 +- test/Object/coff-archive.test | 2 +- test/Object/mri-addlib.test | 14 + test/Object/mri-addmod.test | 33 + test/Object/mri-crlf.test | 1 + test/Object/mri1.test | 6 + test/Object/mri2.test | 7 + test/Object/mri3.test | 6 + test/Object/mri4.test | 4 + test/Object/mri5.test | 2 + test/Object/nm-archive.test | 11 +- test/Object/nm-trivial-object.test | 53 +- test/Object/nm-universal-binary.test | 20 + test/Object/obj2yaml-coff-long-section-name.test | 3 + test/Object/obj2yaml-coff-section-aux-symbol.test | 96 + test/Object/objdump-export-list.test | 4 + test/Object/objdump-macho-quirks.test | 9 + test/Object/objdump-private-headers.test | 7 + test/Object/objdump-reloc-shared.test | 5 + test/Object/objdump-relocations.test | 6 +- .../yaml2obj-elf-file-headers-with-e_flags.yaml | 6 +- test/Object/yaml2obj-elf-symbol-visibility.yaml | 4 +- test/Other/Inputs/block-info-only.bc | Bin 0 -> 64 bytes test/Other/Inputs/has-block-info.bc | Bin 0 -> 108 bytes test/Other/Inputs/no-block-info.bc | Bin 0 -> 48 bytes test/Other/bcanalyzer-block-info.txt | 32 + test/Other/link-opts.ll | 13 - test/Other/lit-unicode.txt | 3 + test/Other/new-pass-manager.ll | 258 +- test/Other/pass-pipeline-parsing.ll | 132 +- test/SymbolRewriter/rewrite.ll | 59 + test/SymbolRewriter/rewrite.map | 46 + test/TableGen/BitOffsetDecoder.td | 74 + test/TableGen/BitsInit.td | 85 + test/TableGen/ClassInstanceValue.td | 19 + test/TableGen/ForeachList.td | 1 - test/TableGen/ForeachLoop.td | 1 - test/TableGen/NestedForeach.td | 1 - test/TableGen/SiblingForeach.td | 1 - test/TableGen/if.td | 2 +- test/TableGen/ifbit.td | 2 + test/TableGen/intrinsic-varargs.td | 2 +- test/TableGen/list-element-bitref.td | 2 +- test/TableGen/math.td | 8 + test/Transforms/AddDiscriminators/basic.ll | 34 +- test/Transforms/AddDiscriminators/first-only.ll | 58 +- test/Transforms/AddDiscriminators/multiple.ll | 34 +- .../AddDiscriminators/no-discriminators.ll | 46 +- test/Transforms/AlignmentFromAssumptions/simple.ll | 215 + .../AlignmentFromAssumptions/simple32.ll | 215 + .../AlignmentFromAssumptions/start-unk.ll | 154 + test/Transforms/ArgumentPromotion/dbg.ll | 26 +- test/Transforms/ArgumentPromotion/fp80.ll | 58 + test/Transforms/ArgumentPromotion/reserve-tbaa.ll | 26 +- test/Transforms/ArgumentPromotion/tail.ll | 2 + test/Transforms/ArgumentPromotion/variadic.ll | 28 + .../AtomicExpand/ARM/atomic-expansion-v7.ll | 364 + .../AtomicExpand/ARM/atomic-expansion-v8.ll | 226 + test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll | 98 + test/Transforms/AtomicExpand/ARM/lit.local.cfg | 3 + .../ARM/atomic-expansion-v7.ll | 364 - .../ARM/atomic-expansion-v8.ll | 226 - .../AtomicExpandLoadLinked/ARM/cmpxchg-weak.ll | 97 - .../AtomicExpandLoadLinked/ARM/lit.local.cfg | 3 - test/Transforms/BBVectorize/loop1.ll | 2 +- test/Transforms/BBVectorize/metadata.ll | 8 +- .../2007-10-19-InlineAsmDirectives.ll | 2 +- .../CodeGenPrepare/AArch64/lit.local.cfg | 3 + .../CodeGenPrepare/AArch64/trunc-weird-user.ll | 36 + test/Transforms/ConstProp/trunc_vec.ll | 9 + test/Transforms/CorrelatedValuePropagation/icmp.ll | 63 + test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll | 84 +- test/Transforms/DeadArgElim/dbginfo.ll | 99 +- test/Transforms/DeadArgElim/dead_vaargs.ll | 36 +- .../2011-03-25-DSEMiscompile.ll | 6 +- test/Transforms/DeadStoreElimination/atomic.ll | 133 +- .../DeadStoreElimination/const-pointers.ll | 1 + .../Transforms/DeadStoreElimination/inst-limits.ll | 33 +- .../DeadStoreElimination/no-targetdata.ll | 30 +- test/Transforms/DebugIR/crash.ll | 42 - test/Transforms/DebugIR/exception.ll | 127 - test/Transforms/DebugIR/function.ll | 51 - test/Transforms/DebugIR/simple-addrspace.ll | 13 - test/Transforms/DebugIR/simple.ll | 25 - test/Transforms/DebugIR/struct.ll | 24 - test/Transforms/DebugIR/vector.ll | 93 - test/Transforms/EarlyCSE/basic.ll | 74 + test/Transforms/FunctionAttrs/optnone-simple.ll | 135 + test/Transforms/FunctionAttrs/optnone.ll | 24 + .../Transforms/GCOVProfiling/function-numbering.ll | 56 + test/Transforms/GCOVProfiling/global-ctor.ll | 36 +- test/Transforms/GCOVProfiling/linezero.ll | 105 +- test/Transforms/GCOVProfiling/linkagename.ll | 24 +- test/Transforms/GCOVProfiling/return-block.ll | 66 + test/Transforms/GCOVProfiling/version.ll | 30 +- test/Transforms/GVN/2009-03-10-PREOnVoid.ll | 28 +- test/Transforms/GVN/atomic.ll | 71 +- test/Transforms/GVN/cond_br2.ll | 12 +- test/Transforms/GVN/condprop.ll | 48 + test/Transforms/GVN/edge.ll | 35 + test/Transforms/GVN/fpmath.ll | 4 +- test/Transforms/GVN/invariant-load.ll | 2 +- .../GVN/load-from-unreachable-predecessor.ll | 20 + test/Transforms/GVN/load-pre-nonlocal.ll | 12 +- test/Transforms/GVN/noalias.ll | 43 + test/Transforms/GVN/pre-gep-load.ll | 49 + test/Transforms/GVN/preserve-tbaa.ll | 8 +- test/Transforms/GVN/range.ll | 32 +- test/Transforms/GVN/tbaa.ll | 30 +- .../Transforms/GlobalDCE/2009-01-05-DeadAliases.ll | 6 +- .../GlobalDCE/2009-02-17-AliasUsesAliasee.ll | 2 +- test/Transforms/GlobalDCE/deadblockaddr.ll | 16 + test/Transforms/GlobalDCE/pr20981.ll | 17 + .../GlobalOpt/2009-02-15-ResolveAlias.ll | 2 +- test/Transforms/GlobalOpt/2009-03-05-dbg.ll | 52 +- test/Transforms/GlobalOpt/alias-resolve.ll | 8 +- .../GlobalOpt/alias-used-address-space.ll | 6 +- test/Transforms/GlobalOpt/alias-used-section.ll | 2 +- test/Transforms/GlobalOpt/alias-used.ll | 14 +- .../GlobalOpt/constantfold-initializers.ll | 17 +- .../GlobalOpt/externally-initialized-global-ctr.ll | 2 +- test/Transforms/GlobalOpt/metadata.ll | 16 +- test/Transforms/GlobalOpt/pr21191.ll | 19 + test/Transforms/GlobalOpt/preserve-comdats.ll | 37 + .../IndVarSimplify/2011-09-10-widen-nsw.ll | 23 +- test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg | 2 + .../IndVarSimplify/NVPTX/no-widen-expensive.ll | 37 + .../IndVarSimplify/backedge-on-min-max.ll | 453 + .../Transforms/IndVarSimplify/lftr-extend-const.ll | 2 +- test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 3 +- test/Transforms/IndVarSimplify/sharpen-range.ll | 113 + .../IndVarSimplify/strengthen-overflow.ll | 214 + .../IndVarSimplify/use-range-metadata.ll | 37 + test/Transforms/IndVarSimplify/verify-scev.ll | 8 +- test/Transforms/IndVarSimplify/widen-loop-comp.ll | 191 + test/Transforms/Inline/align.ll | 98 + test/Transforms/Inline/byval-tail-call.ll | 9 +- test/Transforms/Inline/debug-invoke.ll | 14 +- test/Transforms/Inline/ephemeral.ll | 32 + test/Transforms/Inline/ignore-debug-info.ll | 28 +- test/Transforms/Inline/inline-musttail-varargs.ll | 22 + test/Transforms/Inline/inline-vla.ll | 2 +- test/Transforms/Inline/inline_dbg_declare.ll | 96 + test/Transforms/Inline/noalias-calls.ll | 44 + test/Transforms/Inline/noalias-cs.ll | 84 + test/Transforms/Inline/noalias.ll | 76 + test/Transforms/Inline/noalias2.ll | 97 + test/Transforms/Inline/optimization-remarks.ll | 2 +- test/Transforms/Inline/pr21206.ll | 18 + .../InstCombine/2007-09-10-AliasConstFold.ll | 2 +- .../InstCombine/2007-09-17-AliasConstFold2.ll | 2 +- .../InstCombine/2007-10-10-EliminateMemCpy.ll | 2 +- .../InstCombine/2008-02-16-SDivOverflow.ll | 14 - .../InstCombine/2008-05-23-CompareFold.ll | 5 +- test/Transforms/InstCombine/2008-11-08-FCmp.ll | 7 + .../InstCombine/2011-06-13-nsw-alloca.ll | 5 +- test/Transforms/InstCombine/AddOverFlow.ll | 4 +- test/Transforms/InstCombine/add2.ll | 44 +- test/Transforms/InstCombine/add4.ll | 102 - test/Transforms/InstCombine/addnegneg.ll | 1 - test/Transforms/InstCombine/alias-recursion.ll | 24 + test/Transforms/InstCombine/align-attr.ll | 15 + test/Transforms/InstCombine/and-compare.ll | 8 +- test/Transforms/InstCombine/and-xor-merge.ll | 11 +- test/Transforms/InstCombine/and2.ll | 25 +- .../InstCombine/apint-call-cast-target.ll | 9 +- test/Transforms/InstCombine/apint-sub.ll | 6 - test/Transforms/InstCombine/assume-loop-align.ll | 47 + test/Transforms/InstCombine/assume-redundant.ll | 55 + test/Transforms/InstCombine/assume.ll | 265 + test/Transforms/InstCombine/assume2.ll | 174 + test/Transforms/InstCombine/atomic.ll | 8 - .../InstCombine/bitcast-alias-function.ll | 30 +- test/Transforms/InstCombine/bitcast-store.ll | 10 +- test/Transforms/InstCombine/bswap-fold.ll | 184 +- test/Transforms/InstCombine/call-cast-target.ll | 38 +- test/Transforms/InstCombine/canonicalize_branch.ll | 8 +- test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll | 454 + test/Transforms/InstCombine/cast.ll | 128 +- .../constant-fold-address-space-pointer.ll | 7 +- test/Transforms/InstCombine/constant-fold-alias.ll | 40 + test/Transforms/InstCombine/constant-fold-math.ll | 9 + test/Transforms/InstCombine/debug-line.ll | 22 +- test/Transforms/InstCombine/debuginfo.ll | 60 +- test/Transforms/InstCombine/descale-zero.ll | 3 +- test/Transforms/InstCombine/devirt.ll | 39 - test/Transforms/InstCombine/div.ll | 156 +- .../InstCombine/double-float-shrink-1.ll | 227 +- test/Transforms/InstCombine/fabs.ll | 100 + test/Transforms/InstCombine/fast-math.ll | 180 +- test/Transforms/InstCombine/fcmp.ll | 82 + .../Transforms/InstCombine/float-shrink-compare.ll | 38 + test/Transforms/InstCombine/fmul.ll | 29 + test/Transforms/InstCombine/fold-phi.ll | 36 +- test/Transforms/InstCombine/fpcast.ll | 32 + test/Transforms/InstCombine/getelementptr.ll | 89 +- test/Transforms/InstCombine/icmp-logical.ll | 20 + test/Transforms/InstCombine/icmp-range.ll | 61 + test/Transforms/InstCombine/icmp-shr.ll | 378 + test/Transforms/InstCombine/icmp.ll | 213 +- test/Transforms/InstCombine/intrinsics.ll | 116 +- test/Transforms/InstCombine/load-addrspace-cast.ll | 12 - test/Transforms/InstCombine/load.ll | 32 + test/Transforms/InstCombine/loadstore-metadata.ll | 86 + test/Transforms/InstCombine/malloc-free-delete.ll | 23 + test/Transforms/InstCombine/maxnum.ll | 222 + test/Transforms/InstCombine/memcmp-1.ll | 2 +- test/Transforms/InstCombine/memcpy_chk-1.ll | 13 + test/Transforms/InstCombine/minnum.ll | 244 + test/Transforms/InstCombine/mul.ll | 91 + test/Transforms/InstCombine/narrow-switch.ll | 123 + test/Transforms/InstCombine/no_cgscc_assert.ll | 19 + test/Transforms/InstCombine/not-fcmp.ll | 7 +- test/Transforms/InstCombine/not.ll | 4 +- .../InstCombine/objsize-address-space.ll | 2 +- test/Transforms/InstCombine/objsize.ll | 4 +- test/Transforms/InstCombine/or-xor.ll | 83 + test/Transforms/InstCombine/or.ll | 108 + test/Transforms/InstCombine/overflow-mul.ll | 13 + test/Transforms/InstCombine/pr12251.ll | 2 +- test/Transforms/InstCombine/pr12338.ll | 2 +- test/Transforms/InstCombine/pr21199.ll | 25 + test/Transforms/InstCombine/pr21210.ll | 50 + test/Transforms/InstCombine/pr21651.ll | 20 + test/Transforms/InstCombine/pr21891.ll | 18 + test/Transforms/InstCombine/range-check.ll | 159 + test/Transforms/InstCombine/select-cmp-br.ll | 155 + test/Transforms/InstCombine/select.ll | 386 +- test/Transforms/InstCombine/shift.ll | 58 +- test/Transforms/InstCombine/signext.ll | 27 +- test/Transforms/InstCombine/statepoint.ll | 52 + test/Transforms/InstCombine/store.ll | 10 +- test/Transforms/InstCombine/strcmp-1.ll | 2 +- test/Transforms/InstCombine/strncmp-1.ll | 4 +- test/Transforms/InstCombine/struct-assign-tbaa.ll | 18 +- test/Transforms/InstCombine/sub-xor.ll | 2 +- test/Transforms/InstCombine/sub.ll | 90 +- .../InstCombine/unordered-fcmp-select.ll | 125 + test/Transforms/InstCombine/vec_demanded_elts.ll | 27 + test/Transforms/InstCombine/vsx-unaligned.ll | 44 + test/Transforms/InstCombine/xor.ll | 86 +- test/Transforms/InstCombine/xor2.ll | 90 + test/Transforms/InstMerge/ld_hoist1.ll | 64 + test/Transforms/InstMerge/st_sink_barrier_call.ll | 43 + .../InstMerge/st_sink_no_barrier_call.ll | 45 + .../InstMerge/st_sink_no_barrier_load.ll | 43 + .../InstMerge/st_sink_no_barrier_store.ll | 42 + test/Transforms/InstMerge/st_sink_two_stores.ll | 47 + test/Transforms/InstMerge/st_sink_with_barrier.ll | 42 + test/Transforms/InstSimplify/AndOrXor.ll | 183 + test/Transforms/InstSimplify/ashr-nop.ll | 10 - test/Transforms/InstSimplify/assume.ll | 13 + test/Transforms/InstSimplify/compare.ll | 199 +- test/Transforms/InstSimplify/exact-nsw-nuw.ll | 16 + test/Transforms/InstSimplify/fold-builtin-fma.ll | 119 + test/Transforms/InstSimplify/gep.ll | 80 + test/Transforms/InstSimplify/noalias-ptr.ll | 259 + test/Transforms/InstSimplify/rem.ll | 28 + test/Transforms/InstSimplify/select.ll | 161 + test/Transforms/InstSimplify/shr-nop.ll | 346 + test/Transforms/InstSimplify/undef.ll | 105 + test/Transforms/InstSimplify/vector_ptr_bitcast.ll | 35 + .../Internalize/2009-01-05-InternalizeAliases.ll | 4 +- test/Transforms/Internalize/local-visibility.ll | 4 +- test/Transforms/JumpThreading/assume-edge-dom.ll | 39 + test/Transforms/JumpThreading/assume.ll | 68 + test/Transforms/JumpThreading/conservative-lvi.ll | 58 + test/Transforms/JumpThreading/pr22086.ll | 28 + test/Transforms/JumpThreading/thread-loads.ll | 39 +- test/Transforms/LCSSA/indirectbr.ll | 40 +- .../LICM/2011-04-06-PromoteResultOfPromotion.ll | 14 +- .../LICM/2014-09-10-doFinalizationAssert.ll | 30 + test/Transforms/LICM/PR19798.ll | 22 + test/Transforms/LICM/debug-value.ll | 58 +- test/Transforms/LICM/hoist-invariant-load.ll | 2 +- test/Transforms/LICM/preheader-safe.ll | 69 + test/Transforms/LICM/promote-order.ll | 10 +- test/Transforms/LICM/scalar_promote.ll | 12 +- test/Transforms/LICM/sinking.ll | 78 + test/Transforms/LoadCombine/load-combine-aa.ll | 39 + test/Transforms/LoadCombine/load-combine-assume.ll | 44 + test/Transforms/LoopIdiom/debug-line.ll | 50 +- test/Transforms/LoopRotate/dbgvalue.ll | 62 +- test/Transforms/LoopRotate/nosimplifylatch.ll | 34 + test/Transforms/LoopRotate/simplifylatch.ll | 2 +- test/Transforms/LoopSimplify/merge-exits.ll | 46 +- .../LoopStrengthReduce/AArch64/lsr-memset.ll | 6 +- .../LoopStrengthReduce/ARM/ivchain-ARM.ll | 4 +- test/Transforms/LoopStrengthReduce/pr12018.ll | 6 +- test/Transforms/LoopStrengthReduce/pr18165.ll | 18 +- test/Transforms/LoopUnroll/PowerPC/a2-unrolling.ll | 3 +- test/Transforms/LoopUnroll/PowerPC/p7-unrolling.ll | 99 + test/Transforms/LoopUnroll/ephemeral.ll | 44 + .../LoopUnroll/ignore-annotation-intrinsic-cost.ll | 133 + test/Transforms/LoopUnroll/nsw-tripcount.ll | 32 + .../LoopUnroll/partial-unroll-optsize.ll | 19 +- test/Transforms/LoopUnroll/runtime-loop.ll | 27 +- test/Transforms/LoopUnroll/runtime-loop1.ll | 8 +- test/Transforms/LoopUnroll/runtime-loop2.ll | 5 +- test/Transforms/LoopUnroll/scevunroll.ll | 15 +- test/Transforms/LoopUnroll/tripcount-overflow.ll | 30 + .../LoopUnroll/unroll-pragmas-disabled.ll | 124 +- test/Transforms/LoopUnroll/unroll-pragmas.ll | 60 +- .../LoopUnroll/update-loop-info-in-subloops.ll | 35 + test/Transforms/LoopVectorize/12-12-11-if-conv.ll | 2 +- .../Transforms/LoopVectorize/2012-10-20-infloop.ll | 2 +- .../LoopVectorize/2012-10-22-isconsec.ll | 2 +- test/Transforms/LoopVectorize/AArch64/sdiv-pow2.ll | 31 + .../LoopVectorize/X86/already-vectorized.ll | 8 +- test/Transforms/LoopVectorize/X86/assume.ll | 100 + test/Transforms/LoopVectorize/X86/gcc-examples.ll | 2 +- .../X86/illegal-parallel-loop-uniform-write.ll | 8 +- .../LoopVectorize/X86/masked_load_store.ll | 420 + .../LoopVectorize/X86/metadata-enable.ll | 8 +- .../LoopVectorize/X86/min-trip-count-switch.ll | 2 +- .../X86/parallel-loops-after-reg2mem.ll | 4 +- .../Transforms/LoopVectorize/X86/parallel-loops.ll | 12 +- test/Transforms/LoopVectorize/X86/powof2div.ll | 32 + test/Transforms/LoopVectorize/X86/small-size.ll | 4 +- test/Transforms/LoopVectorize/X86/tripcount.ll | 2 +- .../LoopVectorize/X86/unroll-small-loops.ll | 4 +- .../LoopVectorize/X86/unroll_selection.ll | 2 +- .../Transforms/LoopVectorize/X86/vect.omp.force.ll | 6 +- .../LoopVectorize/X86/vect.omp.force.small-tc.ll | 6 +- .../X86/vectorization-remarks-missed.ll | 78 +- .../LoopVectorize/X86/vectorization-remarks.ll | 50 +- .../LoopVectorize/X86/x86_fp80-vector-store.ll | 2 +- .../LoopVectorize/XCore/no-vector-registers.ll | 2 +- test/Transforms/LoopVectorize/align.ll | 2 +- test/Transforms/LoopVectorize/bsd_regex.ll | 2 +- .../Transforms/LoopVectorize/bzip_reverse_loops.ll | 2 +- test/Transforms/LoopVectorize/calloc.ll | 2 +- test/Transforms/LoopVectorize/cast-induction.ll | 2 +- .../LoopVectorize/conditional-assignment.ll | 58 + test/Transforms/LoopVectorize/control-flow.ll | 44 +- test/Transforms/LoopVectorize/cpp-new-array.ll | 2 +- test/Transforms/LoopVectorize/dbg.value.ll | 58 +- test/Transforms/LoopVectorize/debugloc.ll | 68 +- .../LoopVectorize/duplicated-metadata.ll | 30 + test/Transforms/LoopVectorize/ee-crash.ll | 2 +- test/Transforms/LoopVectorize/exact.ll | 24 + test/Transforms/LoopVectorize/flags.ll | 2 +- test/Transforms/LoopVectorize/float-reduction.ll | 24 +- test/Transforms/LoopVectorize/funcall.ll | 2 +- test/Transforms/LoopVectorize/gcc-examples.ll | 4 +- test/Transforms/LoopVectorize/global_alias.ll | 2 +- test/Transforms/LoopVectorize/hoist-loads.ll | 2 +- test/Transforms/LoopVectorize/i8-induction.ll | 2 +- test/Transforms/LoopVectorize/if-conv-crash.ll | 2 +- .../Transforms/LoopVectorize/if-conversion-nest.ll | 2 +- .../LoopVectorize/if-conversion-reduction.ll | 2 +- test/Transforms/LoopVectorize/if-conversion.ll | 2 +- test/Transforms/LoopVectorize/if-pred-stores.ll | 4 +- .../Transforms/LoopVectorize/incorrect-dom-info.ll | 2 +- test/Transforms/LoopVectorize/increment.ll | 2 +- test/Transforms/LoopVectorize/induction.ll | 4 +- test/Transforms/LoopVectorize/induction_plus.ll | 2 +- test/Transforms/LoopVectorize/intrinsic.ll | 58 +- test/Transforms/LoopVectorize/lcssa-crash.ll | 2 +- test/Transforms/LoopVectorize/lifetime.ll | 2 +- test/Transforms/LoopVectorize/loop-vect-memdep.ll | 26 + test/Transforms/LoopVectorize/memdep.ll | 4 +- test/Transforms/LoopVectorize/metadata-unroll.ll | 4 +- test/Transforms/LoopVectorize/metadata-width.ll | 6 +- test/Transforms/LoopVectorize/metadata.ll | 22 +- test/Transforms/LoopVectorize/minmax_reduction.ll | 18 +- .../LoopVectorize/multi-use-reduction-bug.ll | 2 +- .../LoopVectorize/multiple-address-spaces.ll | 2 +- test/Transforms/LoopVectorize/no_array_bounds.ll | 54 +- test/Transforms/LoopVectorize/no_idiv_reduction.ll | 2 +- test/Transforms/LoopVectorize/no_int_induction.ll | 2 +- test/Transforms/LoopVectorize/no_outside_user.ll | 5 +- test/Transforms/LoopVectorize/no_switch.ll | 52 +- test/Transforms/LoopVectorize/nofloat.ll | 2 +- test/Transforms/LoopVectorize/non-const-n.ll | 2 +- test/Transforms/LoopVectorize/nsw-crash.ll | 2 +- test/Transforms/LoopVectorize/opt.ll | 4 +- test/Transforms/LoopVectorize/ptr_loops.ll | 2 +- test/Transforms/LoopVectorize/read-only.ll | 2 +- test/Transforms/LoopVectorize/reduction.ll | 2 +- test/Transforms/LoopVectorize/reverse_induction.ll | 2 +- test/Transforms/LoopVectorize/reverse_iter.ll | 2 +- .../LoopVectorize/runtime-check-address-space.ll | 2 +- .../runtime-check-readonly-address-space.ll | 2 +- .../LoopVectorize/runtime-check-readonly.ll | 2 +- test/Transforms/LoopVectorize/runtime-check.ll | 2 +- test/Transforms/LoopVectorize/runtime-limit.ll | 2 +- test/Transforms/LoopVectorize/safegep.ll | 2 +- test/Transforms/LoopVectorize/same-base-access.ll | 2 +- test/Transforms/LoopVectorize/scalar-select.ll | 2 +- .../Transforms/LoopVectorize/scev-exitlim-crash.ll | 14 +- test/Transforms/LoopVectorize/simple-unroll.ll | 2 +- test/Transforms/LoopVectorize/small-loop.ll | 2 +- test/Transforms/LoopVectorize/start-non-zero.ll | 2 +- test/Transforms/LoopVectorize/store-shuffle-bug.ll | 2 +- test/Transforms/LoopVectorize/struct_access.ll | 2 +- test/Transforms/LoopVectorize/tbaa-nodep.ll | 16 +- test/Transforms/LoopVectorize/undef-inst-bug.ll | 2 +- test/Transforms/LoopVectorize/unroll_novec.ll | 2 +- test/Transforms/LoopVectorize/value-ptr-bug.ll | 2 +- .../LoopVectorize/vect.omp.persistence.ll | 10 +- test/Transforms/LoopVectorize/vect.stats.ll | 4 +- test/Transforms/LoopVectorize/vectorize-once.ll | 14 +- .../Transforms/LoopVectorize/version-mem-access.ll | 2 +- test/Transforms/LoopVectorize/write-only.ll | 2 +- test/Transforms/LowerExpectIntrinsic/basic.ll | 8 +- .../Mem2Reg/2007-08-27-VolatileLoadsStores.ll | 2 +- test/Transforms/Mem2Reg/ConvertDebugInfo.ll | 40 +- test/Transforms/Mem2Reg/ConvertDebugInfo2.ll | 56 +- test/Transforms/MemCpyOpt/callslot_deref.ll | 29 + .../MemCpyOpt/memcpy-to-memset-with-lifetimes.ll | 55 + .../MergeFunc/call-and-invoke-with-ranges.ll | 4 +- test/Transforms/MergeFunc/ranges.ll | 4 +- test/Transforms/MergeFunc/vector-GEP-crash.ll | 12 + test/Transforms/MetaRenamer/metarenamer.ll | 2 +- test/Transforms/ObjCARC/allocas.ll | 4 +- test/Transforms/ObjCARC/arc-annotations.ll | 12 +- test/Transforms/ObjCARC/basic.ll | 12 +- test/Transforms/ObjCARC/cfg-hazards.ll | 2 +- test/Transforms/ObjCARC/contract-marker.ll | 2 +- test/Transforms/ObjCARC/contract-storestrong.ll | 2 +- test/Transforms/ObjCARC/contract-testcases.ll | 2 +- test/Transforms/ObjCARC/empty-block.ll | 2 +- ...ensure-that-exception-unwind-path-is-visited.ll | 130 +- test/Transforms/ObjCARC/escape.ll | 2 +- test/Transforms/ObjCARC/intrinsic-use.ll | 2 +- test/Transforms/ObjCARC/invoke.ll | 2 +- test/Transforms/ObjCARC/nested.ll | 2 +- test/Transforms/ObjCARC/path-overflow.ll | 2 +- test/Transforms/ObjCARC/provenance.ll | 52 + test/Transforms/ObjCARC/retain-not-declared.ll | 2 +- test/Transforms/ObjCARC/split-backedge.ll | 2 +- test/Transforms/ObjCARC/weak-copies.ll | 2 +- .../PartiallyInlineLibCalls/bad-prototype.ll | 13 + .../Reassociate/2006-04-27-ReassociateVector.ll | 2 +- test/Transforms/Reassociate/basictest.ll | 2 +- .../Reassociate/canonicalize-neg-const.ll | 158 + test/Transforms/Reassociate/commute.ll | 19 + .../Reassociate/fast-AgressiveSubMove.ll | 24 + .../Reassociate/fast-ArrayOutOfBounds.ll | 65 + test/Transforms/Reassociate/fast-MissedTree.ll | 11 + .../Reassociate/fast-ReassociateVector.ll | 73 + test/Transforms/Reassociate/fast-SubReassociate.ll | 70 + test/Transforms/Reassociate/fast-basictest.ll | 285 + test/Transforms/Reassociate/fast-fp-commute.ll | 44 + test/Transforms/Reassociate/fast-mightymul.ll | 35 + test/Transforms/Reassociate/fast-multistep.ll | 32 + .../Reassociate/mixed-fast-nonfast-fp.ll | 18 + test/Transforms/Reassociate/multistep.ll | 2 +- test/Transforms/Reassociate/negation1.ll | 15 + test/Transforms/Reassociate/pr21205.ll | 21 + test/Transforms/Reassociate/wrap-flags.ll | 34 + test/Transforms/SCCP/ipsccp-basic.ll | 20 + test/Transforms/SLPVectorizer/AArch64/commute.ll | 75 + .../SLPVectorizer/AArch64/load-store-q.ll | 46 + test/Transforms/SLPVectorizer/AArch64/sdiv-pow2.ll | 42 + test/Transforms/SLPVectorizer/ARM/sroa.ll | 4 +- test/Transforms/SLPVectorizer/X86/addsub.ll | 12 +- test/Transforms/SLPVectorizer/X86/align.ll | 30 +- .../SLPVectorizer/X86/consecutive-access.ll | 2 +- .../Transforms/SLPVectorizer/X86/crash_binaryop.ll | 41 + test/Transforms/SLPVectorizer/X86/crash_gep.ll | 19 + .../SLPVectorizer/X86/crash_scheduling.ll | 47 + .../SLPVectorizer/X86/crash_vectorizeTree.ll | 2 +- test/Transforms/SLPVectorizer/X86/cycle_dup.ll | 2 +- test/Transforms/SLPVectorizer/X86/debug_info.ll | 76 +- .../SLPVectorizer/X86/extract_in_tree_user.ll | 70 + test/Transforms/SLPVectorizer/X86/hoist.ll | 2 +- test/Transforms/SLPVectorizer/X86/horizontal.ll | 8 +- test/Transforms/SLPVectorizer/X86/in-tree-user.ll | 9 +- .../X86/insert-element-build-vector.ll | 43 + test/Transforms/SLPVectorizer/X86/loopinvariant.ll | 4 +- test/Transforms/SLPVectorizer/X86/metadata.ll | 16 +- test/Transforms/SLPVectorizer/X86/multi_user.ll | 2 +- test/Transforms/SLPVectorizer/X86/powof2div.ll | 43 + test/Transforms/SLPVectorizer/X86/pr16899.ll | 12 +- .../SLPVectorizer/X86/propagate_ir_flags.ll | 350 + test/Transforms/SLPVectorizer/X86/return.ll | 54 + test/Transforms/SLPVectorizer/X86/saxpy.ll | 2 +- test/Transforms/SLPVectorizer/X86/scheduling.ll | 78 + test/Transforms/SLPVectorizer/X86/unreachable.ll | 40 + test/Transforms/SROA/alignment.ll | 13 +- test/Transforms/SROA/basictest.ll | 155 + test/Transforms/SROA/phi-and-select.ll | 69 +- test/Transforms/SROA/slice-width.ll | 83 +- test/Transforms/SROA/vector-lifetime-intrinsic.ll | 31 + test/Transforms/SROA/vector-promotion.ll | 155 + test/Transforms/SampleProfile/Inputs/fnptr.binprof | Bin 0 -> 112 bytes test/Transforms/SampleProfile/Inputs/fnptr.prof | 12 + test/Transforms/SampleProfile/branch.ll | 100 +- test/Transforms/SampleProfile/calls.ll | 60 +- test/Transforms/SampleProfile/discriminator.ll | 44 +- test/Transforms/SampleProfile/fnptr.ll | 155 + test/Transforms/SampleProfile/propagate.ll | 86 +- test/Transforms/SampleProfile/syntax.ll | 6 +- test/Transforms/ScalarRepl/debuginfo-preserved.ll | 50 +- test/Transforms/Scalarizer/basic.ll | 12 +- test/Transforms/Scalarizer/dbginfo.ll | 68 +- .../SeparateConstOffsetFromGEP/NVPTX/split-gep.ll | 43 + .../Transforms/SimplifyCFG/UnreachableEliminate.ll | 51 +- .../SimplifyCFG/X86/switch-covered-bug.ll | 50 + .../SimplifyCFG/X86/switch_to_lookup_table.ll | 283 +- test/Transforms/SimplifyCFG/assume.ll | 22 + test/Transforms/SimplifyCFG/basictest.ll | 6 +- test/Transforms/SimplifyCFG/branch-fold-dbg.ll | 36 +- .../SimplifyCFG/branch-fold-threshold.ll | 28 + test/Transforms/SimplifyCFG/hoist-dbgvalue.ll | 56 +- test/Transforms/SimplifyCFG/hoist-with-range.ll | 20 + test/Transforms/SimplifyCFG/lifetime.ll | 6 +- .../SimplifyCFG/preserve-branchweights-partial.ll | 2 +- .../preserve-branchweights-switch-create.ll | 18 +- .../SimplifyCFG/preserve-branchweights.ll | 48 +- test/Transforms/SimplifyCFG/sink-common-code.ll | 34 +- test/Transforms/SimplifyCFG/speculate-math.ll | 52 + .../Transforms/SimplifyCFG/switch-range-to-icmp.ll | 50 + test/Transforms/SimplifyCFG/switch-to-br.ll | 64 + ...switch-to-select-multiple-edge-per-block-phi.ll | 40 + .../SimplifyCFG/switch-to-select-two-case.ll | 72 + test/Transforms/SimplifyCFG/trap-debugloc.ll | 22 +- test/Transforms/SimplifyCFG/volatile-phioper.ll | 2 +- .../StripSymbols/2010-06-30-StripDebug.ll | 32 +- test/Transforms/StripSymbols/2010-08-25-crash.ll | 30 +- .../StripSymbols/strip-dead-debug-info.ll | 56 +- .../StructurizeCFG/one-loop-multiple-backedges.ll | 41 + test/Transforms/TailCallElim/EraseBB.ll | 26 + test/Transforms/TailCallElim/reorder_load.ll | 27 +- test/Transforms/Util/flattencfg.ll | 26 + test/Transforms/Util/lowerswitch.ll | 54 + test/Verifier/alias.ll | 2 +- test/Verifier/comdat.ll | 2 +- test/Verifier/comdat2.ll | 2 +- test/Verifier/fpmath.ll | 14 +- test/Verifier/frameallocate.ll | 48 + test/Verifier/ident-meta1.ll | 6 +- test/Verifier/ident-meta2.ll | 8 +- test/Verifier/ident-meta3.ll | 4 +- test/Verifier/invoke.ll | 2 +- test/Verifier/module-flags-1.ll | 47 +- test/Verifier/musttail-valid.ll | 23 + test/Verifier/range-1.ll | 49 +- test/Verifier/range-2.ll | 10 +- test/Verifier/statepoint.ll | 50 + test/lit.cfg | 131 +- test/lit.site.cfg.in | 13 +- .../dsymutil/Inputs/basic-archive.macho.x86_64 | Bin 0 -> 9352 bytes test/tools/dsymutil/Inputs/basic-lto.macho.x86_64 | Bin 0 -> 8912 bytes .../tools/dsymutil/Inputs/basic-lto.macho.x86_64.o | Bin 0 -> 4516 bytes test/tools/dsymutil/Inputs/basic.macho.x86_64 | Bin 0 -> 9320 bytes test/tools/dsymutil/Inputs/basic1.c | 28 + test/tools/dsymutil/Inputs/basic1.macho.x86_64.o | Bin 0 -> 2376 bytes test/tools/dsymutil/Inputs/basic2.c | 22 + test/tools/dsymutil/Inputs/basic2.macho.x86_64.o | Bin 0 -> 3472 bytes test/tools/dsymutil/Inputs/basic3.c | 20 + test/tools/dsymutil/Inputs/basic3.macho.x86_64.o | Bin 0 -> 3008 bytes test/tools/dsymutil/Inputs/libbasic.a | Bin 0 -> 6840 bytes test/tools/dsymutil/debug-map-parsing.test | 77 + test/tools/gold/Inputs/alias-1.ll | 1 + test/tools/gold/Inputs/bcsection.s | 2 + test/tools/gold/Inputs/comdat.ll | 25 + test/tools/gold/Inputs/common.ll | 1 + test/tools/gold/Inputs/invalid.bc | Bin 0 -> 272 bytes test/tools/gold/Inputs/linker-script.export | 5 + test/tools/gold/Inputs/linkonce-weak.ll | 3 + test/tools/gold/Inputs/pr19901-1.ll | 4 + test/tools/gold/Inputs/weak.ll | 2 + test/tools/gold/alias.ll | 13 + test/tools/gold/bad-alias.ll | 13 + test/tools/gold/bcsection.ll | 11 + test/tools/gold/coff.ll | 22 + test/tools/gold/comdat.ll | 65 + test/tools/gold/common.ll | 29 + test/tools/gold/emit-llvm.ll | 73 + test/tools/gold/invalid.ll | 7 + test/tools/gold/linker-script.ll | 17 + test/tools/gold/linkonce-weak.ll | 19 + test/tools/gold/lit.local.cfg | 4 + test/tools/gold/mtriple.ll | 13 + test/tools/gold/option.ll | 39 + test/tools/gold/pr19901.ll | 23 + test/tools/gold/slp-vectorize.ll | 30 + test/tools/gold/stats.ll | 7 + test/tools/gold/vectorize.ll | 30 + test/tools/gold/weak.ll | 16 + test/tools/llvm-cov/Inputs/README | 22 +- .../llvm-cov/Inputs/highlightedRanges.covmapping | Bin 0 -> 355 bytes .../llvm-cov/Inputs/highlightedRanges.profdata | Bin 0 -> 848 bytes .../llvm-cov/Inputs/lineExecutionCounts.covmapping | Bin 0 -> 162 bytes .../llvm-cov/Inputs/lineExecutionCounts.profdata | Bin 0 -> 656 bytes .../tools/llvm-cov/Inputs/regionMarkers.covmapping | Bin 0 -> 194 bytes test/tools/llvm-cov/Inputs/regionMarkers.profdata | Bin 0 -> 656 bytes test/tools/llvm-cov/Inputs/report.covmapping | Bin 0 -> 256 bytes test/tools/llvm-cov/Inputs/report.profdata | Bin 0 -> 800 bytes .../llvm-cov/Inputs/showExpansions.covmapping | Bin 0 -> 194 bytes test/tools/llvm-cov/Inputs/showExpansions.profdata | Bin 0 -> 672 bytes .../Inputs/templateInstantiations.covmapping | Bin 0 -> 244 bytes .../Inputs/templateInstantiations.profdata | Bin 0 -> 768 bytes test/tools/llvm-cov/lit.local.cfg | 4 + test/tools/llvm-cov/report.cpp | 24 + test/tools/llvm-cov/showExpansions.cpp | 29 + test/tools/llvm-cov/showHighlightedRanges.cpp | 48 + test/tools/llvm-cov/showLineExecutionCounts.cpp | 30 + test/tools/llvm-cov/showRegionMarkers.cpp | 26 + test/tools/llvm-cov/showTemplateInstantiations.cpp | 43 + test/tools/llvm-mc/line_end_with_space.test | 2 + .../AArch64/Inputs/ObjC.exe.macho-aarch64 | Bin 0 -> 49736 bytes .../AArch64/Inputs/ObjC.obj.macho-aarch64 | Bin 0 -> 2008 bytes .../AArch64/Inputs/hello.exe.macho-aarch64 | Bin 0 -> 49416 bytes .../AArch64/Inputs/hello.obj.macho-aarch64 | Bin 0 -> 604 bytes test/tools/llvm-objdump/AArch64/lit.local.cfg | 2 + .../AArch64/macho-private-headers.test | 312 + .../AArch64/macho-symbolized-disassembly.test | 23 + .../llvm-objdump/ARM/Inputs/hello.exe.macho-arm | Bin 0 -> 49408 bytes .../llvm-objdump/ARM/Inputs/hello.obj.macho-arm | Bin 0 -> 744 bytes test/tools/llvm-objdump/ARM/lit.local.cfg | 2 + .../llvm-objdump/ARM/macho-arm-and-thumb.test | 15 + test/tools/llvm-objdump/ARM/macho-mattr-arm.test | 5 + test/tools/llvm-objdump/ARM/macho-mcpu-arm.test | 10 + .../llvm-objdump/ARM/macho-private-headers.test | 345 + .../ARM/macho-symbolized-disassembly.test | 8 + .../ARM/macho-symbolized-subtractor.test | 15 + .../llvm-objdump/Inputs/bad-ordinal.macho-x86_64 | Bin 0 -> 8496 bytes test/tools/llvm-objdump/Inputs/bind.macho-x86_64 | Bin 0 -> 8776 bytes test/tools/llvm-objdump/Inputs/bind2.macho-x86_64 | Bin 0 -> 8376 bytes .../llvm-objdump/Inputs/compact-unwind.macho-i386 | Bin 0 -> 2140 bytes .../Inputs/compact-unwind.macho-x86_64 | Bin 0 -> 2272 bytes .../llvm-objdump/Inputs/exports-trie.macho-x86_64 | Bin 0 -> 8752 bytes .../llvm-objdump/Inputs/lazy-bind.macho-x86_64 | Bin 0 -> 8592 bytes .../Inputs/out-of-section-sym.elf-i386 | Bin 4450 -> 0 bytes test/tools/llvm-objdump/Inputs/rebase.macho-x86_64 | Bin 0 -> 8336 bytes .../tools/llvm-objdump/Inputs/trivial.obj.elf-i386 | Bin 449 -> 0 bytes .../Inputs/unwind-info-no-relocs.macho-x86_64 | Bin 0 -> 12600 bytes .../llvm-objdump/Inputs/unwind-info.macho-arm64 | Bin 0 -> 50024 bytes .../llvm-objdump/Inputs/unwind-info.macho-x86_64 | Bin 0 -> 9136 bytes .../llvm-objdump/Inputs/weak-bind.macho-x86_64 | Bin 0 -> 8856 bytes .../llvm-objdump/X86/Inputs/ObjC.exe.macho-x86_64 | Bin 0 -> 8944 bytes .../llvm-objdump/X86/Inputs/ObjC.obj.macho-x86_64 | Bin 0 -> 1732 bytes .../X86/Inputs/dylibLoadKinds.macho-x86_64 | Bin 0 -> 4280 bytes .../X86/Inputs/dylibRoutines.macho-x86_64 | Bin 0 -> 4288 bytes .../X86/Inputs/dylibSubClient.macho-x86_64 | Bin 0 -> 4240 bytes .../X86/Inputs/dylibSubFramework.macho-x86_64 | Bin 0 -> 4240 bytes .../X86/Inputs/dylibSubLibrary.macho-x86_64 | Bin 0 -> 4220 bytes .../X86/Inputs/dylibSubUmbrella.macho-x86_64 | Bin 0 -> 4220 bytes .../llvm-objdump/X86/Inputs/exeThread.macho-x86_64 | Bin 0 -> 9100 bytes .../llvm-objdump/X86/Inputs/hello.exe.macho-i386 | Bin 0 -> 8476 bytes .../llvm-objdump/X86/Inputs/hello.exe.macho-x86_64 | Bin 0 -> 8496 bytes .../llvm-objdump/X86/Inputs/hello.obj.macho-i386 | Bin 0 -> 472 bytes .../llvm-objdump/X86/Inputs/hello.obj.macho-x86_64 | Bin 0 -> 844 bytes .../X86/Inputs/hello_cpp.exe.macho-x86_64 | Bin 0 -> 15100 bytes .../X86/Inputs/linkerOption.macho-x86_64 | Bin 0 -> 744 bytes .../X86/Inputs/macho-universal-archive.x86_64.i386 | Bin 0 -> 1656 bytes .../X86/Inputs/macho-universal.x86_64.i386 | Bin 0 -> 16624 bytes .../X86/Inputs/out-of-section-sym.elf-i386 | Bin 0 -> 4450 bytes .../llvm-objdump/X86/Inputs/trivial.obj.elf-i386 | Bin 0 -> 449 bytes .../llvm-objdump/X86/disassembly-show-raw.test | 14 + test/tools/llvm-objdump/X86/lit.local.cfg | 2 + .../llvm-objdump/X86/macho-private-headers.test | 445 + .../X86/macho-symbolized-disassembly.test | 38 + .../X86/macho-symbolized-subtractor-i386.test | 10 + .../X86/macho-symbolized-subtractor.test | 10 + .../X86/macho-universal-x86_64.i386.test | 44 + .../tools/llvm-objdump/X86/out-of-section-sym.test | 13 + test/tools/llvm-objdump/coff-large-bss.test | 5 +- test/tools/llvm-objdump/disassembly-show-raw.test | 14 - test/tools/llvm-objdump/lit.local.cfg | 2 - test/tools/llvm-objdump/macho-bad-ordinal.test | 6 + test/tools/llvm-objdump/macho-bind.test | 10 + test/tools/llvm-objdump/macho-bind2.test | 5 + .../llvm-objdump/macho-compact-unwind-i386.test | 27 + .../llvm-objdump/macho-compact-unwind-x86_64.test | 27 + test/tools/llvm-objdump/macho-exports-trie.test | 11 + test/tools/llvm-objdump/macho-lazy-bind.test | 7 + test/tools/llvm-objdump/macho-rebase.test | 15 + .../llvm-objdump/macho-unwind-info-arm64.test | 28 + .../llvm-objdump/macho-unwind-info-no-relocs.test | 8 + .../llvm-objdump/macho-unwind-info-x86_64.test | 29 + test/tools/llvm-objdump/macho-weak-bind.test | 10 + test/tools/llvm-objdump/out-of-section-sym.test | 13 - test/tools/llvm-profdata/Inputs/bad-hash.profdata | 4 - test/tools/llvm-profdata/Inputs/bad-hash.proftext | 4 + test/tools/llvm-profdata/Inputs/bar3-1.profdata | 6 - test/tools/llvm-profdata/Inputs/bar3-1.proftext | 6 + test/tools/llvm-profdata/Inputs/c-general.profdata | Bin 1384 -> 0 bytes test/tools/llvm-profdata/Inputs/c-general.profraw | Bin 0 -> 1384 bytes test/tools/llvm-profdata/Inputs/compat.profdata.v1 | Bin 0 -> 792 bytes test/tools/llvm-profdata/Inputs/empty.profdata | 0 test/tools/llvm-profdata/Inputs/empty.proftext | 0 .../tools/llvm-profdata/Inputs/extra-word.profdata | 2 - .../tools/llvm-profdata/Inputs/extra-word.proftext | 2 + test/tools/llvm-profdata/Inputs/foo3-1.profdata | 6 - test/tools/llvm-profdata/Inputs/foo3-1.proftext | 6 + test/tools/llvm-profdata/Inputs/foo3-2.profdata | 6 - test/tools/llvm-profdata/Inputs/foo3-2.proftext | 6 + .../tools/llvm-profdata/Inputs/foo3bar3-1.profdata | 13 - .../tools/llvm-profdata/Inputs/foo3bar3-1.proftext | 13 + .../tools/llvm-profdata/Inputs/foo3bar3-2.profdata | 13 - test/tools/llvm-profdata/Inputs/foo4-1.profdata | 7 - test/tools/llvm-profdata/Inputs/foo4-2.profdata | 7 - .../Inputs/invalid-count-later.profdata | 4 - .../Inputs/invalid-count-later.proftext | 4 + test/tools/llvm-profdata/Inputs/no-counts.profdata | 3 - test/tools/llvm-profdata/Inputs/no-counts.proftext | 3 + test/tools/llvm-profdata/Inputs/overflow.profdata | 4 - .../llvm-profdata/Inputs/sample-profile.proftext | 12 + test/tools/llvm-profdata/c-general.test | 6 +- test/tools/llvm-profdata/compat.proftext | 47 + test/tools/llvm-profdata/count-mismatch.proftext | 40 + test/tools/llvm-profdata/errors.test | 16 - test/tools/llvm-profdata/general.proftext | 56 + test/tools/llvm-profdata/hash-mismatch.proftext | 37 + test/tools/llvm-profdata/lit.local.cfg | 1 + test/tools/llvm-profdata/multiple-inputs.test | 51 + test/tools/llvm-profdata/overflow.proftext | 12 + test/tools/llvm-profdata/raw-two-profiles.test | 2 - test/tools/llvm-profdata/sample-profile-basic.test | 30 + test/tools/llvm-profdata/simple.test | 77 - test/tools/llvm-profdata/text-format-errors.test | 10 + test/tools/llvm-readobj/ARM/attribute-0.s | 234 + test/tools/llvm-readobj/ARM/attribute-1.s | 220 + test/tools/llvm-readobj/ARM/attribute-10.s | 24 + test/tools/llvm-readobj/ARM/attribute-11.s | 24 + test/tools/llvm-readobj/ARM/attribute-12.s | 24 + test/tools/llvm-readobj/ARM/attribute-13.s | 10 + test/tools/llvm-readobj/ARM/attribute-136.s | 10 + test/tools/llvm-readobj/ARM/attribute-14.s | 10 + test/tools/llvm-readobj/ARM/attribute-15.s | 10 + test/tools/llvm-readobj/ARM/attribute-2.s | 178 + test/tools/llvm-readobj/ARM/attribute-3.s | 108 + test/tools/llvm-readobj/ARM/attribute-4.s | 59 + test/tools/llvm-readobj/ARM/attribute-5.s | 52 + test/tools/llvm-readobj/ARM/attribute-6.s | 52 + test/tools/llvm-readobj/ARM/attribute-7.s | 38 + test/tools/llvm-readobj/ARM/attribute-8.s | 31 + test/tools/llvm-readobj/ARM/attribute-9.s | 24 + test/tools/llvm-readobj/ARM/attribute-A.s | 10 + test/tools/llvm-readobj/ARM/attribute-M.s | 10 + test/tools/llvm-readobj/ARM/attribute-R.s | 10 + test/tools/llvm-readobj/ARM/attribute-S.s | 10 + .../llvm-readobj/ARM/attribute-conformance-1.s | 8 + .../llvm-readobj/ARM/attribute-conformance-2.s | 8 + test/tools/llvm-readobj/ARM/attributes.s | 287 - .../llvm-readobj/Inputs/bad-relocs.obj.coff-i386 | Bin 0 -> 97 bytes .../llvm-readobj/Inputs/basereloc.obj.coff-i386 | Bin 0 -> 2560 bytes test/tools/llvm-readobj/Inputs/bigobj.coff-x86-64 | Bin 0 -> 340 bytes .../comdat-function-linetables.obj.coff-2012-i386 | Bin 0 -> 2005 bytes .../comdat-function-linetables.obj.coff-2013-i386 | Bin 0 -> 8501 bytes .../llvm-readobj/Inputs/directives.obj.coff-x86_64 | Bin 0 -> 244 bytes test/tools/llvm-readobj/Inputs/export-arm.dll | Bin 0 -> 5632 bytes test/tools/llvm-readobj/Inputs/export-x64.dll | Bin 0 -> 6144 bytes test/tools/llvm-readobj/Inputs/export-x86.dll | Bin 0 -> 6144 bytes .../tools/llvm-readobj/Inputs/file-aux-record.yaml | 4 +- .../Inputs/file-multiple-aux-records.yaml | 4 +- .../llvm-readobj/Inputs/imports.exe.coff-i386 | Bin 0 -> 3072 bytes .../llvm-readobj/Inputs/imports.exe.coff-x86-64 | Bin 0 -> 4096 bytes .../Inputs/multifile-linetables.obj.coff-2012-i368 | Bin 1631 -> 1631 bytes .../multifile-linetables.obj.coff-2012-x86_64 | Bin 1799 -> 1799 bytes .../Inputs/multifile-linetables.obj.coff-2013-i368 | Bin 0 -> 1631 bytes .../multifile-linetables.obj.coff-2013-x86_64 | Bin 0 -> 1795 bytes .../multifunction-linetables.obj.coff-2012-i368 | Bin 2155 -> 2155 bytes .../multifunction-linetables.obj.coff-2012-x86_64 | Bin 2475 -> 2475 bytes .../multifunction-linetables.obj.coff-2013-i368 | Bin 0 -> 2155 bytes .../multifunction-linetables.obj.coff-2013-x86_64 | Bin 0 -> 2471 bytes .../Inputs/relocs-no-symtab.obj.coff-i386 | Bin 0 -> 97 bytes .../tools/llvm-readobj/Inputs/relocs.obj.coff-i386 | Bin 305 -> 305 bytes .../llvm-readobj/Inputs/relocs.obj.coff-x86_64 | Bin 424 -> 424 bytes .../llvm-readobj/Inputs/relocs.obj.elf-aarch64 | Bin 2832 -> 4232 bytes test/tools/llvm-readobj/Inputs/relocs.obj.elf-arm | Bin 2100 -> 2112 bytes test/tools/llvm-readobj/Inputs/relocs.py | 59 +- test/tools/llvm-readobj/bigobj.test | 139 + test/tools/llvm-readobj/codeview-linetables.test | 150 +- test/tools/llvm-readobj/coff-basereloc.test | 24 + test/tools/llvm-readobj/coff-directives.test | 2 + test/tools/llvm-readobj/coff-exports.test | 11 + .../llvm-readobj/coff-file-sections-reading.test | 2 +- test/tools/llvm-readobj/cxx-cli-aux.test | 6 +- test/tools/llvm-readobj/file-headers.test | 122 +- test/tools/llvm-readobj/imports.test | 88 + test/tools/llvm-readobj/peplus.test | 2 +- test/tools/llvm-readobj/reloc-types.test | 56 +- test/tools/llvm-readobj/relocations.test | 10 + test/tools/llvm-readobj/sections-ext.test | 1 - test/tools/llvm-readobj/symbols.test | 5 +- test/tools/llvm-symbolizer/Inputs/dsym-test-exe | Bin 0 -> 4584 bytes .../Contents/Info.plist | 20 + .../Contents/Resources/DWARF/dsym-test-exe-second | Bin 0 -> 8833 bytes .../llvm-symbolizer/Inputs/dsym-test-exe-second | Bin 0 -> 4584 bytes .../Inputs/dsym-test-exe.dSYM/Contents/Info.plist | 20 + .../Contents/Resources/DWARF/dsym-test-exe | Bin 0 -> 8833 bytes test/tools/llvm-symbolizer/Inputs/dsym-test.c | 8 + test/tools/llvm-symbolizer/Inputs/ppc64 | Bin 0 -> 1624 bytes test/tools/llvm-symbolizer/dsym.test | 14 + test/tools/llvm-symbolizer/ppc64.test | 11 + .../llvm-vtabledump/Inputs/trivial.obj.coff-i386 | Bin 0 -> 2938 bytes .../llvm-vtabledump/Inputs/trivial.obj.elf-i386 | Bin 0 -> 1032 bytes test/tools/llvm-vtabledump/trivial.test | 58 + tools/CMakeLists.txt | 25 +- tools/LLVMBuild.txt | 2 +- tools/Makefile | 10 +- tools/bugpoint/BugDriver.cpp | 21 +- tools/bugpoint/BugDriver.h | 81 +- tools/bugpoint/CrashDebugger.cpp | 31 +- tools/bugpoint/ExtractFunction.cpp | 45 +- tools/bugpoint/ListReducer.h | 4 +- tools/bugpoint/Miscompilation.cpp | 57 +- tools/bugpoint/OptimizerDriver.cpp | 50 +- tools/bugpoint/ToolRunner.cpp | 39 +- tools/bugpoint/ToolRunner.h | 4 +- tools/bugpoint/bugpoint.cpp | 14 +- tools/dsymutil/BinaryHolder.cpp | 111 + tools/dsymutil/BinaryHolder.h | 104 + tools/dsymutil/CMakeLists.txt | 13 + tools/dsymutil/DebugMap.cpp | 80 + tools/dsymutil/DebugMap.h | 128 + tools/dsymutil/DwarfLinker.cpp | 20 + tools/dsymutil/LLVMBuild.txt | 22 + tools/dsymutil/MachODebugMapParser.cpp | 234 + tools/dsymutil/Makefile | 17 + tools/dsymutil/dsymutil.cpp | 71 + tools/dsymutil/dsymutil.h | 39 + tools/gold/CMakeLists.txt | 10 +- tools/gold/Makefile | 2 +- tools/gold/gold-plugin.cpp | 820 +- tools/llc/llc.cpp | 75 +- tools/lli/CMakeLists.txt | 1 - tools/lli/ChildTarget/ChildTarget.cpp | 14 +- tools/lli/LLVMBuild.txt | 2 +- tools/lli/Makefile | 2 +- tools/lli/RPCChannel.h | 6 +- tools/lli/RemoteMemoryManager.cpp | 36 +- tools/lli/RemoteMemoryManager.h | 27 +- tools/lli/RemoteTarget.h | 4 +- tools/lli/RemoteTargetExternal.h | 6 +- tools/lli/RemoteTargetMessage.h | 4 +- tools/lli/lli.cpp | 121 +- tools/llvm-ar/CMakeLists.txt | 15 +- tools/llvm-ar/install_symlink.cmake | 25 + tools/llvm-ar/llvm-ar.cpp | 399 +- tools/llvm-as/llvm-as.cpp | 10 +- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp | 110 +- tools/llvm-c-test/CMakeLists.txt | 27 + tools/llvm-c-test/disassemble.c | 20 +- tools/llvm-config/BuildVariables.inc.in | 1 + tools/llvm-config/CMakeLists.txt | 15 + tools/llvm-config/Makefile | 2 + tools/llvm-config/llvm-config.cpp | 10 +- tools/llvm-cov/CMakeLists.txt | 10 +- tools/llvm-cov/CodeCoverage.cpp | 483 + tools/llvm-cov/CoverageFilters.cpp | 59 + tools/llvm-cov/CoverageFilters.h | 127 + tools/llvm-cov/CoverageReport.cpp | 202 + tools/llvm-cov/CoverageReport.h | 40 + tools/llvm-cov/CoverageSummary.cpp | 64 + tools/llvm-cov/CoverageSummary.h | 45 + tools/llvm-cov/CoverageSummaryInfo.cpp | 96 + tools/llvm-cov/CoverageSummaryInfo.h | 133 + tools/llvm-cov/CoverageViewOptions.h | 36 + tools/llvm-cov/LLVMBuild.txt | 2 +- tools/llvm-cov/Makefile | 2 +- tools/llvm-cov/RenderingSupport.h | 60 + tools/llvm-cov/SourceCoverageView.cpp | 260 + tools/llvm-cov/SourceCoverageView.h | 162 + tools/llvm-cov/TestingSupport.cpp | 90 + tools/llvm-cov/gcov.cpp | 152 + tools/llvm-cov/llvm-cov.cpp | 178 +- tools/llvm-diff/DiffConsumer.h | 4 +- tools/llvm-diff/DiffLog.h | 4 +- tools/llvm-diff/DifferenceEngine.h | 4 +- tools/llvm-diff/llvm-diff.cpp | 22 +- tools/llvm-dis/llvm-dis.cpp | 47 +- tools/llvm-dwarfdump/llvm-dwarfdump.cpp | 21 +- tools/llvm-extract/llvm-extract.cpp | 38 +- tools/llvm-go/CMakeLists.txt | 9 + tools/llvm-go/Makefile | 16 + tools/llvm-go/llvm-go.go | 290 + tools/llvm-jitlistener/CMakeLists.txt | 43 +- tools/llvm-jitlistener/LLVMBuild.txt | 2 +- tools/llvm-jitlistener/Makefile | 2 +- tools/llvm-jitlistener/llvm-jitlistener.cpp | 23 +- tools/llvm-link/llvm-link.cpp | 69 +- tools/llvm-lto/llvm-lto.cpp | 99 +- tools/llvm-mc/Disassembler.cpp | 71 +- tools/llvm-mc/Disassembler.h | 4 +- tools/llvm-mc/llvm-mc.cpp | 118 +- tools/llvm-mcmarkup/llvm-mcmarkup.cpp | 7 +- tools/llvm-nm/llvm-nm.cpp | 274 +- tools/llvm-objdump/CMakeLists.txt | 2 +- tools/llvm-objdump/COFFDump.cpp | 13 +- tools/llvm-objdump/LLVMBuild.txt | 2 +- tools/llvm-objdump/MachODump.cpp | 5004 +++++++++- tools/llvm-objdump/Makefile | 2 +- tools/llvm-objdump/llvm-objdump.cpp | 391 +- tools/llvm-objdump/llvm-objdump.h | 31 +- tools/llvm-profdata/CMakeLists.txt | 6 +- tools/llvm-profdata/llvm-profdata.cpp | 180 +- tools/llvm-readobj/ARMAttributeParser.cpp | 2 +- tools/llvm-readobj/ARMAttributeParser.h | 4 +- tools/llvm-readobj/ARMEHABIPrinter.h | 4 +- tools/llvm-readobj/ARMWinEHPrinter.cpp | 63 +- tools/llvm-readobj/ARMWinEHPrinter.h | 52 +- tools/llvm-readobj/COFFDumper.cpp | 428 +- tools/llvm-readobj/ELFDumper.cpp | 5 +- tools/llvm-readobj/Error.cpp | 2 +- tools/llvm-readobj/Error.h | 4 +- tools/llvm-readobj/MachODumper.cpp | 202 +- tools/llvm-readobj/ObjDumper.h | 10 +- tools/llvm-readobj/StreamWriter.h | 20 +- tools/llvm-readobj/Win64EHDumper.h | 4 +- tools/llvm-readobj/llvm-readobj.cpp | 52 +- tools/llvm-readobj/llvm-readobj.h | 4 +- tools/llvm-rtdyld/CMakeLists.txt | 1 + tools/llvm-rtdyld/LLVMBuild.txt | 2 +- tools/llvm-rtdyld/Makefile | 2 +- tools/llvm-rtdyld/llvm-rtdyld.cpp | 234 +- tools/llvm-shlib/CMakeLists.txt | 100 + tools/llvm-shlib/libllvm.cpp | 20 + tools/llvm-size/llvm-size.cpp | 65 +- tools/llvm-stress/llvm-stress.cpp | 9 +- tools/llvm-symbolizer/LLVMSymbolize.cpp | 190 +- tools/llvm-symbolizer/LLVMSymbolize.h | 56 +- tools/llvm-symbolizer/llvm-symbolizer.cpp | 14 + tools/llvm-vtabledump/CMakeLists.txt | 10 + tools/llvm-vtabledump/Error.cpp | 43 + tools/llvm-vtabledump/Error.h | 39 + tools/llvm-vtabledump/LLVMBuild.txt | 22 + tools/llvm-vtabledump/Makefile | 18 + tools/llvm-vtabledump/llvm-vtabledump.cpp | 464 + tools/llvm-vtabledump/llvm-vtabledump.h | 23 + tools/lto/CMakeLists.txt | 2 - tools/lto/Makefile | 4 - tools/lto/lto.cpp | 47 +- tools/lto/lto.exports | 3 + tools/macho-dump/macho-dump.cpp | 16 +- tools/msbuild/CMakeLists.txt | 11 + tools/msbuild/install.bat | 40 +- tools/msbuild/toolset-vs2014.targets | 3 + tools/msbuild/toolset-vs2014_xp.targets | 21 + tools/msbuild/uninstall.bat | 23 +- tools/obj2yaml/CMakeLists.txt | 2 +- tools/obj2yaml/Error.cpp | 4 +- tools/obj2yaml/Error.h | 4 +- tools/obj2yaml/Makefile | 3 - tools/obj2yaml/coff2yaml.cpp | 161 +- tools/obj2yaml/elf2yaml.cpp | 2 +- tools/obj2yaml/obj2yaml.cpp | 6 +- tools/obj2yaml/obj2yaml.h | 4 +- tools/opt/BreakpointPrinter.cpp | 2 +- tools/opt/NewPMDriver.cpp | 33 +- tools/opt/NewPMDriver.h | 4 +- tools/opt/PassRegistry.def | 14 + tools/opt/Passes.cpp | 209 +- tools/opt/Passes.h | 27 +- tools/opt/opt.cpp | 121 +- tools/verify-uselistorder/CMakeLists.txt | 12 + tools/verify-uselistorder/LLVMBuild.txt | 22 + tools/verify-uselistorder/Makefile | 17 + tools/verify-uselistorder/verify-uselistorder.cpp | 568 ++ tools/yaml2obj/CMakeLists.txt | 2 +- tools/yaml2obj/Makefile | 3 - tools/yaml2obj/yaml2coff.cpp | 311 +- tools/yaml2obj/yaml2elf.cpp | 12 +- tools/yaml2obj/yaml2obj.cpp | 8 +- tools/yaml2obj/yaml2obj.h | 4 +- unittests/ADT/APFloatTest.cpp | 205 + unittests/ADT/APIntTest.cpp | 36 +- unittests/ADT/ArrayRefTest.cpp | 53 + unittests/ADT/CMakeLists.txt | 2 + unittests/ADT/DenseMapTest.cpp | 5 + unittests/ADT/DenseSetTest.cpp | 38 + unittests/ADT/FunctionRefTest.cpp | 28 + unittests/ADT/MapVectorTest.cpp | 251 + unittests/ADT/OptionalTest.cpp | 99 + unittests/ADT/PostOrderIteratorTest.cpp | 37 + unittests/ADT/SmallVectorTest.cpp | 130 + unittests/ADT/StringMapTest.cpp | 22 +- unittests/ADT/TinyPtrVectorTest.cpp | 26 + unittests/ADT/TripleTest.cpp | 90 +- unittests/Analysis/CFGTest.cpp | 10 +- unittests/Analysis/CMakeLists.txt | 2 + unittests/Analysis/CallGraphTest.cpp | 59 + unittests/Analysis/LazyCallGraphTest.cpp | 8 +- unittests/Analysis/Makefile | 2 +- unittests/Analysis/MixedTBAATest.cpp | 2 +- unittests/Bitcode/BitReaderTest.cpp | 160 +- unittests/Bitcode/BitstreamReaderTest.cpp | 56 + unittests/Bitcode/CMakeLists.txt | 2 + unittests/Bitcode/Makefile | 2 +- unittests/CMakeLists.txt | 2 +- unittests/CodeGen/DIEHashTest.cpp | 4 +- unittests/ExecutionEngine/CMakeLists.txt | 3 +- unittests/ExecutionEngine/ExecutionEngineTest.cpp | 48 +- unittests/ExecutionEngine/JIT/CMakeLists.txt | 65 - .../JIT/IntelJITEventListenerTest.cpp | 113 - .../ExecutionEngine/JIT/JITEventListenerTest.cpp | 237 - .../JIT/JITEventListenerTestCommon.h | 207 - .../ExecutionEngine/JIT/JITMemoryManagerTest.cpp | 302 - unittests/ExecutionEngine/JIT/JITTest.cpp | 728 -- unittests/ExecutionEngine/JIT/JITTests.def | 4 - unittests/ExecutionEngine/JIT/Makefile | 52 - unittests/ExecutionEngine/JIT/MultiJITTest.cpp | 190 - .../JIT/OProfileJITEventListenerTest.cpp | 165 - unittests/ExecutionEngine/MCJIT/CMakeLists.txt | 1 - unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 40 +- .../MCJIT/MCJITMemoryManagerTest.cpp | 1 - .../MCJIT/MCJITMultipleModuleTest.cpp | 60 +- .../ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp | 43 +- unittests/ExecutionEngine/MCJIT/MCJITTest.cpp | 22 +- .../ExecutionEngine/MCJIT/MCJITTestAPICommon.h | 6 +- unittests/ExecutionEngine/MCJIT/MCJITTestBase.h | 26 +- unittests/ExecutionEngine/MCJIT/Makefile | 2 +- unittests/ExecutionEngine/Makefile | 2 +- unittests/IR/CMakeLists.txt | 3 +- unittests/IR/ConstantsTest.cpp | 73 + unittests/IR/DebugInfoTest.cpp | 68 + unittests/IR/DominatorTreeTest.cpp | 7 +- unittests/IR/IRBuilderTest.cpp | 4 + unittests/IR/LeakDetectorTest.cpp | 31 - unittests/IR/LegacyPassManagerTest.cpp | 52 +- unittests/IR/MDBuilderTest.cpp | 21 +- unittests/IR/MetadataTest.cpp | 456 +- unittests/IR/PassManagerTest.cpp | 35 +- unittests/IR/UseTest.cpp | 112 + unittests/IR/UserTest.cpp | 4 +- unittests/IR/ValueMapTest.cpp | 4 +- unittests/IR/ValueTest.cpp | 25 +- unittests/IR/WaymarkTest.cpp | 5 +- unittests/LineEditor/CMakeLists.txt | 1 + unittests/Linker/CMakeLists.txt | 1 + unittests/Linker/LinkModulesTest.cpp | 46 +- unittests/Linker/Makefile | 2 +- unittests/MC/CMakeLists.txt | 5 +- unittests/MC/Disassembler.cpp | 64 + unittests/MC/MCAtomTest.cpp | 31 - unittests/MC/Makefile | 2 +- unittests/MC/StringTableBuilderTest.cpp | 35 +- unittests/Support/AllocatorTest.cpp | 43 +- unittests/Support/CMakeLists.txt | 6 + unittests/Support/Casting.cpp | 96 + unittests/Support/CommandLineTest.cpp | 6 +- unittests/Support/CompressionTest.cpp | 2 +- unittests/Support/ConvertUTFTest.cpp | 20 +- unittests/Support/ErrorOrTest.cpp | 31 + unittests/Support/FileOutputBufferTest.cpp | 13 +- unittests/Support/LEB128Test.cpp | 37 + unittests/Support/LineIteratorTest.cpp | 130 +- unittests/Support/LockFileManagerTest.cpp | 4 +- unittests/Support/MD5Test.cpp | 16 +- unittests/Support/MemoryBufferTest.cpp | 50 + unittests/Support/MemoryTest.cpp | 2 +- unittests/Support/Path.cpp | 158 +- unittests/Support/ProcessTest.cpp | 20 - unittests/Support/ProgramTest.cpp | 100 + unittests/Support/ScaledNumberTest.cpp | 1 - unittests/Support/SourceMgrTest.cpp | 5 +- unittests/Support/SpecialCaseListTest.cpp | 51 +- unittests/Support/StreamingMemoryObject.cpp | 29 + unittests/Support/StringPool.cpp | 4 +- unittests/Support/ThreadLocalTest.cpp | 23 +- unittests/Support/YAMLIOTest.cpp | 7 + unittests/Support/YAMLParserTest.cpp | 7 +- unittests/Support/raw_ostream_test.cpp | 37 + unittests/Transforms/CMakeLists.txt | 1 - unittests/Transforms/DebugIR/CMakeLists.txt | 9 - unittests/Transforms/DebugIR/DebugIR.cpp | 308 - unittests/Transforms/DebugIR/Makefile | 15 - unittests/Transforms/Makefile | 2 +- unittests/Transforms/Utils/Cloning.cpp | 12 +- utils/FileCheck/FileCheck.cpp | 55 +- utils/TableGen/AsmMatcherEmitter.cpp | 463 +- utils/TableGen/AsmWriterEmitter.cpp | 80 +- utils/TableGen/AsmWriterInst.cpp | 4 +- utils/TableGen/AsmWriterInst.h | 7 +- utils/TableGen/CTagsEmitter.cpp | 16 +- utils/TableGen/CallingConvEmitter.cpp | 12 +- utils/TableGen/CodeEmitterGen.cpp | 26 +- utils/TableGen/CodeGenDAGPatterns.cpp | 144 +- utils/TableGen/CodeGenDAGPatterns.h | 29 +- utils/TableGen/CodeGenInstruction.cpp | 31 +- utils/TableGen/CodeGenInstruction.h | 8 +- utils/TableGen/CodeGenIntrinsics.h | 4 +- utils/TableGen/CodeGenRegisters.cpp | 474 +- utils/TableGen/CodeGenRegisters.h | 85 +- utils/TableGen/CodeGenSchedule.cpp | 48 +- utils/TableGen/CodeGenSchedule.h | 4 +- utils/TableGen/CodeGenTarget.cpp | 54 +- utils/TableGen/CodeGenTarget.h | 17 +- utils/TableGen/DAGISelEmitter.cpp | 12 +- utils/TableGen/DAGISelMatcher.h | 9 +- utils/TableGen/DAGISelMatcherEmitter.cpp | 2 +- utils/TableGen/DAGISelMatcherGen.cpp | 39 +- utils/TableGen/DAGISelMatcherOpt.cpp | 11 +- utils/TableGen/FastISelEmitter.cpp | 243 +- utils/TableGen/FixedLenDecoderEmitter.cpp | 163 +- utils/TableGen/InstrInfoEmitter.cpp | 12 +- utils/TableGen/IntrinsicEmitter.cpp | 43 +- utils/TableGen/PseudoLoweringEmitter.cpp | 9 +- utils/TableGen/RegisterInfoEmitter.cpp | 564 +- utils/TableGen/SequenceToOffsetTable.h | 9 +- utils/TableGen/SubtargetEmitter.cpp | 21 +- utils/TableGen/TableGen.cpp | 16 +- utils/TableGen/TableGenBackends.h | 4 + utils/TableGen/X86DisassemblerShared.h | 4 +- utils/TableGen/X86DisassemblerTables.cpp | 75 +- utils/TableGen/X86DisassemblerTables.h | 8 +- utils/TableGen/X86ModRMFilters.h | 4 +- utils/TableGen/X86RecognizableInstr.cpp | 274 +- utils/TableGen/X86RecognizableInstr.h | 8 +- utils/bisect | 37 + utils/emacs/emacs.el | 21 +- utils/emacs/llvm-mode.el | 98 +- utils/emacs/tablegen-mode.el | 20 +- utils/findmisopt | 4 +- utils/git-svn/git-svnrevert | 25 +- utils/lit/lit/ProgressBar.py | 8 +- utils/lit/lit/Test.py | 54 +- utils/lit/lit/TestRunner.py | 98 +- utils/lit/lit/TestingConfig.py | 14 +- utils/lit/lit/__init__.py | 2 +- utils/lit/lit/discovery.py | 2 +- utils/lit/lit/formats/googletest.py | 1 - utils/lit/lit/main.py | 16 +- utils/lit/lit/util.py | 27 +- utils/lit/tests/test-output.py | 2 - utils/lit/tests/xunit-output.py | 10 + utils/lldbDataFormatters.py | 33 + utils/llvm-build/llvmbuild/main.py | 47 +- utils/not/not.cpp | 14 +- utils/release/export.sh | 4 +- utils/release/merge.sh | 10 +- utils/release/tag.sh | 58 +- utils/release/test-release.sh | 53 +- utils/shuffle_fuzz.py | 256 + utils/update_llc_test_checks.py | 207 + utils/valgrind/x86_64-pc-linux-gnu.supp | 16 + utils/vim/llvm.vim | 41 +- utils/yaml-bench/YAMLBench.cpp | 6 +- 5966 files changed, 343873 insertions(+), 135595 deletions(-) create mode 100644 .clang-tidy create mode 100644 bindings/go/README.txt create mode 100755 bindings/go/build.sh create mode 100644 bindings/go/conftest.go create mode 100644 bindings/go/llvm/DIBuilderBindings.cpp create mode 100644 bindings/go/llvm/DIBuilderBindings.h create mode 100644 bindings/go/llvm/IRBindings.cpp create mode 100644 bindings/go/llvm/IRBindings.h create mode 100644 bindings/go/llvm/InstrumentationBindings.cpp create mode 100644 bindings/go/llvm/InstrumentationBindings.h create mode 100644 bindings/go/llvm/SupportBindings.cpp create mode 100644 bindings/go/llvm/SupportBindings.h create mode 100644 bindings/go/llvm/analysis.go create mode 100644 bindings/go/llvm/bitreader.go create mode 100644 bindings/go/llvm/bitwriter.go create mode 100644 bindings/go/llvm/dibuilder.go create mode 100644 bindings/go/llvm/executionengine.go create mode 100644 bindings/go/llvm/executionengine_test.go create mode 100644 bindings/go/llvm/ir.go create mode 100644 bindings/go/llvm/ir_test.go create mode 100644 bindings/go/llvm/linker.go create mode 100644 bindings/go/llvm/llvm_config.go.in create mode 100644 bindings/go/llvm/llvm_dep.go create mode 100644 bindings/go/llvm/string.go create mode 100644 bindings/go/llvm/string_test.go create mode 100644 bindings/go/llvm/support.go create mode 100644 bindings/go/llvm/target.go create mode 100644 bindings/go/llvm/transforms_instrumentation.go create mode 100644 bindings/go/llvm/transforms_ipo.go create mode 100644 bindings/go/llvm/transforms_pmbuilder.go create mode 100644 bindings/go/llvm/transforms_scalar.go create mode 100644 bindings/go/llvm/version.go create mode 100644 bindings/ocaml/CMakeLists.txt create mode 100644 bindings/ocaml/all_backends/CMakeLists.txt create mode 100644 bindings/ocaml/analysis/CMakeLists.txt create mode 100644 bindings/ocaml/backends/CMakeLists.txt create mode 100644 bindings/ocaml/bitreader/CMakeLists.txt create mode 100644 bindings/ocaml/bitwriter/CMakeLists.txt create mode 100644 bindings/ocaml/executionengine/CMakeLists.txt create mode 100644 bindings/ocaml/irreader/CMakeLists.txt create mode 100644 bindings/ocaml/linker/CMakeLists.txt create mode 100644 bindings/ocaml/llvm/CMakeLists.txt create mode 100644 bindings/ocaml/target/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/ipo/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt delete mode 100644 bindings/ocaml/transforms/scalar/Makefile delete mode 100644 bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml delete mode 100644 bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli delete mode 100644 bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c create mode 100644 bindings/ocaml/transforms/scalar_opts/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/scalar_opts/Makefile create mode 100644 bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.ml create mode 100644 bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli create mode 100644 bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c create mode 100644 bindings/ocaml/transforms/utils/CMakeLists.txt create mode 100644 bindings/ocaml/transforms/utils/Makefile create mode 100644 bindings/ocaml/transforms/utils/llvm_transform_utils.ml create mode 100644 bindings/ocaml/transforms/utils/llvm_transform_utils.mli create mode 100644 bindings/ocaml/transforms/utils/transform_utils_ocaml.c create mode 100644 bindings/ocaml/transforms/vectorize/CMakeLists.txt create mode 100644 cmake/modules/AddOCaml.cmake create mode 100644 cmake/modules/CrossCompile.cmake create mode 100644 cmake/modules/FindOCaml.cmake create mode 100644 cmake/platforms/iOS.cmake create mode 100644 docs/CoverageMappingFormat.rst create mode 100644 docs/MergeFunctions.rst create mode 100644 docs/R600Usage.rst create mode 100644 docs/Statepoints.rst create mode 100644 docs/tutorial/LangImpl9.rst create mode 100644 examples/Kaleidoscope/Chapter8/CMakeLists.txt create mode 100644 examples/Kaleidoscope/Chapter8/Makefile create mode 100644 examples/Kaleidoscope/Chapter8/toy.cpp create mode 100644 include/llvm/Analysis/AssumptionCache.h delete mode 100644 include/llvm/Analysis/FindUsedTypes.h create mode 100644 include/llvm/Analysis/FunctionTargetTransformInfo.h create mode 100644 include/llvm/CodeGen/DIE.h create mode 100644 include/llvm/CodeGen/ForwardControlFlowIntegrity.h delete mode 100644 include/llvm/CodeGen/JITCodeEmitter.h delete mode 100644 include/llvm/CodeGen/MachineCodeEmitter.h delete mode 100644 include/llvm/CodeGen/MachineCodeInfo.h create mode 100644 include/llvm/CodeGen/MachineCombinerPattern.h delete mode 100644 include/llvm/CodeGen/MachineRelocation.h delete mode 100644 include/llvm/CodeGen/PBQP/RegAllocSolver.h create mode 100644 include/llvm/CodeGen/PBQPRAConstraint.h create mode 100644 include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h create mode 100644 include/llvm/DebugInfo/DWARFAcceleratorTable.h create mode 100644 include/llvm/DebugInfo/DWARFCompileUnit.h create mode 100644 include/llvm/DebugInfo/DWARFContext.h create mode 100644 include/llvm/DebugInfo/DWARFDebugAbbrev.h create mode 100644 include/llvm/DebugInfo/DWARFDebugArangeSet.h create mode 100644 include/llvm/DebugInfo/DWARFDebugAranges.h create mode 100644 include/llvm/DebugInfo/DWARFDebugFrame.h create mode 100644 include/llvm/DebugInfo/DWARFDebugInfoEntry.h create mode 100644 include/llvm/DebugInfo/DWARFDebugLine.h create mode 100644 include/llvm/DebugInfo/DWARFDebugLoc.h create mode 100644 include/llvm/DebugInfo/DWARFDebugRangeList.h create mode 100644 include/llvm/DebugInfo/DWARFRelocMap.h create mode 100644 include/llvm/DebugInfo/DWARFSection.h create mode 100644 include/llvm/DebugInfo/DWARFTypeUnit.h create mode 100644 include/llvm/DebugInfo/DWARFUnit.h delete mode 100644 include/llvm/ExecutionEngine/JIT.h delete mode 100644 include/llvm/ExecutionEngine/JITMemoryManager.h delete mode 100644 include/llvm/ExecutionEngine/ObjectBuffer.h delete mode 100644 include/llvm/ExecutionEngine/ObjectImage.h delete mode 100644 include/llvm/IR/LeakDetector.h create mode 100644 include/llvm/IR/Metadata.def create mode 100644 include/llvm/IR/MetadataTracking.h create mode 100644 include/llvm/IR/PassManagerInternal.h create mode 100644 include/llvm/IR/Statepoint.h create mode 100644 include/llvm/IR/TrackingMDRef.h create mode 100644 include/llvm/IR/UseListOrder.h delete mode 100644 include/llvm/MC/MCAnalysis/MCAtom.h delete mode 100644 include/llvm/MC/MCAnalysis/MCFunction.h delete mode 100644 include/llvm/MC/MCAnalysis/MCModule.h delete mode 100644 include/llvm/MC/MCAnalysis/MCModuleYAML.h delete mode 100644 include/llvm/MC/MCObjectDisassembler.h delete mode 100644 include/llvm/MC/MCObjectSymbolizer.h create mode 100644 include/llvm/ProfileData/CoverageMapping.h create mode 100644 include/llvm/ProfileData/CoverageMappingReader.h create mode 100644 include/llvm/ProfileData/CoverageMappingWriter.h create mode 100644 include/llvm/ProfileData/SampleProf.h create mode 100644 include/llvm/ProfileData/SampleProfReader.h create mode 100644 include/llvm/ProfileData/SampleProfWriter.h create mode 100644 include/llvm/Support/ELFRelocs/AArch64.def create mode 100644 include/llvm/Support/ELFRelocs/ARM.def create mode 100644 include/llvm/Support/ELFRelocs/Hexagon.def create mode 100644 include/llvm/Support/ELFRelocs/Mips.def create mode 100644 include/llvm/Support/ELFRelocs/PowerPC.def create mode 100644 include/llvm/Support/ELFRelocs/PowerPC64.def create mode 100644 include/llvm/Support/ELFRelocs/Sparc.def create mode 100644 include/llvm/Support/ELFRelocs/SystemZ.def create mode 100644 include/llvm/Support/ELFRelocs/i386.def create mode 100644 include/llvm/Support/ELFRelocs/x86_64.def delete mode 100644 include/llvm/Support/IncludeFile.h create mode 100644 include/llvm/Support/Options.h delete mode 100644 include/llvm/Support/StreamableMemoryObject.h create mode 100644 include/llvm/Support/StreamingMemoryObject.h delete mode 100644 include/llvm/Support/StringRefMemoryObject.h create mode 100644 include/llvm/Support/UniqueLock.h delete mode 100644 include/llvm/Target/TargetJITInfo.h create mode 100644 include/llvm/Transforms/Utils/SymbolRewriter.h create mode 100644 lib/Analysis/AssumptionCache.cpp create mode 100644 lib/Analysis/CFLAliasAnalysis.cpp create mode 100644 lib/Analysis/FunctionTargetTransformInfo.cpp delete mode 100644 lib/Analysis/IPA/FindUsedTypes.cpp create mode 100644 lib/Analysis/ScopedNoAliasAA.cpp create mode 100644 lib/Analysis/StratifiedSets.h delete mode 100644 lib/CodeGen/AsmPrinter/DIE.h create mode 100644 lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp create mode 100644 lib/CodeGen/AsmPrinter/DwarfCompileUnit.h create mode 100644 lib/CodeGen/AsmPrinter/DwarfExpression.cpp create mode 100644 lib/CodeGen/AsmPrinter/DwarfExpression.h create mode 100644 lib/CodeGen/AsmPrinter/Win64Exception.h delete mode 100644 lib/CodeGen/AtomicExpandLoadLinkedPass.cpp create mode 100644 lib/CodeGen/AtomicExpandPass.cpp create mode 100644 lib/CodeGen/ForwardControlFlowIntegrity.cpp delete mode 100644 lib/CodeGen/JITCodeEmitter.cpp delete mode 100644 lib/CodeGen/MachineCodeEmitter.cpp create mode 100644 lib/CodeGen/MachineCombiner.cpp create mode 100644 lib/CodeGen/SelectionDAG/StatepointLowering.cpp create mode 100644 lib/CodeGen/SelectionDAG/StatepointLowering.h delete mode 100644 lib/CodeGen/Spiller.cpp create mode 100644 lib/CodeGen/StatepointExampleGC.cpp delete mode 100644 lib/DebugInfo/DWARFAbbreviationDeclaration.h create mode 100644 lib/DebugInfo/DWARFAcceleratorTable.cpp delete mode 100644 lib/DebugInfo/DWARFCompileUnit.h delete mode 100644 lib/DebugInfo/DWARFContext.h delete mode 100644 lib/DebugInfo/DWARFDebugAbbrev.h delete mode 100644 lib/DebugInfo/DWARFDebugArangeSet.h delete mode 100644 lib/DebugInfo/DWARFDebugAranges.h delete mode 100644 lib/DebugInfo/DWARFDebugFrame.h delete mode 100644 lib/DebugInfo/DWARFDebugInfoEntry.h delete mode 100644 lib/DebugInfo/DWARFDebugLine.h delete mode 100644 lib/DebugInfo/DWARFDebugLoc.h delete mode 100644 lib/DebugInfo/DWARFDebugRangeList.h delete mode 100644 lib/DebugInfo/DWARFRelocMap.h delete mode 100644 lib/DebugInfo/DWARFTypeUnit.h delete mode 100644 lib/DebugInfo/DWARFUnit.h create mode 100644 lib/DebugInfo/SyntaxHighlighting.cpp create mode 100644 lib/DebugInfo/SyntaxHighlighting.h create mode 100644 lib/ExecutionEngine/GDBRegistrationListener.cpp delete mode 100644 lib/ExecutionEngine/JIT/CMakeLists.txt delete mode 100644 lib/ExecutionEngine/JIT/JIT.cpp delete mode 100644 lib/ExecutionEngine/JIT/JIT.h delete mode 100644 lib/ExecutionEngine/JIT/JITEmitter.cpp delete mode 100644 lib/ExecutionEngine/JIT/JITMemoryManager.cpp delete mode 100644 lib/ExecutionEngine/JIT/LLVMBuild.txt delete mode 100644 lib/ExecutionEngine/JIT/Makefile create mode 100644 lib/ExecutionEngine/MCJIT/ObjectBuffer.h delete mode 100644 lib/ExecutionEngine/RuntimeDyld/GDBRegistrar.cpp delete mode 100644 lib/ExecutionEngine/RuntimeDyld/JITRegistrar.h delete mode 100644 lib/ExecutionEngine/RuntimeDyld/ObjectImageCommon.h create mode 100644 lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h delete mode 100644 lib/IR/LeakDetector.cpp create mode 100644 lib/IR/MetadataTracking.cpp create mode 100644 lib/IR/Statepoint.cpp create mode 100644 lib/IR/UseListOrder.cpp delete mode 100644 lib/MC/MCAnalysis/CMakeLists.txt delete mode 100644 lib/MC/MCAnalysis/LLVMBuild.txt delete mode 100644 lib/MC/MCAnalysis/MCAtom.cpp delete mode 100644 lib/MC/MCAnalysis/MCFunction.cpp delete mode 100644 lib/MC/MCAnalysis/MCModule.cpp delete mode 100644 lib/MC/MCAnalysis/MCModuleYAML.cpp delete mode 100644 lib/MC/MCAnalysis/MCObjectDisassembler.cpp delete mode 100644 lib/MC/MCAnalysis/MCObjectSymbolizer.cpp delete mode 100644 lib/MC/MCAnalysis/Makefile delete mode 100644 lib/MC/MCDisassembler.cpp create mode 100644 lib/MC/MCDisassembler/MCDisassembler.cpp create mode 100644 lib/MC/MCDisassembler/MCExternalSymbolizer.cpp create mode 100644 lib/MC/MCDisassembler/MCRelocationInfo.cpp delete mode 100644 lib/MC/MCExternalSymbolizer.cpp delete mode 100644 lib/MC/MCRelocationInfo.cpp create mode 100644 lib/MC/MCWinEH.cpp create mode 100644 lib/ProfileData/CoverageMapping.cpp create mode 100644 lib/ProfileData/CoverageMappingReader.cpp create mode 100644 lib/ProfileData/CoverageMappingWriter.cpp create mode 100644 lib/ProfileData/SampleProf.cpp create mode 100644 lib/ProfileData/SampleProfReader.cpp create mode 100644 lib/ProfileData/SampleProfWriter.cpp delete mode 100644 lib/Support/IncludeFile.cpp create mode 100644 lib/Support/MathExtras.cpp create mode 100644 lib/Support/Options.cpp delete mode 100644 lib/Support/StreamableMemoryObject.cpp create mode 100644 lib/Support/StreamingMemoryObject.cpp delete mode 100644 lib/Support/StringRefMemoryObject.cpp create mode 100644 lib/Target/AArch64/AArch64A53Fix835769.cpp create mode 100644 lib/Target/AArch64/AArch64A57FPLoadBalancing.cpp create mode 100644 lib/Target/AArch64/AArch64CallingConvention.h create mode 100644 lib/Target/AArch64/AArch64ConditionOptimizer.cpp create mode 100644 lib/Target/AArch64/AArch64MachineCombinerPattern.h create mode 100644 lib/Target/AArch64/AArch64PBQPRegAlloc.cpp create mode 100644 lib/Target/AArch64/AArch64PBQPRegAlloc.h delete mode 100644 lib/Target/ARM/ARMCodeEmitter.cpp delete mode 100644 lib/Target/ARM/ARMJITInfo.cpp delete mode 100644 lib/Target/ARM/ARMJITInfo.h delete mode 100644 lib/Target/ARM/ARMRelocations.h create mode 100644 lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h create mode 100644 lib/Target/ARM/MCTargetDesc/ARMAsmBackendDarwin.h create mode 100644 lib/Target/ARM/MCTargetDesc/ARMAsmBackendELF.h create mode 100644 lib/Target/ARM/MCTargetDesc/ARMAsmBackendWinCOFF.h create mode 100644 lib/Target/Hexagon/Disassembler/CMakeLists.txt create mode 100644 lib/Target/Hexagon/Disassembler/HexagonDisassembler.cpp create mode 100644 lib/Target/Hexagon/Disassembler/LLVMBuild.txt create mode 100644 lib/Target/Hexagon/Disassembler/Makefile delete mode 100644 lib/Target/Hexagon/InstPrinter/CMakeLists.txt delete mode 100644 lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.cpp delete mode 100644 lib/Target/Hexagon/InstPrinter/HexagonInstPrinter.h delete mode 100644 lib/Target/Hexagon/InstPrinter/LLVMBuild.txt delete mode 100644 lib/Target/Hexagon/InstPrinter/Makefile create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.cpp create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonInstPrinter.h create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp create mode 100644 lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.h create mode 100644 lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp create mode 100644 lib/Target/Mips/MCTargetDesc/MipsABIInfo.h delete mode 100644 lib/Target/Mips/MipsABIInfo.cpp delete mode 100644 lib/Target/Mips/MipsABIInfo.h delete mode 100644 lib/Target/Mips/MipsCodeEmitter.cpp delete mode 100644 lib/Target/Mips/MipsJITInfo.cpp delete mode 100644 lib/Target/Mips/MipsJITInfo.h delete mode 100644 lib/Target/Mips/MipsRelocations.h create mode 100644 lib/Target/NVPTX/NVPTXLowerStructArgs.cpp create mode 100644 lib/Target/NVPTX/NVPTXTargetTransformInfo.cpp create mode 100644 lib/Target/PowerPC/PPCCallingConv.h delete mode 100644 lib/Target/PowerPC/PPCCodeEmitter.cpp create mode 100644 lib/Target/PowerPC/PPCInstrSPE.td delete mode 100644 lib/Target/PowerPC/PPCJITInfo.cpp delete mode 100644 lib/Target/PowerPC/PPCJITInfo.h delete mode 100644 lib/Target/PowerPC/PPCRelocations.h create mode 100644 lib/Target/PowerPC/PPCScheduleP8.td create mode 100644 lib/Target/R600/AMDGPUAlwaysInlinePass.cpp create mode 100644 lib/Target/R600/AMDKernelCodeT.h create mode 100644 lib/Target/R600/AsmParser/AMDGPUAsmParser.cpp create mode 100644 lib/Target/R600/AsmParser/CMakeLists.txt create mode 100644 lib/Target/R600/AsmParser/LLVMBuild.txt create mode 100644 lib/Target/R600/AsmParser/Makefile create mode 100644 lib/Target/R600/CIInstructions.td create mode 100644 lib/Target/R600/SIFoldOperands.cpp create mode 100644 lib/Target/R600/SILoadStoreOptimizer.cpp create mode 100644 lib/Target/R600/SIPrepareScratchRegs.cpp create mode 100644 lib/Target/R600/VIInstrFormats.td create mode 100644 lib/Target/R600/VIInstructions.td delete mode 100644 lib/Target/Sparc/SparcCodeEmitter.cpp delete mode 100644 lib/Target/Sparc/SparcJITInfo.cpp delete mode 100644 lib/Target/Sparc/SparcJITInfo.h delete mode 100644 lib/Target/Sparc/SparcRelocations.h delete mode 100644 lib/Target/TargetJITInfo.cpp delete mode 100644 lib/Target/X86/X86AtomicExpandPass.cpp delete mode 100644 lib/Target/X86/X86CodeEmitter.cpp create mode 100644 lib/Target/X86/X86InstrSGX.td create mode 100644 lib/Target/X86/X86IntrinsicsInfo.h delete mode 100644 lib/Target/X86/X86JITInfo.cpp delete mode 100644 lib/Target/X86/X86JITInfo.h delete mode 100644 lib/Target/X86/X86Relocations.h create mode 100644 lib/Target/X86/X86ScheduleBtVer2.td delete mode 100644 lib/Transforms/Instrumentation/DebugIR.cpp delete mode 100644 lib/Transforms/Instrumentation/DebugIR.h create mode 100644 lib/Transforms/Instrumentation/InstrProfiling.cpp create mode 100644 lib/Transforms/Instrumentation/SanitizerCoverage.cpp create mode 100644 lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp create mode 100644 lib/Transforms/Scalar/AlignmentFromAssumptions.cpp create mode 100644 lib/Transforms/Utils/SymbolRewriter.cpp create mode 100644 test/Analysis/BasicAA/assume.ll create mode 100644 test/Analysis/BasicAA/zext.ll create mode 100644 test/Analysis/CFLAliasAnalysis/arguments-globals.ll create mode 100644 test/Analysis/CFLAliasAnalysis/arguments.ll create mode 100644 test/Analysis/CFLAliasAnalysis/basic-interproc-ret.ll create mode 100644 test/Analysis/CFLAliasAnalysis/basic-interproc.ll create mode 100644 test/Analysis/CFLAliasAnalysis/const-expr-gep.ll create mode 100644 test/Analysis/CFLAliasAnalysis/constant-over-index.ll create mode 100644 test/Analysis/CFLAliasAnalysis/empty.ll create mode 100644 test/Analysis/CFLAliasAnalysis/full-store-partial-alias.ll create mode 100644 test/Analysis/CFLAliasAnalysis/gep-signed-arithmetic.ll create mode 100644 test/Analysis/CFLAliasAnalysis/multilevel-combine.ll create mode 100644 test/Analysis/CFLAliasAnalysis/multilevel.ll create mode 100644 test/Analysis/CFLAliasAnalysis/must-and-partial.ll create mode 100644 test/Analysis/CFLAliasAnalysis/phi-and-select.ll create mode 100644 test/Analysis/CFLAliasAnalysis/simple.ll create mode 100644 test/Analysis/CFLAliasAnalysis/va.ll create mode 100644 test/Analysis/CostModel/PowerPC/cmp-expanded.ll create mode 100644 test/Analysis/DependenceAnalysis/NonCanonicalizedSubscript.ll create mode 100644 test/Analysis/Dominators/basic.ll create mode 100644 test/Analysis/ScalarEvolution/load-with-range-metadata.ll create mode 100644 test/Analysis/ScalarEvolution/nsw-offset-assume.ll create mode 100644 test/Analysis/ScalarEvolution/pr22179.ll create mode 100644 test/Analysis/ScopedNoAliasAA/basic-domains.ll create mode 100644 test/Analysis/ScopedNoAliasAA/basic.ll create mode 100644 test/Analysis/ScopedNoAliasAA/basic2.ll create mode 100644 test/Assembler/alias-use-list-order.ll create mode 100644 test/Assembler/distinct-mdnode.ll create mode 100644 test/Assembler/inline-asm-clobber.ll create mode 100644 test/Assembler/invalid-attrgrp.ll create mode 100644 test/Assembler/invalid-datalayout1.ll create mode 100644 test/Assembler/invalid-datalayout10.ll create mode 100644 test/Assembler/invalid-datalayout11.ll create mode 100644 test/Assembler/invalid-datalayout12.ll create mode 100644 test/Assembler/invalid-datalayout13.ll create mode 100644 test/Assembler/invalid-datalayout2.ll create mode 100644 test/Assembler/invalid-datalayout3.ll create mode 100644 test/Assembler/invalid-datalayout4.ll create mode 100644 test/Assembler/invalid-datalayout5.ll create mode 100644 test/Assembler/invalid-datalayout6.ll create mode 100644 test/Assembler/invalid-datalayout7.ll create mode 100644 test/Assembler/invalid-datalayout8.ll create mode 100644 test/Assembler/invalid-datalayout9.ll create mode 100644 test/Assembler/invalid-fwdref2.ll create mode 100644 test/Assembler/invalid-hexint.ll create mode 100644 test/Assembler/invalid-mdlocation-field-bad.ll create mode 100644 test/Assembler/invalid-mdlocation-field-twice.ll create mode 100644 test/Assembler/invalid-mdlocation-overflow-column.ll create mode 100644 test/Assembler/invalid-mdlocation-overflow-line.ll create mode 100644 test/Assembler/invalid-mdnode-vector.ll create mode 100644 test/Assembler/invalid-mdnode-vector2.ll create mode 100644 test/Assembler/invalid-metadata-attachment-has-type.ll create mode 100644 test/Assembler/invalid-metadata-function-local-attachments.ll create mode 100644 test/Assembler/invalid-metadata-function-local-complex-1.ll create mode 100644 test/Assembler/invalid-metadata-function-local-complex-2.ll create mode 100644 test/Assembler/invalid-metadata-function-local-complex-3.ll create mode 100644 test/Assembler/invalid-metadata-has-type.ll create mode 100644 test/Assembler/invalid-name2.ll create mode 100644 test/Assembler/invalid-specialized-mdnode.ll create mode 100644 test/Assembler/invalid-uselistorder-function-between-blocks.ll create mode 100644 test/Assembler/invalid-uselistorder-function-missing-named.ll create mode 100644 test/Assembler/invalid-uselistorder-function-missing-numbered.ll create mode 100644 test/Assembler/invalid-uselistorder-global-missing.ll create mode 100644 test/Assembler/invalid-uselistorder-indexes-duplicated.ll create mode 100644 test/Assembler/invalid-uselistorder-indexes-empty.ll create mode 100644 test/Assembler/invalid-uselistorder-indexes-one.ll create mode 100644 test/Assembler/invalid-uselistorder-indexes-ordered.ll create mode 100644 test/Assembler/invalid-uselistorder-indexes-range.ll create mode 100644 test/Assembler/invalid-uselistorder-indexes-toofew.ll create mode 100644 test/Assembler/invalid-uselistorder-indexes-toomany.ll create mode 100644 test/Assembler/invalid-uselistorder-type.ll create mode 100644 test/Assembler/invalid-uselistorder_bb-missing-bb.ll create mode 100644 test/Assembler/invalid-uselistorder_bb-missing-body.ll create mode 100644 test/Assembler/invalid-uselistorder_bb-missing-func.ll create mode 100644 test/Assembler/invalid-uselistorder_bb-not-bb.ll create mode 100644 test/Assembler/invalid-uselistorder_bb-not-func.ll create mode 100644 test/Assembler/invalid-uselistorder_bb-numbered.ll create mode 100644 test/Assembler/mdlocation.ll create mode 100644 test/Assembler/musttail-invalid-1.ll create mode 100644 test/Assembler/musttail-invalid-2.ll create mode 100644 test/Assembler/musttail.ll create mode 100644 test/Assembler/short-hexpair.ll create mode 100644 test/Assembler/unnamed-comdat.ll create mode 100644 test/Assembler/uselistorder.ll create mode 100644 test/Assembler/uselistorder_bb.ll create mode 100644 test/Bindings/Go/go.test create mode 100644 test/Bindings/Go/lit.local.cfg create mode 100644 test/Bindings/OCaml/analysis.ml create mode 100644 test/Bindings/OCaml/bitreader.ml create mode 100644 test/Bindings/OCaml/bitwriter.ml create mode 100644 test/Bindings/OCaml/core.ml create mode 100644 test/Bindings/OCaml/executionengine.ml create mode 100644 test/Bindings/OCaml/ext_exc.ml create mode 100644 test/Bindings/OCaml/ipo.ml create mode 100644 test/Bindings/OCaml/irreader.ml create mode 100644 test/Bindings/OCaml/linker.ml create mode 100644 test/Bindings/OCaml/lit.local.cfg create mode 100644 test/Bindings/OCaml/passmgr_builder.ml create mode 100644 test/Bindings/OCaml/scalar_opts.ml create mode 100644 test/Bindings/OCaml/target.ml create mode 100644 test/Bindings/OCaml/transform_utils.ml create mode 100644 test/Bindings/OCaml/vectorize.ml delete mode 100644 test/Bindings/Ocaml/analysis.ml delete mode 100644 test/Bindings/Ocaml/bitreader.ml delete mode 100644 test/Bindings/Ocaml/bitwriter.ml delete mode 100644 test/Bindings/Ocaml/executionengine.ml delete mode 100644 test/Bindings/Ocaml/ext_exc.ml delete mode 100644 test/Bindings/Ocaml/ipo_opts.ml delete mode 100644 test/Bindings/Ocaml/irreader.ml delete mode 100644 test/Bindings/Ocaml/linker.ml delete mode 100644 test/Bindings/Ocaml/lit.local.cfg delete mode 100644 test/Bindings/Ocaml/passmgr_builder.ml delete mode 100644 test/Bindings/Ocaml/scalar_opts.ml delete mode 100644 test/Bindings/Ocaml/target.ml delete mode 100644 test/Bindings/Ocaml/vectorize_opts.ml delete mode 100644 test/Bindings/Ocaml/vmcore.ml create mode 100644 test/Bindings/llvm-c/objectfile.ll create mode 100644 test/Bitcode/constantsTest.3.2.ll create mode 100644 test/Bitcode/constantsTest.3.2.ll.bc delete mode 100644 test/Bitcode/deprecated-linker_private-linker_private_weak.ll create mode 100644 test/Bitcode/function-local-metadata.3.5.ll create mode 100644 test/Bitcode/function-local-metadata.3.5.ll.bc create mode 100644 test/Bitcode/highLevelStructure.3.2.ll create mode 100644 test/Bitcode/highLevelStructure.3.2.ll.bc create mode 100644 test/Bitcode/mdstring-high-bits.ll create mode 100644 test/Bitcode/metadata.3.5.ll create mode 100644 test/Bitcode/metadata.3.5.ll.bc create mode 100644 test/Bitcode/standardCIntrinsic.3.2.ll create mode 100644 test/Bitcode/standardCIntrinsic.3.2.ll.bc create mode 100644 test/Bitcode/use-list-order.ll create mode 100644 test/CodeGen/AArch64/PBQP-chain.ll create mode 100644 test/CodeGen/AArch64/PBQP-coalesce-benefit.ll create mode 100644 test/CodeGen/AArch64/PBQP-csr.ll create mode 100644 test/CodeGen/AArch64/PBQP.ll create mode 100644 test/CodeGen/AArch64/Redundantstore.ll create mode 100644 test/CodeGen/AArch64/a57-csel.ll create mode 100644 test/CodeGen/AArch64/aarch64-2014-08-11-MachineCombinerCrash.ll create mode 100644 test/CodeGen/AArch64/aarch64-2014-12-02-combine-soften.ll create mode 100644 test/CodeGen/AArch64/aarch64-a57-fp-load-balancing.ll create mode 100644 test/CodeGen/AArch64/aarch64-be-bv.ll create mode 100644 test/CodeGen/AArch64/aarch64-fix-cortex-a53-835769.ll create mode 100644 test/CodeGen/AArch64/aarch64-gep-opt.ll create mode 100644 test/CodeGen/AArch64/aarch64-smull.ll create mode 100644 test/CodeGen/AArch64/aarch64-wide-shuffle.ll create mode 100644 test/CodeGen/AArch64/aarch64_f16_be.ll create mode 100644 test/CodeGen/AArch64/aarch64_tree_tests.ll create mode 100644 test/CodeGen/AArch64/analyzecmp.ll create mode 100644 test/CodeGen/AArch64/and-mask-removal.ll create mode 100644 test/CodeGen/AArch64/andandshift.ll create mode 100644 test/CodeGen/AArch64/argument-blocks.ll create mode 100644 test/CodeGen/AArch64/arm64-aapcs-be.ll create mode 100644 test/CodeGen/AArch64/arm64-bcc.ll delete mode 100644 test/CodeGen/AArch64/arm64-dagcombiner-indexed-load.ll delete mode 100644 test/CodeGen/AArch64/arm64-fast-isel-select.ll create mode 100644 test/CodeGen/AArch64/arm64-fast-isel-store.ll delete mode 100644 test/CodeGen/AArch64/arm64-frameaddr.ll create mode 100644 test/CodeGen/AArch64/arm64-patchpoint-scratch-regs.ll create mode 100644 test/CodeGen/AArch64/arm64-patchpoint-webkit_jscc.ll create mode 100644 test/CodeGen/AArch64/arm64-stackmap-nops.ll create mode 100644 test/CodeGen/AArch64/arm64-triv-disjoint-mem-access.ll create mode 100644 test/CodeGen/AArch64/bitcast-v2i8.ll create mode 100644 test/CodeGen/AArch64/br-to-eh-lpad.ll create mode 100644 test/CodeGen/AArch64/br-undef-cond.ll create mode 100644 test/CodeGen/AArch64/cmp-const-max.ll create mode 100644 test/CodeGen/AArch64/cmpwithshort.ll create mode 100644 test/CodeGen/AArch64/combine-comparisons-by-cse.ll create mode 100644 test/CodeGen/AArch64/dag-combine-invaraints.ll create mode 100644 test/CodeGen/AArch64/dont-take-over-the-world.ll create mode 100644 test/CodeGen/AArch64/fast-isel-addressing-modes.ll create mode 100644 test/CodeGen/AArch64/fast-isel-branch-cond-split.ll create mode 100644 test/CodeGen/AArch64/fast-isel-branch_weights.ll create mode 100644 test/CodeGen/AArch64/fast-isel-call-return.ll create mode 100644 test/CodeGen/AArch64/fast-isel-cbz.ll create mode 100644 test/CodeGen/AArch64/fast-isel-cmp-branch.ll create mode 100644 test/CodeGen/AArch64/fast-isel-folding.ll create mode 100644 test/CodeGen/AArch64/fast-isel-gep.ll create mode 100644 test/CodeGen/AArch64/fast-isel-int-ext.ll create mode 100644 test/CodeGen/AArch64/fast-isel-int-ext2.ll create mode 100644 test/CodeGen/AArch64/fast-isel-int-ext3.ll create mode 100644 test/CodeGen/AArch64/fast-isel-int-ext4.ll create mode 100644 test/CodeGen/AArch64/fast-isel-intrinsic.ll create mode 100644 test/CodeGen/AArch64/fast-isel-logic-op.ll create mode 100644 test/CodeGen/AArch64/fast-isel-memcpy.ll create mode 100644 test/CodeGen/AArch64/fast-isel-runtime-libcall.ll create mode 100644 test/CodeGen/AArch64/fast-isel-sdiv.ll create mode 100644 test/CodeGen/AArch64/fast-isel-select.ll create mode 100644 test/CodeGen/AArch64/fast-isel-shift.ll create mode 100644 test/CodeGen/AArch64/fast-isel-sqrt.ll create mode 100644 test/CodeGen/AArch64/fast-isel-switch-phi.ll create mode 100644 test/CodeGen/AArch64/fast-isel-tbz.ll create mode 100644 test/CodeGen/AArch64/fast-isel-trunc.ll create mode 100644 test/CodeGen/AArch64/fast-isel-vector-arithmetic.ll create mode 100644 test/CodeGen/AArch64/fast-isel-vret.ll create mode 100644 test/CodeGen/AArch64/fdiv-combine.ll create mode 100644 test/CodeGen/AArch64/fp16-instructions.ll create mode 100644 test/CodeGen/AArch64/fp16-v4-instructions.ll create mode 100644 test/CodeGen/AArch64/fp16-v8-instructions.ll create mode 100644 test/CodeGen/AArch64/fp16-vector-bitcast.ll create mode 100644 test/CodeGen/AArch64/fp16-vector-load-store.ll create mode 100644 test/CodeGen/AArch64/fp16-vector-shuffle.ll create mode 100644 test/CodeGen/AArch64/fpconv-vector-op-scalarize.ll create mode 100644 test/CodeGen/AArch64/legalize-bug-bogus-cpu.ll create mode 100644 test/CodeGen/AArch64/machine_cse.ll create mode 100644 test/CodeGen/AArch64/machine_cse_impdef_killflags.ll create mode 100644 test/CodeGen/AArch64/madd-combiner.ll create mode 100644 test/CodeGen/AArch64/madd-lohi.ll create mode 100644 test/CodeGen/AArch64/paired-load.ll create mode 100644 test/CodeGen/AArch64/postra-mi-sched.ll create mode 100644 test/CodeGen/AArch64/remat.ll create mode 100644 test/CodeGen/AArch64/rm_redundant_cmp.ll create mode 100644 test/CodeGen/AArch64/sdivpow2.ll create mode 100644 test/CodeGen/AArch64/stack-guard-remat-bitcast.ll create mode 100644 test/CodeGen/AArch64/stack_guard_remat.ll create mode 100644 test/CodeGen/AArch64/tailcall-fastisel.ll create mode 100644 test/CodeGen/AArch64/tbz-tbnz.ll delete mode 100644 test/CodeGen/ARM/2009-10-21-InvalidFNeg.ll create mode 100644 test/CodeGen/ARM/2014-08-04-muls-it.ll create mode 100644 test/CodeGen/ARM/adv-copy-opt.ll create mode 100644 test/CodeGen/ARM/arm32-round-conv.ll create mode 100644 test/CodeGen/ARM/arm32-rounding.ll create mode 100644 test/CodeGen/ARM/constant-islands.ll create mode 100644 test/CodeGen/ARM/copy-cpsr.ll create mode 100644 test/CodeGen/ARM/crc32.ll create mode 100644 test/CodeGen/ARM/dbg.ll create mode 100644 test/CodeGen/ARM/dwarf-unwind.ll create mode 100644 test/CodeGen/ARM/fpcmp-f64-neon-opt.ll create mode 100644 test/CodeGen/ARM/inlineasm-global.ll create mode 100644 test/CodeGen/ARM/invalid-target.ll create mode 100644 test/CodeGen/ARM/isel-v8i32-crash.ll delete mode 100644 test/CodeGen/ARM/jump_tables.ll create mode 100644 test/CodeGen/ARM/negative-offset.ll create mode 100644 test/CodeGen/ARM/no-tail-call.ll create mode 100644 test/CodeGen/ARM/none-macho-v4t.ll create mode 100644 test/CodeGen/ARM/pr18364-movw.ll create mode 100644 test/CodeGen/ARM/preferred-align.ll create mode 100644 test/CodeGen/ARM/smulw.ll create mode 100644 test/CodeGen/ARM/space-directive.ll create mode 100644 test/CodeGen/ARM/stack-alignment.ll create mode 100644 test/CodeGen/ARM/stack_guard_remat.ll create mode 100644 test/CodeGen/ARM/tail-call-weak.ll create mode 100644 test/CodeGen/ARM/tail-merge-branch-weight.ll create mode 100644 test/CodeGen/ARM/thumb1_return_sequence.ll create mode 100644 test/CodeGen/ARM/thumb2-size-opt.ll create mode 100644 test/CodeGen/ARM/thumb_indirect_calls.ll create mode 100644 test/CodeGen/ARM/vararg_no_start.ll create mode 100644 test/CodeGen/ARM/vector-load.ll create mode 100644 test/CodeGen/ARM/vector-promotion.ll create mode 100644 test/CodeGen/ARM/vector-store.ll create mode 100644 test/CodeGen/ARM/wrong-t2stmia-size-opt.ll create mode 100644 test/CodeGen/Generic/PBQP.ll create mode 100644 test/CodeGen/Generic/assume.ll create mode 100644 test/CodeGen/Generic/empty-insertvalue.ll create mode 100644 test/CodeGen/Generic/empty-phi.ll create mode 100644 test/CodeGen/Hexagon/cmp-not.ll create mode 100644 test/CodeGen/Hexagon/ctor.ll create mode 100644 test/CodeGen/MSP430/asm-clobbers.ll create mode 100644 test/CodeGen/MSP430/memset.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/br1.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/callabi.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/fpcmpa.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/fpext.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/fpintconv.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/fptrunc.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/icmpa.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/loadstoreconv.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/loadstrconst.ll create mode 100644 test/CodeGen/Mips/Fast-ISel/shift.ll create mode 100644 test/CodeGen/Mips/ctlz-v.ll create mode 100644 test/CodeGen/Mips/cttz-v.ll delete mode 100644 test/CodeGen/Mips/fptr2.ll create mode 100644 test/CodeGen/Mips/inlineasm-assembler-directives.ll create mode 100644 test/CodeGen/Mips/llvm-ir/mul.ll create mode 100644 test/CodeGen/Mips/llvm-ir/select.ll create mode 100644 test/CodeGen/Mips/micromips-addiu.ll create mode 100644 test/CodeGen/Mips/micromips-andi.ll create mode 100644 test/CodeGen/Mips/micromips-atomic1.ll create mode 100644 test/CodeGen/Mips/micromips-compact-branches.ll create mode 100644 test/CodeGen/Mips/micromips-delay-slot-jr.ll create mode 100644 test/CodeGen/Mips/micromips-delay-slot.ll create mode 100644 test/CodeGen/Mips/micromips-li.ll create mode 100644 test/CodeGen/Mips/micromips-rdhwr-directives.ll create mode 100644 test/CodeGen/Mips/micromips-shift.ll create mode 100644 test/CodeGen/Mips/mips16-hf-attr-2.ll create mode 100644 test/CodeGen/Mips/named-register-n32.ll create mode 100644 test/CodeGen/Mips/named-register-n64.ll create mode 100644 test/CodeGen/Mips/named-register-o32.ll create mode 100644 test/CodeGen/NVPTX/bug21465.ll create mode 100644 test/CodeGen/NVPTX/fma-assoc.ll create mode 100644 test/CodeGen/NVPTX/machine-sink.ll create mode 100644 test/CodeGen/NVPTX/nvcl-param-align.ll create mode 100644 test/CodeGen/NVPTX/vector-global.ll create mode 100644 test/CodeGen/NVPTX/vector-return.ll delete mode 100644 test/CodeGen/PowerPC/Atomics-32.ll create mode 100644 test/CodeGen/PowerPC/add-fi.ll create mode 100644 test/CodeGen/PowerPC/addi-licm.ll create mode 100644 test/CodeGen/PowerPC/arr-fp-arg-no-copy.ll create mode 100644 test/CodeGen/PowerPC/asm-constraints.ll create mode 100644 test/CodeGen/PowerPC/atomics-fences.ll create mode 100644 test/CodeGen/PowerPC/atomics-indexed.ll create mode 100644 test/CodeGen/PowerPC/atomics.ll create mode 100644 test/CodeGen/PowerPC/bperm.ll create mode 100644 test/CodeGen/PowerPC/byval-aliased.ll create mode 100644 test/CodeGen/PowerPC/cmpb-ppc32.ll create mode 100644 test/CodeGen/PowerPC/cmpb.ll create mode 100644 test/CodeGen/PowerPC/code-align.ll create mode 100644 test/CodeGen/PowerPC/constants-i64.ll create mode 100644 test/CodeGen/PowerPC/cttz-ctlz-spec.ll create mode 100644 test/CodeGen/PowerPC/fast-isel-const.ll create mode 100644 test/CodeGen/PowerPC/fdiv-combine.ll create mode 100644 test/CodeGen/PowerPC/fma-assoc.ll create mode 100644 test/CodeGen/PowerPC/fma-ext.ll create mode 100644 test/CodeGen/PowerPC/fma-mutate.ll create mode 100644 test/CodeGen/PowerPC/fmaxnum.ll create mode 100644 test/CodeGen/PowerPC/fminnum.ll create mode 100644 test/CodeGen/PowerPC/fp-to-int-ext.ll create mode 100644 test/CodeGen/PowerPC/fp-to-int-to-fp.ll create mode 100644 test/CodeGen/PowerPC/i1-ext-fold.ll create mode 100644 test/CodeGen/PowerPC/lbz-from-ld-shift.ll create mode 100644 test/CodeGen/PowerPC/ld-st-upd.ll create mode 100644 test/CodeGen/PowerPC/no-extra-fp-conv-ldst.ll create mode 100644 test/CodeGen/PowerPC/post-ra-ec.ll create mode 100644 test/CodeGen/PowerPC/ppc32-cyclecounter.ll create mode 100644 test/CodeGen/PowerPC/ppc32-pic-large.ll create mode 100644 test/CodeGen/PowerPC/ppc64-anyregcc-crash.ll create mode 100644 test/CodeGen/PowerPC/ppc64-anyregcc.ll create mode 100644 test/CodeGen/PowerPC/ppc64-elf-abi.ll create mode 100644 test/CodeGen/PowerPC/ppc64-gep-opt.ll create mode 100644 test/CodeGen/PowerPC/ppc64-nonfunc-calls.ll create mode 100644 test/CodeGen/PowerPC/ppc64-patchpoint.ll create mode 100644 test/CodeGen/PowerPC/ppc64-stackmap-nops.ll create mode 100644 test/CodeGen/PowerPC/ppc64-stackmap.ll create mode 100644 test/CodeGen/PowerPC/retaddr2.ll create mode 100644 test/CodeGen/PowerPC/rm-zext.ll create mode 100644 test/CodeGen/PowerPC/sdiv-pow2.ll create mode 100644 test/CodeGen/PowerPC/split-index-tc.ll create mode 100644 test/CodeGen/PowerPC/unal-altivec-wint.ll create mode 100644 test/CodeGen/PowerPC/vsx-div.ll create mode 100644 test/CodeGen/PowerPC/vsx-ldst-builtin-le.ll create mode 100644 test/CodeGen/PowerPC/vsx-ldst.ll create mode 100644 test/CodeGen/PowerPC/vsx-minmax.ll create mode 100644 test/CodeGen/PowerPC/vsx-p8.ll create mode 100644 test/CodeGen/PowerPC/vsx_insert_extract_le.ll create mode 100644 test/CodeGen/PowerPC/vsx_shuffle_le.ll create mode 100644 test/CodeGen/PowerPC/zext-free.ll create mode 100644 test/CodeGen/R600/add-debug.ll create mode 100644 test/CodeGen/R600/commute_modifiers.ll create mode 100644 test/CodeGen/R600/copy-to-reg.ll create mode 100644 test/CodeGen/R600/cttz-ctlz.ll create mode 100644 test/CodeGen/R600/ds-negative-offset-addressing-mode-loop.ll create mode 100644 test/CodeGen/R600/ds_read2.ll create mode 100644 test/CodeGen/R600/ds_read2_offset_order.ll create mode 100644 test/CodeGen/R600/ds_read2st64.ll create mode 100644 test/CodeGen/R600/ds_write2.ll create mode 100644 test/CodeGen/R600/ds_write2st64.ll create mode 100644 test/CodeGen/R600/empty-function.ll create mode 100644 test/CodeGen/R600/fabs.f64.ll create mode 100644 test/CodeGen/R600/flat-address-space.ll create mode 100644 test/CodeGen/R600/fma.f64.ll create mode 100644 test/CodeGen/R600/fmax3.ll create mode 100644 test/CodeGen/R600/fmax_legacy.f64.ll create mode 100644 test/CodeGen/R600/fmax_legacy.ll create mode 100644 test/CodeGen/R600/fmaxnum.f64.ll create mode 100644 test/CodeGen/R600/fmaxnum.ll create mode 100644 test/CodeGen/R600/fmin3.ll create mode 100644 test/CodeGen/R600/fmin_legacy.f64.ll create mode 100644 test/CodeGen/R600/fmin_legacy.ll create mode 100644 test/CodeGen/R600/fminnum.f64.ll create mode 100644 test/CodeGen/R600/fminnum.ll create mode 100644 test/CodeGen/R600/fneg-fabs.f64.ll create mode 100644 test/CodeGen/R600/fneg.f64.ll create mode 100644 test/CodeGen/R600/fp-classify.ll delete mode 100644 test/CodeGen/R600/fp64_to_sint.ll create mode 100644 test/CodeGen/R600/fp_to_sint.f64.ll create mode 100644 test/CodeGen/R600/frem.ll create mode 100644 test/CodeGen/R600/ftrunc.f64.ll create mode 100644 test/CodeGen/R600/global-directive.ll create mode 100644 test/CodeGen/R600/global-extload-i1.ll create mode 100644 test/CodeGen/R600/global-extload-i16.ll create mode 100644 test/CodeGen/R600/global-extload-i32.ll create mode 100644 test/CodeGen/R600/global-extload-i8.ll create mode 100644 test/CodeGen/R600/global-zero-initializer.ll create mode 100644 test/CodeGen/R600/global_atomics.ll create mode 100644 test/CodeGen/R600/hsa.ll create mode 100644 test/CodeGen/R600/i1-copy-implicit-def.ll create mode 100644 test/CodeGen/R600/i1-copy-phi.ll create mode 100644 test/CodeGen/R600/inline-asm.ll create mode 100644 test/CodeGen/R600/inline-calls.ll create mode 100644 test/CodeGen/R600/insert_subreg.ll delete mode 100644 test/CodeGen/R600/insert_vector_elt_f64.ll create mode 100644 test/CodeGen/R600/lds-initializer.ll create mode 100644 test/CodeGen/R600/lds-zero-initializer.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.class.ll create mode 100644 test/CodeGen/R600/llvm.AMDGPU.ldexp.ll create mode 100644 test/CodeGen/R600/llvm.memcpy.ll create mode 100644 test/CodeGen/R600/m0-spill.ll create mode 100644 test/CodeGen/R600/mad-sub.ll create mode 100644 test/CodeGen/R600/max.ll create mode 100644 test/CodeGen/R600/max3.ll create mode 100644 test/CodeGen/R600/min.ll create mode 100644 test/CodeGen/R600/min3.ll create mode 100644 test/CodeGen/R600/missing-store.ll create mode 100644 test/CodeGen/R600/no-shrink-extloads.ll create mode 100644 test/CodeGen/R600/operand-folding.ll create mode 100644 test/CodeGen/R600/operand-spacing.ll create mode 100644 test/CodeGen/R600/s_movk_i32.ll create mode 100644 test/CodeGen/R600/schedule-global-loads.ll create mode 100644 test/CodeGen/R600/schedule-kernel-arg-loads.ll create mode 100644 test/CodeGen/R600/sdivrem24.ll create mode 100644 test/CodeGen/R600/sext-eliminate.ll create mode 100644 test/CodeGen/R600/shl_add_constant.ll create mode 100644 test/CodeGen/R600/shl_add_ptr.ll create mode 100644 test/CodeGen/R600/si-triv-disjoint-mem-access.ll create mode 100644 test/CodeGen/R600/sint_to_fp.f64.ll delete mode 100644 test/CodeGen/R600/sint_to_fp64.ll create mode 100644 test/CodeGen/R600/split-scalar-i64-add.ll create mode 100644 test/CodeGen/R600/store-barrier.ll create mode 100644 test/CodeGen/R600/subreg-coalescer-crash.ll create mode 100644 test/CodeGen/R600/trunc-cmp-constant.ll create mode 100644 test/CodeGen/R600/udivrem24.ll create mode 100644 test/CodeGen/R600/use-sgpr-multiple-times.ll create mode 100644 test/CodeGen/SPARC/empty-functions.ll create mode 100644 test/CodeGen/Thumb/copy_thumb.ll create mode 100644 test/CodeGen/Thumb/ldm-merge-call.ll create mode 100644 test/CodeGen/Thumb/ldm-merge-struct.ll create mode 100644 test/CodeGen/Thumb/ldm-stm-base-materialization.ll create mode 100644 test/CodeGen/Thumb/stack_guard_remat.ll create mode 100644 test/CodeGen/Thumb/stm-merge.ll create mode 100644 test/CodeGen/Thumb2/aapcs.ll create mode 100644 test/CodeGen/Thumb2/constant-islands-jump-table.ll create mode 100644 test/CodeGen/Thumb2/constant-islands-new-island-padding.ll create mode 100644 test/CodeGen/Thumb2/constant-islands-new-island.ll create mode 100644 test/CodeGen/Thumb2/float-cmp.ll create mode 100644 test/CodeGen/Thumb2/float-intrinsics-double.ll create mode 100644 test/CodeGen/Thumb2/float-intrinsics-float.ll create mode 100644 test/CodeGen/Thumb2/float-ops.ll create mode 100644 test/CodeGen/Thumb2/stack_guard_remat.ll delete mode 100644 test/CodeGen/X86/2008-06-18-BadShuffle.ll delete mode 100644 test/CodeGen/X86/2009-04-21-NoReloadImpDef.ll delete mode 100644 test/CodeGen/X86/2012-05-19-avx2-store.ll create mode 100644 test/CodeGen/X86/2014-08-29-CompactUnwind.ll create mode 100644 test/CodeGen/X86/TruncAssertZext.ll create mode 100644 test/CodeGen/X86/add_shl_constant.ll create mode 100644 test/CodeGen/X86/addr-mode-matcher.ll create mode 100644 test/CodeGen/X86/adx-intrinsics.ll create mode 100644 test/CodeGen/X86/aligned-variadic.ll create mode 100644 test/CodeGen/X86/atomic_idempotent.ll create mode 100644 test/CodeGen/X86/atomic_mi.ll delete mode 100644 test/CodeGen/X86/avx-blend.ll create mode 100644 test/CodeGen/X86/avx-intrinsics-x86-upgrade.ll delete mode 100644 test/CodeGen/X86/avx-movdup.ll delete mode 100755 test/CodeGen/X86/avx-sext.ll delete mode 100644 test/CodeGen/X86/avx-shuffle.ll delete mode 100644 test/CodeGen/X86/avx-vmovddup.ll delete mode 100644 test/CodeGen/X86/avx-vperm2f128.ll create mode 100644 test/CodeGen/X86/avx-vperm2x128.ll delete mode 100644 test/CodeGen/X86/avx-vpermil.ll delete mode 100644 test/CodeGen/X86/avx-vshufp.ll delete mode 100755 test/CodeGen/X86/avx-zext.ll create mode 100644 test/CodeGen/X86/avx1-stack-reload-folding.ll delete mode 100644 test/CodeGen/X86/avx2-blend.ll create mode 100644 test/CodeGen/X86/avx2-intrinsics-x86-upgrade.ll delete mode 100644 test/CodeGen/X86/avx2-palignr.ll create mode 100644 test/CodeGen/X86/avx2-pmovx-256-old-shuffle.ll create mode 100644 test/CodeGen/X86/avx2-pmovxrm-intrinsics.ll delete mode 100644 test/CodeGen/X86/avx2-shuffle.ll delete mode 100644 test/CodeGen/X86/avx2-unpack.ll delete mode 100644 test/CodeGen/X86/avx2-vperm2i128.ll create mode 100755 test/CodeGen/X86/avx512-i1test.ll create mode 100644 test/CodeGen/X86/avx512-logic.ll delete mode 100644 test/CodeGen/X86/avx512-shuffle.ll delete mode 100644 test/CodeGen/X86/avx512-zext-load-crash.ll create mode 100644 test/CodeGen/X86/avx512bw-arith.ll create mode 100644 test/CodeGen/X86/avx512bw-intrinsics.ll create mode 100644 test/CodeGen/X86/avx512bw-mask-op.ll create mode 100644 test/CodeGen/X86/avx512bw-mov.ll create mode 100644 test/CodeGen/X86/avx512bw-vec-cmp.ll create mode 100644 test/CodeGen/X86/avx512bwvl-arith.ll create mode 100644 test/CodeGen/X86/avx512bwvl-intrinsics.ll create mode 100644 test/CodeGen/X86/avx512bwvl-mov.ll create mode 100644 test/CodeGen/X86/avx512bwvl-vec-cmp.ll create mode 100644 test/CodeGen/X86/avx512dq-mask-op.ll create mode 100644 test/CodeGen/X86/avx512er-intrinsics.ll create mode 100644 test/CodeGen/X86/avx512vl-arith.ll create mode 100644 test/CodeGen/X86/avx512vl-intrinsics.ll create mode 100644 test/CodeGen/X86/avx512vl-logic.ll create mode 100644 test/CodeGen/X86/avx512vl-mov.ll create mode 100644 test/CodeGen/X86/avx512vl-nontemporal.ll create mode 100644 test/CodeGen/X86/avx512vl-vec-cmp.ll delete mode 100644 test/CodeGen/X86/blend-msb.ll delete mode 100644 test/CodeGen/X86/break-avx-dep.ll create mode 100644 test/CodeGen/X86/break-false-dep.ll delete mode 100644 test/CodeGen/X86/break-sse-dep.ll create mode 100644 test/CodeGen/X86/byval-callee-cleanup.ll create mode 100644 test/CodeGen/X86/cfi_enforcing.ll create mode 100644 test/CodeGen/X86/cfi_invoke.ll create mode 100644 test/CodeGen/X86/cfi_non_default_function.ll create mode 100644 test/CodeGen/X86/cfi_simple_indirect_call.ll create mode 100644 test/CodeGen/X86/cmpxchg-clobber-flags.ll create mode 100644 test/CodeGen/X86/coalesce_commute_subreg.ll create mode 100644 test/CodeGen/X86/combine-and.ll delete mode 100644 test/CodeGen/X86/combine-vec-shuffle-2.ll delete mode 100644 test/CodeGen/X86/combine-vec-shuffle-3.ll delete mode 100644 test/CodeGen/X86/combine-vec-shuffle-4.ll delete mode 100644 test/CodeGen/X86/combine-vec-shuffle-5.ll delete mode 100644 test/CodeGen/X86/combine-vec-shuffle.ll create mode 100644 test/CodeGen/X86/commute-blend-avx2.ll create mode 100644 test/CodeGen/X86/commute-blend-sse41.ll create mode 100644 test/CodeGen/X86/commuted-blend-mask.ll create mode 100644 test/CodeGen/X86/copysign-constant-magnitude.ll delete mode 100644 test/CodeGen/X86/copysign-zero.ll create mode 100644 test/CodeGen/X86/cpus.ll create mode 100644 test/CodeGen/X86/critical-anti-dep-breaker.ll create mode 100644 test/CodeGen/X86/cttz-ctlz.ll create mode 100644 test/CodeGen/X86/divrem8_ext.ll create mode 100644 test/CodeGen/X86/dont-trunc-store-double-to-float.ll create mode 100644 test/CodeGen/X86/dynamic-alloca-lifetime.ll create mode 100644 test/CodeGen/X86/equiv_with_fndef.ll create mode 100644 test/CodeGen/X86/equiv_with_vardef.ll create mode 100644 test/CodeGen/X86/fast-isel-call-bool.ll create mode 100644 test/CodeGen/X86/fast-isel-x32.ll create mode 100644 test/CodeGen/X86/fastmath-optnone.ll create mode 100644 test/CodeGen/X86/fma-intrinsics-x86_64.ll create mode 100644 test/CodeGen/X86/fma-phi-213-to-231.ll create mode 100644 test/CodeGen/X86/fma4-intrinsics-x86_64-folded-load.ll delete mode 100644 test/CodeGen/X86/fma4-intrinsics-x86_64.ll create mode 100644 test/CodeGen/X86/fmaxnum.ll create mode 100644 test/CodeGen/X86/fminnum.ll create mode 100644 test/CodeGen/X86/fmul-combines.ll create mode 100644 test/CodeGen/X86/fnabs.ll delete mode 100644 test/CodeGen/X86/fold-pcmpeqd-0.ll create mode 100644 test/CodeGen/X86/fold-tied-op.ll create mode 100644 test/CodeGen/X86/fpstack-debuginstr-kill.ll create mode 100644 test/CodeGen/X86/frameallocate.ll create mode 100644 test/CodeGen/X86/gcc_except_table_functions.ll delete mode 100644 test/CodeGen/X86/i8-umulo.ll create mode 100644 test/CodeGen/X86/inalloca-regparm.ll create mode 100644 test/CodeGen/X86/jump_table_align.ll create mode 100644 test/CodeGen/X86/large-code-model-isel.ll create mode 100644 test/CodeGen/X86/lea-5.ll delete mode 100644 test/CodeGen/X86/long-extend.ll create mode 100644 test/CodeGen/X86/lower-vec-shift-2.ll create mode 100644 test/CodeGen/X86/masked_memop.ll create mode 100644 test/CodeGen/X86/mem-intrin-base-reg.ll create mode 100644 test/CodeGen/X86/misched-code-difference-with-debug.ll create mode 100644 test/CodeGen/X86/movtopush.ll create mode 100644 test/CodeGen/X86/musttail-fastcall.ll create mode 100644 test/CodeGen/X86/musttail-varargs.ll delete mode 100644 test/CodeGen/X86/no-compact-unwind.ll create mode 100644 test/CodeGen/X86/nontemporal-2.ll create mode 100644 test/CodeGen/X86/patchpoint-invoke.ll create mode 100644 test/CodeGen/X86/patchpoint-webkit_jscc.ll delete mode 100644 test/CodeGen/X86/peep-vector-extract-concat.ll delete mode 100644 test/CodeGen/X86/peep-vector-extract-insert.ll create mode 100644 test/CodeGen/X86/peephole-fold-movsd.ll delete mode 100644 test/CodeGen/X86/pr12359.ll create mode 100644 test/CodeGen/X86/pr18846.ll create mode 100644 test/CodeGen/X86/pr21099.ll create mode 100644 test/CodeGen/X86/pr21529.ll create mode 100644 test/CodeGen/X86/pr22019.ll create mode 100644 test/CodeGen/X86/pr22103.ll create mode 100644 test/CodeGen/X86/prologuedata.ll create mode 100644 test/CodeGen/X86/pshufb-mask-comments.ll create mode 100644 test/CodeGen/X86/recip-fastmath.ll create mode 100644 test/CodeGen/X86/regalloc-reconcile-broken-hints.ll create mode 100644 test/CodeGen/X86/return_zeroext_i2.ll create mode 100644 test/CodeGen/X86/seh-basic.ll create mode 100644 test/CodeGen/X86/seh-safe-div.ll create mode 100644 test/CodeGen/X86/sink-blockfreq.ll create mode 100644 test/CodeGen/X86/sjlj-baseptr.ll create mode 100644 test/CodeGen/X86/slow-div.ll create mode 100644 test/CodeGen/X86/slow-incdec.ll create mode 100644 test/CodeGen/X86/splat-for-size.ll delete mode 100644 test/CodeGen/X86/splat-scalar-load.ll delete mode 100644 test/CodeGen/X86/sse-scalar-fp-arith-2.ll delete mode 100644 test/CodeGen/X86/sse2-blend.ll delete mode 100644 test/CodeGen/X86/sse2-mul.ll delete mode 100644 test/CodeGen/X86/sse41-blend.ll create mode 100644 test/CodeGen/X86/sse41-intrinsics-x86-upgrade.ll create mode 100644 test/CodeGen/X86/sse41-pmovxrm-intrinsics.ll create mode 100644 test/CodeGen/X86/stack-probe-size.ll create mode 100644 test/CodeGen/X86/stack-protector-weight.ll create mode 100644 test/CodeGen/X86/stack_guard_remat.ll create mode 100644 test/CodeGen/X86/stackmap-large-constants.ll create mode 100644 test/CodeGen/X86/stackmap-shadow-optimization.ll create mode 100644 test/CodeGen/X86/statepoint-call-lowering.ll create mode 100644 test/CodeGen/X86/statepoint-forward.ll create mode 100644 test/CodeGen/X86/statepoint-stack-usage.ll create mode 100644 test/CodeGen/X86/statepoint-stackmap-format.ll create mode 100644 test/CodeGen/X86/switch-default-only.ll create mode 100644 test/CodeGen/X86/switch-jump-table.ll delete mode 100644 test/CodeGen/X86/swizzle.ll create mode 100644 test/CodeGen/X86/tailcall-multiret.ll create mode 100644 test/CodeGen/X86/tls-addr-non-leaf-function.ll create mode 100644 test/CodeGen/X86/unaligned-32-byte-memops.ll delete mode 100644 test/CodeGen/X86/v-binop-widen.ll delete mode 100644 test/CodeGen/X86/v-binop-widen2.ll create mode 100644 test/CodeGen/X86/vararg-callee-cleanup.ll create mode 100644 test/CodeGen/X86/vararg_no_start.ll create mode 100644 test/CodeGen/X86/vec-loadsingles-alignment.ll delete mode 100644 test/CodeGen/X86/vec_compare-2.ll create mode 100644 test/CodeGen/X86/vec_extract-avx.ll delete mode 100644 test/CodeGen/X86/vec_insert-6.ll delete mode 100644 test/CodeGen/X86/vec_insert.ll delete mode 100644 test/CodeGen/X86/vec_set-5.ll delete mode 100644 test/CodeGen/X86/vec_set-9.ll delete mode 100644 test/CodeGen/X86/vec_set-E.ll delete mode 100644 test/CodeGen/X86/vec_set-G.ll delete mode 100644 test/CodeGen/X86/vec_set-I.ll delete mode 100644 test/CodeGen/X86/vec_set-J.ll delete mode 100644 test/CodeGen/X86/vec_sext.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-11.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-14.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-15.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-16.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-17.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-18.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-19.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-20.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-22.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-23.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-24.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-25.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-26.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-27.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-28.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-30.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-31.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-34.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-35.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-36.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-37.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-38.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-39.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-40.ll delete mode 100644 test/CodeGen/X86/vec_shuffle-41.ll delete mode 100644 test/CodeGen/X86/vec_shuffle.ll delete mode 100644 test/CodeGen/X86/vec_splat-2.ll delete mode 100644 test/CodeGen/X86/vec_splat-3.ll delete mode 100644 test/CodeGen/X86/vec_splat.ll create mode 100644 test/CodeGen/X86/vec_trunc_sext.ll create mode 100644 test/CodeGen/X86/vec_unsafe-fp-math.ll delete mode 100644 test/CodeGen/X86/vec_zext.ll create mode 100644 test/CodeGen/X86/vector-blend.ll create mode 100644 test/CodeGen/X86/vector-ctpop.ll create mode 100644 test/CodeGen/X86/vector-sext.ll create mode 100644 test/CodeGen/X86/vector-shuffle-256-v16.ll create mode 100644 test/CodeGen/X86/vector-shuffle-256-v32.ll create mode 100644 test/CodeGen/X86/vector-shuffle-256-v4.ll create mode 100644 test/CodeGen/X86/vector-shuffle-256-v8.ll create mode 100644 test/CodeGen/X86/vector-shuffle-512-v16.ll create mode 100644 test/CodeGen/X86/vector-shuffle-512-v8.ll create mode 100644 test/CodeGen/X86/vector-shuffle-sse1.ll create mode 100644 test/CodeGen/X86/vector-trunc.ll create mode 100644 test/CodeGen/X86/vector-zext.ll create mode 100644 test/CodeGen/X86/vector-zmov.ll create mode 100644 test/CodeGen/X86/vectorcall.ll create mode 100644 test/CodeGen/X86/vselect-avx.ll create mode 100644 test/CodeGen/X86/win32-pic-jumptable.ll create mode 100644 test/CodeGen/X86/win64_call_epi.ll create mode 100644 test/CodeGen/X86/windows-itanium-alloca.ll create mode 100644 test/CodeGen/X86/x32-function_pointer-1.ll create mode 100644 test/CodeGen/X86/x32-function_pointer-2.ll create mode 100644 test/CodeGen/X86/x32-function_pointer-3.ll create mode 100644 test/CodeGen/X86/x86-64-call.ll create mode 100644 test/CodeGen/X86/x86-64-stack-and-frame-ptr.ll create mode 100644 test/CodeGen/X86/x86-inline-asm-validation.ll create mode 100644 test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll create mode 100644 test/DebugInfo/AArch64/big-endian-dump.ll create mode 100644 test/DebugInfo/AArch64/big-endian.ll create mode 100644 test/DebugInfo/AArch64/cfi-eof-prologue.ll create mode 100644 test/DebugInfo/AArch64/coalescing.ll create mode 100644 test/DebugInfo/AArch64/little-endian-dump.ll create mode 100644 test/DebugInfo/AArch64/processes-relocations.ll create mode 100644 test/DebugInfo/ARM/big-endian-dump.ll create mode 100644 test/DebugInfo/ARM/cfi-eof-prologue.ll create mode 100644 test/DebugInfo/ARM/little-endian-dump.ll create mode 100644 test/DebugInfo/ARM/processes-relocations.ll create mode 100644 test/DebugInfo/ARM/s-super-register.ll create mode 100644 test/DebugInfo/COFF/cpp-mangling.ll create mode 100644 test/DebugInfo/Inputs/cross-cu-inlining.c create mode 100644 test/DebugInfo/Inputs/cross-cu-inlining.x86_64-macho.o create mode 100644 test/DebugInfo/Inputs/dwarfdump-objc.m create mode 100644 test/DebugInfo/Inputs/dwarfdump-objc.x86_64.o create mode 100644 test/DebugInfo/Inputs/gmlt.ll create mode 100755 test/DebugInfo/Inputs/split-dwarf-test create mode 100644 test/DebugInfo/Inputs/split-dwarf-test.cc create mode 100644 test/DebugInfo/Inputs/split-dwarf-test.dwo create mode 100644 test/DebugInfo/Mips/processes-relocations.ll create mode 100644 test/DebugInfo/PowerPC/processes-relocations.ll create mode 100644 test/DebugInfo/Sparc/processes-relocations.ll create mode 100644 test/DebugInfo/SystemZ/processes-relocations.ll create mode 100644 test/DebugInfo/X86/asm-macro-line-number.s create mode 100644 test/DebugInfo/X86/constant-aggregate.ll create mode 100644 test/DebugInfo/X86/debug-info-access.ll create mode 100644 test/DebugInfo/X86/fission-inline.ll create mode 100644 test/DebugInfo/X86/ghost-sdnode-dbgvalues.ll create mode 100644 test/DebugInfo/X86/gmlt.test create mode 100644 test/DebugInfo/X86/memberfnptr.ll create mode 100644 test/DebugInfo/X86/nodebug_with_debug_loc.ll create mode 100644 test/DebugInfo/X86/pieces-1.ll create mode 100644 test/DebugInfo/X86/pieces-2.ll create mode 100644 test/DebugInfo/X86/pieces-3.ll create mode 100644 test/DebugInfo/X86/processes-relocations.ll create mode 100644 test/DebugInfo/X86/recursive_inlining.ll create mode 100644 test/DebugInfo/block-asan.ll create mode 100644 test/DebugInfo/cross-cu-linkonce-distinct.ll delete mode 100644 test/DebugInfo/cu-line-tables.ll create mode 100644 test/DebugInfo/debug-info-always-inline.ll create mode 100644 test/DebugInfo/duplicate_inline.ll create mode 100644 test/DebugInfo/dwarfdump-accel.test create mode 100644 test/DebugInfo/dwarfdump-objc.test create mode 100644 test/DebugInfo/enum-types.ll create mode 100644 test/DebugInfo/gmlt.test create mode 100644 test/DebugInfo/incorrect-variable-debugloc1.ll create mode 100644 test/DebugInfo/member-pointers.o create mode 100644 test/DebugInfo/missing-abstract-variable.o create mode 100644 test/DebugInfo/multiline.ll create mode 100644 test/DebugInfo/nodebug.ll delete mode 100644 test/ExecutionEngine/2003-05-11-PHIRegAllocBug.ll delete mode 100644 test/ExecutionEngine/2003-06-04-bzip2-bug.ll delete mode 100644 test/ExecutionEngine/2003-06-05-PHIBug.ll create mode 100644 test/ExecutionEngine/Interpreter/intrinsics.ll create mode 100644 test/ExecutionEngine/Interpreter/lit.local.cfg delete mode 100644 test/ExecutionEngine/MCJIT/non-extern-addend-smallcodemodel.ll create mode 100644 test/ExecutionEngine/RuntimeDyld/AArch64/MachO_ARM64_relocations.s create mode 100644 test/ExecutionEngine/RuntimeDyld/AArch64/lit.local.cfg create mode 100644 test/ExecutionEngine/RuntimeDyld/X86/MachO_i386_DynNoPIC_relocations.s create mode 100644 test/ExecutionEngine/RuntimeDyld/X86/MachO_i386_eh_frame.s create mode 100644 test/ExecutionEngine/frem.ll create mode 100644 test/Feature/prologuedata.ll create mode 100644 test/FileCheck/check-empty.txt create mode 100644 test/Instrumentation/AddressSanitizer/X86/asm_cfi.ll create mode 100644 test/Instrumentation/AddressSanitizer/X86/asm_cfi.s create mode 100644 test/Instrumentation/AddressSanitizer/X86/asm_rep_movs.ll create mode 100644 test/Instrumentation/AddressSanitizer/X86/asm_rsp_mem_op.s delete mode 100644 test/Instrumentation/AddressSanitizer/coverage-dbg.ll delete mode 100644 test/Instrumentation/AddressSanitizer/coverage.ll create mode 100644 test/Instrumentation/AddressSanitizer/do-not-instrument-cstring.ll create mode 100644 test/Instrumentation/AddressSanitizer/instrument-dynamic-allocas.ll delete mode 100644 test/Instrumentation/AddressSanitizer/keep-instrumented_functions.ll create mode 100644 test/Instrumentation/AddressSanitizer/stack_dynamic_alloca.ll create mode 100644 test/Instrumentation/AddressSanitizer/undecidable-dynamic-alloca-1.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/Inputs/debuglist.txt create mode 100644 test/Instrumentation/DataFlowSanitizer/debug.ll create mode 100644 test/Instrumentation/DataFlowSanitizer/union-large.ll create mode 100644 test/Instrumentation/InstrProfiling/no-counters.ll create mode 100644 test/Instrumentation/InstrProfiling/noruntime.ll create mode 100644 test/Instrumentation/InstrProfiling/platform.ll create mode 100644 test/Instrumentation/InstrProfiling/profiling.ll create mode 100644 test/Instrumentation/MemorySanitizer/array_types.ll create mode 100644 test/Instrumentation/MemorySanitizer/byval-alignment.ll create mode 100644 test/Instrumentation/MemorySanitizer/check-constant-shadow.ll delete mode 100644 test/Instrumentation/MemorySanitizer/do-not-emit-module-limits.ll create mode 100644 test/Instrumentation/MemorySanitizer/origin-alignment.ll delete mode 100644 test/Instrumentation/MemorySanitizer/wrap_indirect_calls.ll create mode 100644 test/Instrumentation/SanitizerCoverage/coverage-dbg.ll create mode 100644 test/Instrumentation/SanitizerCoverage/coverage.ll create mode 100644 test/Instrumentation/SanitizerCoverage/coverage2-dbg.ll create mode 100644 test/Instrumentation/SanitizerCoverage/tracing.ll create mode 100644 test/JitListener/multiple.ll create mode 100644 test/JitListener/simple.ll delete mode 100644 test/JitListener/test-common-symbols.ll delete mode 100644 test/JitListener/test-inline.ll delete mode 100644 test/JitListener/test-parameters.ll create mode 100644 test/LTO/Inputs/bcsection.macho.s create mode 100644 test/LTO/Inputs/bcsection.s create mode 100644 test/LTO/Inputs/invalid.ll.bc create mode 100644 test/LTO/Inputs/list-symbols.ll create mode 100644 test/LTO/bcsection.ll create mode 100644 test/LTO/diagnostic-handler-remarks.ll create mode 100644 test/LTO/invalid.ll create mode 100644 test/LTO/list-symbols.ll delete mode 100644 test/Linker/2006-06-15-GlobalVarAlignment.ll create mode 100644 test/Linker/ConstantGlobals.ll delete mode 100644 test/Linker/ConstantGlobals1.ll delete mode 100644 test/Linker/ConstantGlobals2.ll delete mode 100644 test/Linker/ConstantGlobals3.ll create mode 100644 test/Linker/Inputs/2003-01-30-LinkerRename.ll create mode 100644 test/Linker/Inputs/2003-05-31-LinkerRename.ll create mode 100644 test/Linker/Inputs/ConstantGlobals.ll create mode 100644 test/Linker/Inputs/alignment.ll create mode 100644 test/Linker/Inputs/comdat8.ll create mode 100644 test/Linker/Inputs/constructor-comdat.ll create mode 100644 test/Linker/Inputs/ctors.ll create mode 100644 test/Linker/Inputs/distinct.ll create mode 100644 test/Linker/Inputs/ident.a.ll create mode 100644 test/Linker/Inputs/ident.b.ll create mode 100644 test/Linker/Inputs/linkage2.ll create mode 100644 test/Linker/Inputs/mdlocation.ll create mode 100644 test/Linker/Inputs/module-flags-dont-change-others.ll create mode 100644 test/Linker/Inputs/module-flags-pic-1-b.ll create mode 100644 test/Linker/Inputs/module-flags-pic-2-b.ll create mode 100644 test/Linker/Inputs/opaque.ll create mode 100644 test/Linker/Inputs/pr21374.ll create mode 100644 test/Linker/Inputs/redefinition.ll create mode 100644 test/Linker/Inputs/replaced-function-matches-first-subprogram.ll create mode 100644 test/Linker/Inputs/testlink.ll create mode 100644 test/Linker/Inputs/type-unique-alias.ll create mode 100644 test/Linker/Inputs/type-unique-dst-types2.ll create mode 100644 test/Linker/Inputs/type-unique-dst-types3.ll create mode 100644 test/Linker/Inputs/type-unique-name.ll create mode 100644 test/Linker/Inputs/type-unique-opaque.ll create mode 100644 test/Linker/Inputs/type-unique-unrelated2.ll create mode 100644 test/Linker/Inputs/type-unique-unrelated3.ll create mode 100644 test/Linker/Inputs/unique-fwd-decl-b.ll create mode 100644 test/Linker/Inputs/unique-fwd-decl-order.ll create mode 100644 test/Linker/Inputs/visibility.ll create mode 100644 test/Linker/alignment.ll create mode 100644 test/Linker/comdat9.ll create mode 100644 test/Linker/constructor-comdat.ll create mode 100644 test/Linker/ctors.ll create mode 100644 test/Linker/distinct.ll create mode 100644 test/Linker/ident.ll delete mode 100644 test/Linker/link-messages.ll create mode 100644 test/Linker/linkage2.ll create mode 100644 test/Linker/lto-attributes.ll create mode 100644 test/Linker/mdlocation.ll create mode 100644 test/Linker/module-flags-dont-change-others.ll create mode 100644 test/Linker/module-flags-pic-1-a.ll create mode 100644 test/Linker/module-flags-pic-2-a.ll create mode 100644 test/Linker/opaque.ll create mode 100644 test/Linker/pr21374.ll create mode 100644 test/Linker/pr21494.ll delete mode 100644 test/Linker/prefixdata.ll create mode 100644 test/Linker/prologuedata.ll create mode 100644 test/Linker/replaced-function-matches-first-subprogram.ll create mode 100644 test/Linker/testlink.ll delete mode 100644 test/Linker/testlink1.ll delete mode 100644 test/Linker/testlink2.ll create mode 100644 test/Linker/type-unique-alias.ll create mode 100644 test/Linker/type-unique-dst-types.ll create mode 100644 test/Linker/type-unique-name.ll create mode 100644 test/Linker/type-unique-opaque.ll create mode 100644 test/Linker/type-unique-src-type.ll create mode 100644 test/Linker/type-unique-type-array-a.ll create mode 100644 test/Linker/type-unique-type-array-b.ll create mode 100644 test/Linker/type-unique-unrelated.ll create mode 100644 test/Linker/unique-fwd-decl-a.ll create mode 100644 test/Linker/unique-fwd-decl-order.ll create mode 100644 test/Linker/visibility.ll delete mode 100644 test/Linker/visibility1.ll delete mode 100644 test/Linker/visibility2.ll create mode 100644 test/MC/AArch64/elf_osabi_flags.s create mode 100644 test/MC/AArch64/inst-directive-diagnostic.s create mode 100644 test/MC/AArch64/inst-directive.s create mode 100644 test/MC/AArch64/single-slash.s create mode 100644 test/MC/ARM/arm-elf-relocation-diagnostics.s create mode 100644 test/MC/ARM/arm-elf-relocations.s create mode 100644 test/MC/ARM/arm-load-store-multiple-deprecated.s create mode 100644 test/MC/ARM/coproc-diag.s create mode 100644 test/MC/ARM/cps.s create mode 100644 test/MC/ARM/cpu-test.s create mode 100644 test/MC/ARM/d16.s create mode 100644 test/MC/ARM/directive-arch_extension-mode-switch.s create mode 100644 test/MC/ARM/directive-arch_extension-toggle.s delete mode 100644 test/MC/ARM/directive-eabi_attribute-2.s create mode 100644 test/MC/ARM/directive-fpu-instrs.s create mode 100644 test/MC/ARM/directive-thumb_func.s create mode 100644 test/MC/ARM/directive-unsupported.s create mode 100644 test/MC/ARM/dwarf-asm-multiple-sections-dwarf-2.s create mode 100644 test/MC/ARM/move-banked-regs.s create mode 100644 test/MC/ARM/neon-mov-vfp.s create mode 100644 test/MC/ARM/thumb-load-store-multiple.s create mode 100644 test/MC/ARM/thumb-not-mclass.s create mode 100644 test/MC/ARM/thumb2-bxj.s create mode 100644 test/MC/ARM/thumb2-exception-return-mclass.s create mode 100644 test/MC/ARM/thumb2-ldrb-ldrh.s create mode 100644 test/MC/ARM/thumb2-ldrexd-strexd.s create mode 100644 test/MC/ARM/thumb_rewrites.s create mode 100644 test/MC/ARM/thumbv7em.s create mode 100644 test/MC/ARM/virtexts-arm.s create mode 100644 test/MC/ARM/virtexts-thumb.s create mode 100644 test/MC/AsmParser/comments-x86-darwin.s create mode 100644 test/MC/AsmParser/directive-warning.s create mode 100644 test/MC/AsmParser/macro-exitm.s create mode 100644 test/MC/COFF/bigobj.py create mode 100644 test/MC/COFF/comm-align.s create mode 100644 test/MC/COFF/const-gv-with-rel-init.ll create mode 100644 test/MC/COFF/section-passthru-flags.s create mode 100644 test/MC/COFF/seh-linkonce.s create mode 100644 test/MC/Disassembler/ARM/d16.txt create mode 100644 test/MC/Disassembler/ARM/invalid-thumb-MSR-MClass.txt create mode 100644 test/MC/Disassembler/ARM/invalid-virtexts.arm.txt create mode 100644 test/MC/Disassembler/ARM/move-banked-regs-arm.txt create mode 100644 test/MC/Disassembler/ARM/move-banked-regs-thumb.txt create mode 100644 test/MC/Disassembler/ARM/thumb2-preloads.txt create mode 100644 test/MC/Disassembler/ARM/virtexts-arm.txt create mode 100644 test/MC/Disassembler/ARM/virtexts-thumb.txt create mode 100644 test/MC/Disassembler/Hexagon/alu32_alu.txt create mode 100644 test/MC/Disassembler/Hexagon/alu32_perm.txt create mode 100644 test/MC/Disassembler/Hexagon/alu32_pred.txt create mode 100644 test/MC/Disassembler/Hexagon/cr.txt create mode 100644 test/MC/Disassembler/Hexagon/j.txt create mode 100644 test/MC/Disassembler/Hexagon/jr.txt create mode 100644 test/MC/Disassembler/Hexagon/ld.txt create mode 100644 test/MC/Disassembler/Hexagon/lit.local.cfg create mode 100644 test/MC/Disassembler/Hexagon/memop.txt create mode 100644 test/MC/Disassembler/Hexagon/nv_j.txt create mode 100644 test/MC/Disassembler/Hexagon/nv_st.txt create mode 100644 test/MC/Disassembler/Hexagon/st.txt create mode 100644 test/MC/Disassembler/Hexagon/system_user.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_alu.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_bit.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_fp.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_mpy.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_perm.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_pred.txt create mode 100644 test/MC/Disassembler/Hexagon/xtype_shift.txt create mode 100644 test/MC/Disassembler/Mips/mips1/valid-mips1-el.txt create mode 100644 test/MC/Disassembler/Mips/mips1/valid-mips1.txt create mode 100644 test/MC/Disassembler/Mips/mips1/valid-xfail.txt create mode 100644 test/MC/Disassembler/Mips/mips2/valid-mips2-el.txt create mode 100644 test/MC/Disassembler/Mips/mips2/valid-mips2.txt create mode 100644 test/MC/Disassembler/Mips/mips3/valid-mips3-el.txt create mode 100644 test/MC/Disassembler/Mips/mips3/valid-mips3.txt create mode 100644 test/MC/Disassembler/Mips/mips32/valid-mips32-el.txt create mode 100644 test/MC/Disassembler/Mips/mips32/valid-mips32.txt create mode 100644 test/MC/Disassembler/Mips/mips32/valid-xfail-mips32.txt create mode 100644 test/MC/Disassembler/Mips/mips32r2/valid-mips32r2-le.txt create mode 100644 test/MC/Disassembler/Mips/mips32r2/valid-mips32r2.txt create mode 100644 test/MC/Disassembler/Mips/mips32r2/valid-xfail-mips32r2.txt create mode 100644 test/MC/Disassembler/Mips/mips4/valid-mips4-el.txt create mode 100644 test/MC/Disassembler/Mips/mips4/valid-mips4.txt create mode 100644 test/MC/Disassembler/Mips/mips4/valid-xfail-mips4.txt create mode 100644 test/MC/Disassembler/PowerPC/ppc64-encoding-4xx.txt create mode 100644 test/MC/Disassembler/PowerPC/ppc64-encoding-6xx.txt create mode 100644 test/MC/Disassembler/PowerPC/ppc64-encoding-e500.txt delete mode 100644 test/MC/Disassembler/X86/invalid-cmp-imm.txt create mode 100644 test/MC/ELF/cfi-large-model.s create mode 100644 test/MC/ELF/reloc-same-name-section.s create mode 100644 test/MC/ELF/section-sym-err.s create mode 100644 test/MC/ELF/section-sym.s create mode 100644 test/MC/ELF/section-sym2.s create mode 100644 test/MC/Hexagon/basic.ll create mode 100644 test/MC/Hexagon/inst_add.ll create mode 100644 test/MC/Hexagon/inst_add64.ll create mode 100644 test/MC/Hexagon/inst_and.ll create mode 100644 test/MC/Hexagon/inst_and64.ll create mode 100644 test/MC/Hexagon/inst_aslh.ll create mode 100644 test/MC/Hexagon/inst_asrh.ll create mode 100644 test/MC/Hexagon/inst_cmp_eq.ll create mode 100644 test/MC/Hexagon/inst_cmp_eqi.ll create mode 100644 test/MC/Hexagon/inst_cmp_gt.ll create mode 100644 test/MC/Hexagon/inst_cmp_gti.ll create mode 100644 test/MC/Hexagon/inst_cmp_lt.ll create mode 100644 test/MC/Hexagon/inst_cmp_ugt.ll create mode 100644 test/MC/Hexagon/inst_cmp_ugti.ll create mode 100644 test/MC/Hexagon/inst_cmp_ult.ll create mode 100644 test/MC/Hexagon/inst_or.ll create mode 100644 test/MC/Hexagon/inst_or64.ll create mode 100644 test/MC/Hexagon/inst_select.ll create mode 100644 test/MC/Hexagon/inst_sub.ll create mode 100644 test/MC/Hexagon/inst_sub64.ll create mode 100644 test/MC/Hexagon/inst_sxtb.ll create mode 100644 test/MC/Hexagon/inst_sxth.ll create mode 100644 test/MC/Hexagon/inst_xor.ll create mode 100644 test/MC/Hexagon/inst_xor64.ll create mode 100644 test/MC/Hexagon/inst_zxtb.ll create mode 100644 test/MC/Hexagon/inst_zxth.ll create mode 100644 test/MC/Hexagon/lit.local.cfg create mode 100644 test/MC/MachO/AArch64/mergeable.s create mode 100644 test/MC/MachO/AArch64/reloc-crash.s create mode 100644 test/MC/MachO/AArch64/reloc-crash2.s create mode 100644 test/MC/MachO/bad-darwin-x86_64-reloc-expr1.s create mode 100644 test/MC/MachO/bad-darwin-x86_64-reloc-expr2.s delete mode 100644 test/MC/MachO/empty-dwarf-lines.s create mode 100644 test/MC/MachO/x86_64-mergeable.s delete mode 100644 test/MC/Mips/elf-objdump.s create mode 100644 test/MC/Mips/micromips-branch7.s create mode 100644 test/MC/Mips/micromips-func-addr.s create mode 100644 test/MC/Mips/micromips-invalid.s create mode 100644 test/MC/Mips/micromips-label-test-sections.s create mode 100644 test/MC/Mips/micromips-label-test.s create mode 100644 test/MC/Mips/mips-hwr-register-names.s create mode 100644 test/MC/Mips/mips-jump-delay-slots.s create mode 100644 test/MC/Mips/mips-pdr-bad.s create mode 100644 test/MC/Mips/mips-pdr.s create mode 100644 test/MC/Mips/mips1/invalid-mips32r2.s create mode 100644 test/MC/Mips/mips3/invalid-mips32r2.s create mode 100644 test/MC/Mips/mips3/invalid-mips4-wrong-error.s create mode 100644 test/MC/Mips/mips4/invalid-mips32r2.s create mode 100644 test/MC/Mips/mips5/invalid-mips32r2.s create mode 100644 test/MC/Mips/mips64/invalid-mips32r2.s create mode 100644 test/MC/Mips/msa/set-msa-directive-bad.s create mode 100644 test/MC/Mips/msa/set-msa-directive.s create mode 100644 test/MC/Mips/set-arch.s create mode 100644 test/MC/Mips/set-mips-directives-bad.s create mode 100644 test/MC/Mips/set-mips-directives.s create mode 100644 test/MC/Mips/set-mips0-directive.s create mode 100644 test/MC/Mips/set-mips16-directive.s create mode 100644 test/MC/Mips/set-nodsp.s create mode 100644 test/MC/Mips/set-push-pop-directives-bad.s create mode 100644 test/MC/Mips/set-push-pop-directives.s create mode 100644 test/MC/Mips/unaligned-nops.s create mode 100644 test/MC/PowerPC/lcomm.s create mode 100644 test/MC/PowerPC/ppc32-ba.s create mode 100644 test/MC/PowerPC/ppc64-encoding-4xx.s create mode 100644 test/MC/PowerPC/ppc64-encoding-6xx.s create mode 100644 test/MC/PowerPC/ppc64-encoding-e500.s create mode 100644 test/MC/PowerPC/ppc64-encoding-spe.s create mode 100644 test/MC/R600/lit.local.cfg create mode 100644 test/MC/R600/sopp.s create mode 100644 test/MC/X86/AlignedBundling/labeloffset.s create mode 100644 test/MC/X86/AlignedBundling/nesting.s create mode 100644 test/MC/X86/avx512bw-encoding.s create mode 100644 test/MC/X86/avx512vl-encoding.s create mode 100644 test/MC/X86/compact-unwind.s create mode 100644 test/MC/X86/intel-syntax-ambiguous.s create mode 100644 test/MC/X86/intel-syntax-error.s create mode 100644 test/MC/X86/intel-syntax-ptr-sized.s create mode 100644 test/MC/X86/intel-syntax-unsized-memory.s create mode 100644 test/MC/X86/macho-uleb.s create mode 100644 test/MC/X86/reloc-macho.s create mode 100644 test/MC/X86/sgx-encoding.s create mode 100644 test/MC/X86/validate-inst-att.s create mode 100644 test/MC/X86/validate-inst-intel.s create mode 100644 test/MC/X86/x86-64-avx512bw.s create mode 100644 test/MC/X86/x86-64-avx512bw_vl.s create mode 100644 test/MC/X86/x86-64-avx512dq.s create mode 100644 test/MC/X86/x86-64-avx512dq_vl.s create mode 100644 test/MC/X86/x86-64-avx512f_vl.s create mode 100644 test/Object/AArch64/yaml2obj-elf-aarch64-rel.yaml create mode 100644 test/Object/Inputs/COFF/long-section-name.yaml create mode 100644 test/Object/Inputs/COFF/section-aux-symbol.yaml create mode 100644 test/Object/Inputs/macho-archive-unsorted-x86_64.a create mode 100755 test/Object/Inputs/macho-no-exports.dylib create mode 100755 test/Object/Inputs/macho-rpath-x86_64 create mode 100644 test/Object/Inputs/macho-zero-ncmds create mode 100755 test/Object/Inputs/micro-mips.elf-mipsel create mode 100644 test/Object/Inputs/mri-crlf.mri create mode 100644 test/Object/Inputs/thin.a create mode 100644 test/Object/Inputs/trivial-label-test.elf-x86-64 create mode 100644 test/Object/Mips/objdump-micro-mips.test delete mode 100644 test/Object/X86/objdump-cfg-invalid-opcode.yaml delete mode 100644 test/Object/X86/objdump-cfg-textatomsize.yaml delete mode 100644 test/Object/X86/objdump-cfg.yaml delete mode 100644 test/Object/X86/objdump-disassembly-symbolic.test create mode 100644 test/Object/X86/objdump-label.test create mode 100644 test/Object/mri-addlib.test create mode 100644 test/Object/mri-addmod.test create mode 100644 test/Object/mri-crlf.test create mode 100644 test/Object/mri1.test create mode 100644 test/Object/mri2.test create mode 100644 test/Object/mri3.test create mode 100644 test/Object/mri4.test create mode 100644 test/Object/mri5.test create mode 100644 test/Object/obj2yaml-coff-long-section-name.test create mode 100644 test/Object/obj2yaml-coff-section-aux-symbol.test create mode 100644 test/Object/objdump-export-list.test create mode 100644 test/Object/objdump-macho-quirks.test create mode 100644 test/Object/objdump-reloc-shared.test create mode 100755 test/Other/Inputs/block-info-only.bc create mode 100644 test/Other/Inputs/has-block-info.bc create mode 100755 test/Other/Inputs/no-block-info.bc create mode 100644 test/Other/bcanalyzer-block-info.txt delete mode 100644 test/Other/link-opts.ll create mode 100644 test/Other/lit-unicode.txt create mode 100644 test/SymbolRewriter/rewrite.ll create mode 100644 test/SymbolRewriter/rewrite.map create mode 100644 test/TableGen/BitOffsetDecoder.td create mode 100644 test/TableGen/BitsInit.td create mode 100644 test/TableGen/ClassInstanceValue.td create mode 100644 test/Transforms/AlignmentFromAssumptions/simple.ll create mode 100644 test/Transforms/AlignmentFromAssumptions/simple32.ll create mode 100644 test/Transforms/AlignmentFromAssumptions/start-unk.ll create mode 100644 test/Transforms/ArgumentPromotion/fp80.ll create mode 100644 test/Transforms/ArgumentPromotion/variadic.ll create mode 100644 test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll create mode 100644 test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll create mode 100644 test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll create mode 100644 test/Transforms/AtomicExpand/ARM/lit.local.cfg delete mode 100644 test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v7.ll delete mode 100644 test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v8.ll delete mode 100644 test/Transforms/AtomicExpandLoadLinked/ARM/cmpxchg-weak.ll delete mode 100644 test/Transforms/AtomicExpandLoadLinked/ARM/lit.local.cfg create mode 100644 test/Transforms/CodeGenPrepare/AArch64/lit.local.cfg create mode 100644 test/Transforms/CodeGenPrepare/AArch64/trunc-weird-user.ll create mode 100644 test/Transforms/ConstProp/trunc_vec.ll create mode 100644 test/Transforms/CorrelatedValuePropagation/icmp.ll delete mode 100644 test/Transforms/DebugIR/crash.ll delete mode 100644 test/Transforms/DebugIR/exception.ll delete mode 100644 test/Transforms/DebugIR/function.ll delete mode 100644 test/Transforms/DebugIR/simple-addrspace.ll delete mode 100644 test/Transforms/DebugIR/simple.ll delete mode 100644 test/Transforms/DebugIR/struct.ll delete mode 100644 test/Transforms/DebugIR/vector.ll create mode 100644 test/Transforms/FunctionAttrs/optnone-simple.ll create mode 100644 test/Transforms/FunctionAttrs/optnone.ll create mode 100644 test/Transforms/GCOVProfiling/function-numbering.ll create mode 100644 test/Transforms/GCOVProfiling/return-block.ll create mode 100644 test/Transforms/GVN/load-from-unreachable-predecessor.ll create mode 100644 test/Transforms/GVN/noalias.ll create mode 100644 test/Transforms/GVN/pre-gep-load.ll create mode 100644 test/Transforms/GlobalDCE/deadblockaddr.ll create mode 100644 test/Transforms/GlobalDCE/pr20981.ll create mode 100644 test/Transforms/GlobalOpt/pr21191.ll create mode 100644 test/Transforms/GlobalOpt/preserve-comdats.ll create mode 100644 test/Transforms/IndVarSimplify/NVPTX/lit.local.cfg create mode 100644 test/Transforms/IndVarSimplify/NVPTX/no-widen-expensive.ll create mode 100644 test/Transforms/IndVarSimplify/backedge-on-min-max.ll create mode 100644 test/Transforms/IndVarSimplify/sharpen-range.ll create mode 100644 test/Transforms/IndVarSimplify/strengthen-overflow.ll create mode 100644 test/Transforms/IndVarSimplify/use-range-metadata.ll create mode 100644 test/Transforms/IndVarSimplify/widen-loop-comp.ll create mode 100644 test/Transforms/Inline/align.ll create mode 100644 test/Transforms/Inline/ephemeral.ll create mode 100644 test/Transforms/Inline/inline-musttail-varargs.ll create mode 100644 test/Transforms/Inline/inline_dbg_declare.ll create mode 100644 test/Transforms/Inline/noalias-calls.ll create mode 100644 test/Transforms/Inline/noalias-cs.ll create mode 100644 test/Transforms/Inline/noalias.ll create mode 100644 test/Transforms/Inline/noalias2.ll create mode 100644 test/Transforms/Inline/pr21206.ll delete mode 100644 test/Transforms/InstCombine/2008-02-16-SDivOverflow.ll delete mode 100644 test/Transforms/InstCombine/add4.ll create mode 100644 test/Transforms/InstCombine/alias-recursion.ll create mode 100644 test/Transforms/InstCombine/align-attr.ll create mode 100644 test/Transforms/InstCombine/assume-loop-align.ll create mode 100644 test/Transforms/InstCombine/assume-redundant.ll create mode 100644 test/Transforms/InstCombine/assume.ll create mode 100644 test/Transforms/InstCombine/assume2.ll create mode 100644 test/Transforms/InstCombine/cast-int-fcmp-eq-0.ll create mode 100644 test/Transforms/InstCombine/constant-fold-alias.ll delete mode 100644 test/Transforms/InstCombine/devirt.ll create mode 100644 test/Transforms/InstCombine/fabs.ll create mode 100644 test/Transforms/InstCombine/icmp-range.ll create mode 100644 test/Transforms/InstCombine/icmp-shr.ll delete mode 100644 test/Transforms/InstCombine/load-addrspace-cast.ll create mode 100644 test/Transforms/InstCombine/loadstore-metadata.ll create mode 100644 test/Transforms/InstCombine/maxnum.ll create mode 100644 test/Transforms/InstCombine/minnum.ll create mode 100644 test/Transforms/InstCombine/narrow-switch.ll create mode 100644 test/Transforms/InstCombine/no_cgscc_assert.ll create mode 100644 test/Transforms/InstCombine/pr21199.ll create mode 100644 test/Transforms/InstCombine/pr21210.ll create mode 100644 test/Transforms/InstCombine/pr21651.ll create mode 100644 test/Transforms/InstCombine/pr21891.ll create mode 100644 test/Transforms/InstCombine/range-check.ll create mode 100644 test/Transforms/InstCombine/select-cmp-br.ll create mode 100644 test/Transforms/InstCombine/statepoint.ll create mode 100644 test/Transforms/InstCombine/unordered-fcmp-select.ll create mode 100644 test/Transforms/InstCombine/vsx-unaligned.ll create mode 100644 test/Transforms/InstMerge/ld_hoist1.ll create mode 100644 test/Transforms/InstMerge/st_sink_barrier_call.ll create mode 100644 test/Transforms/InstMerge/st_sink_no_barrier_call.ll create mode 100644 test/Transforms/InstMerge/st_sink_no_barrier_load.ll create mode 100644 test/Transforms/InstMerge/st_sink_no_barrier_store.ll create mode 100644 test/Transforms/InstMerge/st_sink_two_stores.ll create mode 100644 test/Transforms/InstMerge/st_sink_with_barrier.ll delete mode 100644 test/Transforms/InstSimplify/ashr-nop.ll create mode 100644 test/Transforms/InstSimplify/assume.ll create mode 100644 test/Transforms/InstSimplify/fold-builtin-fma.ll create mode 100644 test/Transforms/InstSimplify/gep.ll create mode 100644 test/Transforms/InstSimplify/noalias-ptr.ll create mode 100644 test/Transforms/InstSimplify/select.ll create mode 100644 test/Transforms/InstSimplify/shr-nop.ll create mode 100644 test/Transforms/InstSimplify/vector_ptr_bitcast.ll create mode 100644 test/Transforms/JumpThreading/assume-edge-dom.ll create mode 100644 test/Transforms/JumpThreading/assume.ll create mode 100644 test/Transforms/JumpThreading/conservative-lvi.ll create mode 100644 test/Transforms/JumpThreading/pr22086.ll create mode 100644 test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll create mode 100644 test/Transforms/LICM/PR19798.ll create mode 100644 test/Transforms/LICM/preheader-safe.ll create mode 100644 test/Transforms/LoadCombine/load-combine-aa.ll create mode 100644 test/Transforms/LoadCombine/load-combine-assume.ll create mode 100644 test/Transforms/LoopRotate/nosimplifylatch.ll create mode 100644 test/Transforms/LoopUnroll/PowerPC/p7-unrolling.ll create mode 100644 test/Transforms/LoopUnroll/ephemeral.ll create mode 100644 test/Transforms/LoopUnroll/ignore-annotation-intrinsic-cost.ll create mode 100644 test/Transforms/LoopUnroll/nsw-tripcount.ll create mode 100644 test/Transforms/LoopUnroll/tripcount-overflow.ll create mode 100644 test/Transforms/LoopUnroll/update-loop-info-in-subloops.ll create mode 100644 test/Transforms/LoopVectorize/AArch64/sdiv-pow2.ll create mode 100644 test/Transforms/LoopVectorize/X86/assume.ll create mode 100644 test/Transforms/LoopVectorize/X86/masked_load_store.ll create mode 100644 test/Transforms/LoopVectorize/X86/powof2div.ll create mode 100644 test/Transforms/LoopVectorize/conditional-assignment.ll create mode 100644 test/Transforms/LoopVectorize/duplicated-metadata.ll create mode 100644 test/Transforms/LoopVectorize/exact.ll create mode 100644 test/Transforms/LoopVectorize/loop-vect-memdep.ll create mode 100644 test/Transforms/MemCpyOpt/callslot_deref.ll create mode 100644 test/Transforms/MemCpyOpt/memcpy-to-memset-with-lifetimes.ll create mode 100644 test/Transforms/MergeFunc/vector-GEP-crash.ll create mode 100644 test/Transforms/ObjCARC/provenance.ll create mode 100644 test/Transforms/PartiallyInlineLibCalls/bad-prototype.ll create mode 100644 test/Transforms/Reassociate/canonicalize-neg-const.ll create mode 100644 test/Transforms/Reassociate/commute.ll create mode 100644 test/Transforms/Reassociate/fast-AgressiveSubMove.ll create mode 100644 test/Transforms/Reassociate/fast-ArrayOutOfBounds.ll create mode 100644 test/Transforms/Reassociate/fast-MissedTree.ll create mode 100644 test/Transforms/Reassociate/fast-ReassociateVector.ll create mode 100644 test/Transforms/Reassociate/fast-SubReassociate.ll create mode 100644 test/Transforms/Reassociate/fast-basictest.ll create mode 100644 test/Transforms/Reassociate/fast-fp-commute.ll create mode 100644 test/Transforms/Reassociate/fast-mightymul.ll create mode 100644 test/Transforms/Reassociate/fast-multistep.ll create mode 100644 test/Transforms/Reassociate/mixed-fast-nonfast-fp.ll create mode 100644 test/Transforms/Reassociate/negation1.ll create mode 100644 test/Transforms/Reassociate/pr21205.ll create mode 100644 test/Transforms/Reassociate/wrap-flags.ll create mode 100644 test/Transforms/SLPVectorizer/AArch64/commute.ll create mode 100644 test/Transforms/SLPVectorizer/AArch64/load-store-q.ll create mode 100644 test/Transforms/SLPVectorizer/AArch64/sdiv-pow2.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_binaryop.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_gep.ll create mode 100644 test/Transforms/SLPVectorizer/X86/crash_scheduling.ll create mode 100644 test/Transforms/SLPVectorizer/X86/extract_in_tree_user.ll create mode 100644 test/Transforms/SLPVectorizer/X86/powof2div.ll create mode 100644 test/Transforms/SLPVectorizer/X86/propagate_ir_flags.ll create mode 100644 test/Transforms/SLPVectorizer/X86/return.ll create mode 100644 test/Transforms/SLPVectorizer/X86/scheduling.ll create mode 100644 test/Transforms/SLPVectorizer/X86/unreachable.ll create mode 100644 test/Transforms/SROA/vector-lifetime-intrinsic.ll create mode 100644 test/Transforms/SampleProfile/Inputs/fnptr.binprof create mode 100644 test/Transforms/SampleProfile/Inputs/fnptr.prof create mode 100644 test/Transforms/SampleProfile/fnptr.ll create mode 100644 test/Transforms/SimplifyCFG/X86/switch-covered-bug.ll create mode 100644 test/Transforms/SimplifyCFG/assume.ll create mode 100644 test/Transforms/SimplifyCFG/branch-fold-threshold.ll create mode 100644 test/Transforms/SimplifyCFG/hoist-with-range.ll create mode 100644 test/Transforms/SimplifyCFG/switch-range-to-icmp.ll create mode 100644 test/Transforms/SimplifyCFG/switch-to-br.ll create mode 100644 test/Transforms/SimplifyCFG/switch-to-select-multiple-edge-per-block-phi.ll create mode 100644 test/Transforms/SimplifyCFG/switch-to-select-two-case.ll create mode 100644 test/Transforms/StructurizeCFG/one-loop-multiple-backedges.ll create mode 100644 test/Transforms/TailCallElim/EraseBB.ll create mode 100644 test/Transforms/Util/flattencfg.ll create mode 100644 test/Transforms/Util/lowerswitch.ll create mode 100644 test/Verifier/frameallocate.ll create mode 100644 test/Verifier/statepoint.ll create mode 100755 test/tools/dsymutil/Inputs/basic-archive.macho.x86_64 create mode 100755 test/tools/dsymutil/Inputs/basic-lto.macho.x86_64 create mode 100644 test/tools/dsymutil/Inputs/basic-lto.macho.x86_64.o create mode 100755 test/tools/dsymutil/Inputs/basic.macho.x86_64 create mode 100644 test/tools/dsymutil/Inputs/basic1.c create mode 100644 test/tools/dsymutil/Inputs/basic1.macho.x86_64.o create mode 100644 test/tools/dsymutil/Inputs/basic2.c create mode 100644 test/tools/dsymutil/Inputs/basic2.macho.x86_64.o create mode 100644 test/tools/dsymutil/Inputs/basic3.c create mode 100644 test/tools/dsymutil/Inputs/basic3.macho.x86_64.o create mode 100644 test/tools/dsymutil/Inputs/libbasic.a create mode 100644 test/tools/dsymutil/debug-map-parsing.test create mode 100644 test/tools/gold/Inputs/alias-1.ll create mode 100644 test/tools/gold/Inputs/bcsection.s create mode 100644 test/tools/gold/Inputs/comdat.ll create mode 100644 test/tools/gold/Inputs/common.ll create mode 100644 test/tools/gold/Inputs/invalid.bc create mode 100644 test/tools/gold/Inputs/linker-script.export create mode 100644 test/tools/gold/Inputs/linkonce-weak.ll create mode 100644 test/tools/gold/Inputs/pr19901-1.ll create mode 100644 test/tools/gold/Inputs/weak.ll create mode 100644 test/tools/gold/alias.ll create mode 100644 test/tools/gold/bad-alias.ll create mode 100644 test/tools/gold/bcsection.ll create mode 100644 test/tools/gold/coff.ll create mode 100644 test/tools/gold/comdat.ll create mode 100644 test/tools/gold/common.ll create mode 100644 test/tools/gold/emit-llvm.ll create mode 100644 test/tools/gold/invalid.ll create mode 100644 test/tools/gold/linker-script.ll create mode 100644 test/tools/gold/linkonce-weak.ll create mode 100644 test/tools/gold/lit.local.cfg create mode 100644 test/tools/gold/mtriple.ll create mode 100644 test/tools/gold/option.ll create mode 100644 test/tools/gold/pr19901.ll create mode 100644 test/tools/gold/slp-vectorize.ll create mode 100644 test/tools/gold/stats.ll create mode 100644 test/tools/gold/vectorize.ll create mode 100644 test/tools/gold/weak.ll create mode 100644 test/tools/llvm-cov/Inputs/highlightedRanges.covmapping create mode 100644 test/tools/llvm-cov/Inputs/highlightedRanges.profdata create mode 100644 test/tools/llvm-cov/Inputs/lineExecutionCounts.covmapping create mode 100644 test/tools/llvm-cov/Inputs/lineExecutionCounts.profdata create mode 100644 test/tools/llvm-cov/Inputs/regionMarkers.covmapping create mode 100644 test/tools/llvm-cov/Inputs/regionMarkers.profdata create mode 100644 test/tools/llvm-cov/Inputs/report.covmapping create mode 100644 test/tools/llvm-cov/Inputs/report.profdata create mode 100644 test/tools/llvm-cov/Inputs/showExpansions.covmapping create mode 100644 test/tools/llvm-cov/Inputs/showExpansions.profdata create mode 100644 test/tools/llvm-cov/Inputs/templateInstantiations.covmapping create mode 100644 test/tools/llvm-cov/Inputs/templateInstantiations.profdata create mode 100644 test/tools/llvm-cov/report.cpp create mode 100644 test/tools/llvm-cov/showExpansions.cpp create mode 100644 test/tools/llvm-cov/showHighlightedRanges.cpp create mode 100644 test/tools/llvm-cov/showLineExecutionCounts.cpp create mode 100644 test/tools/llvm-cov/showRegionMarkers.cpp create mode 100644 test/tools/llvm-cov/showTemplateInstantiations.cpp create mode 100644 test/tools/llvm-mc/line_end_with_space.test create mode 100755 test/tools/llvm-objdump/AArch64/Inputs/ObjC.exe.macho-aarch64 create mode 100644 test/tools/llvm-objdump/AArch64/Inputs/ObjC.obj.macho-aarch64 create mode 100755 test/tools/llvm-objdump/AArch64/Inputs/hello.exe.macho-aarch64 create mode 100644 test/tools/llvm-objdump/AArch64/Inputs/hello.obj.macho-aarch64 create mode 100644 test/tools/llvm-objdump/AArch64/lit.local.cfg create mode 100644 test/tools/llvm-objdump/AArch64/macho-private-headers.test create mode 100644 test/tools/llvm-objdump/AArch64/macho-symbolized-disassembly.test create mode 100755 test/tools/llvm-objdump/ARM/Inputs/hello.exe.macho-arm create mode 100644 test/tools/llvm-objdump/ARM/Inputs/hello.obj.macho-arm create mode 100644 test/tools/llvm-objdump/ARM/lit.local.cfg create mode 100644 test/tools/llvm-objdump/ARM/macho-arm-and-thumb.test create mode 100644 test/tools/llvm-objdump/ARM/macho-mattr-arm.test create mode 100644 test/tools/llvm-objdump/ARM/macho-mcpu-arm.test create mode 100644 test/tools/llvm-objdump/ARM/macho-private-headers.test create mode 100644 test/tools/llvm-objdump/ARM/macho-symbolized-disassembly.test create mode 100644 test/tools/llvm-objdump/ARM/macho-symbolized-subtractor.test create mode 100755 test/tools/llvm-objdump/Inputs/bad-ordinal.macho-x86_64 create mode 100755 test/tools/llvm-objdump/Inputs/bind.macho-x86_64 create mode 100755 test/tools/llvm-objdump/Inputs/bind2.macho-x86_64 create mode 100644 test/tools/llvm-objdump/Inputs/compact-unwind.macho-i386 create mode 100644 test/tools/llvm-objdump/Inputs/compact-unwind.macho-x86_64 create mode 100755 test/tools/llvm-objdump/Inputs/exports-trie.macho-x86_64 create mode 100755 test/tools/llvm-objdump/Inputs/lazy-bind.macho-x86_64 delete mode 100644 test/tools/llvm-objdump/Inputs/out-of-section-sym.elf-i386 create mode 100755 test/tools/llvm-objdump/Inputs/rebase.macho-x86_64 delete mode 100644 test/tools/llvm-objdump/Inputs/trivial.obj.elf-i386 create mode 100755 test/tools/llvm-objdump/Inputs/unwind-info-no-relocs.macho-x86_64 create mode 100755 test/tools/llvm-objdump/Inputs/unwind-info.macho-arm64 create mode 100755 test/tools/llvm-objdump/Inputs/unwind-info.macho-x86_64 create mode 100755 test/tools/llvm-objdump/Inputs/weak-bind.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/ObjC.exe.macho-x86_64 create mode 100644 test/tools/llvm-objdump/X86/Inputs/ObjC.obj.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibLoadKinds.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibRoutines.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubClient.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubFramework.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubLibrary.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/dylibSubUmbrella.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/exeThread.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/hello.exe.macho-i386 create mode 100755 test/tools/llvm-objdump/X86/Inputs/hello.exe.macho-x86_64 create mode 100644 test/tools/llvm-objdump/X86/Inputs/hello.obj.macho-i386 create mode 100644 test/tools/llvm-objdump/X86/Inputs/hello.obj.macho-x86_64 create mode 100755 test/tools/llvm-objdump/X86/Inputs/hello_cpp.exe.macho-x86_64 create mode 100644 test/tools/llvm-objdump/X86/Inputs/linkerOption.macho-x86_64 create mode 100644 test/tools/llvm-objdump/X86/Inputs/macho-universal-archive.x86_64.i386 create mode 100755 test/tools/llvm-objdump/X86/Inputs/macho-universal.x86_64.i386 create mode 100644 test/tools/llvm-objdump/X86/Inputs/out-of-section-sym.elf-i386 create mode 100644 test/tools/llvm-objdump/X86/Inputs/trivial.obj.elf-i386 create mode 100644 test/tools/llvm-objdump/X86/disassembly-show-raw.test create mode 100644 test/tools/llvm-objdump/X86/lit.local.cfg create mode 100644 test/tools/llvm-objdump/X86/macho-private-headers.test create mode 100644 test/tools/llvm-objdump/X86/macho-symbolized-disassembly.test create mode 100644 test/tools/llvm-objdump/X86/macho-symbolized-subtractor-i386.test create mode 100644 test/tools/llvm-objdump/X86/macho-symbolized-subtractor.test create mode 100644 test/tools/llvm-objdump/X86/macho-universal-x86_64.i386.test create mode 100644 test/tools/llvm-objdump/X86/out-of-section-sym.test delete mode 100644 test/tools/llvm-objdump/disassembly-show-raw.test delete mode 100644 test/tools/llvm-objdump/lit.local.cfg create mode 100644 test/tools/llvm-objdump/macho-bad-ordinal.test create mode 100644 test/tools/llvm-objdump/macho-bind.test create mode 100644 test/tools/llvm-objdump/macho-bind2.test create mode 100644 test/tools/llvm-objdump/macho-compact-unwind-i386.test create mode 100644 test/tools/llvm-objdump/macho-compact-unwind-x86_64.test create mode 100644 test/tools/llvm-objdump/macho-exports-trie.test create mode 100644 test/tools/llvm-objdump/macho-lazy-bind.test create mode 100644 test/tools/llvm-objdump/macho-rebase.test create mode 100644 test/tools/llvm-objdump/macho-unwind-info-arm64.test create mode 100644 test/tools/llvm-objdump/macho-unwind-info-no-relocs.test create mode 100644 test/tools/llvm-objdump/macho-unwind-info-x86_64.test create mode 100644 test/tools/llvm-objdump/macho-weak-bind.test delete mode 100644 test/tools/llvm-objdump/out-of-section-sym.test delete mode 100644 test/tools/llvm-profdata/Inputs/bad-hash.profdata create mode 100644 test/tools/llvm-profdata/Inputs/bad-hash.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/bar3-1.profdata create mode 100644 test/tools/llvm-profdata/Inputs/bar3-1.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/c-general.profdata create mode 100644 test/tools/llvm-profdata/Inputs/c-general.profraw create mode 100644 test/tools/llvm-profdata/Inputs/compat.profdata.v1 delete mode 100644 test/tools/llvm-profdata/Inputs/empty.profdata create mode 100644 test/tools/llvm-profdata/Inputs/empty.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/extra-word.profdata create mode 100644 test/tools/llvm-profdata/Inputs/extra-word.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/foo3-1.profdata create mode 100644 test/tools/llvm-profdata/Inputs/foo3-1.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/foo3-2.profdata create mode 100644 test/tools/llvm-profdata/Inputs/foo3-2.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/foo3bar3-1.profdata create mode 100644 test/tools/llvm-profdata/Inputs/foo3bar3-1.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/foo3bar3-2.profdata delete mode 100644 test/tools/llvm-profdata/Inputs/foo4-1.profdata delete mode 100644 test/tools/llvm-profdata/Inputs/foo4-2.profdata delete mode 100644 test/tools/llvm-profdata/Inputs/invalid-count-later.profdata create mode 100644 test/tools/llvm-profdata/Inputs/invalid-count-later.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/no-counts.profdata create mode 100644 test/tools/llvm-profdata/Inputs/no-counts.proftext delete mode 100644 test/tools/llvm-profdata/Inputs/overflow.profdata create mode 100644 test/tools/llvm-profdata/Inputs/sample-profile.proftext create mode 100644 test/tools/llvm-profdata/compat.proftext create mode 100644 test/tools/llvm-profdata/count-mismatch.proftext delete mode 100644 test/tools/llvm-profdata/errors.test create mode 100644 test/tools/llvm-profdata/general.proftext create mode 100644 test/tools/llvm-profdata/hash-mismatch.proftext create mode 100644 test/tools/llvm-profdata/lit.local.cfg create mode 100644 test/tools/llvm-profdata/multiple-inputs.test create mode 100644 test/tools/llvm-profdata/overflow.proftext create mode 100644 test/tools/llvm-profdata/sample-profile-basic.test delete mode 100644 test/tools/llvm-profdata/simple.test create mode 100644 test/tools/llvm-profdata/text-format-errors.test create mode 100644 test/tools/llvm-readobj/ARM/attribute-0.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-1.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-10.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-11.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-12.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-13.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-136.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-14.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-15.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-2.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-3.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-4.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-5.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-6.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-7.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-8.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-9.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-A.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-M.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-R.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-S.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-conformance-1.s create mode 100644 test/tools/llvm-readobj/ARM/attribute-conformance-2.s delete mode 100644 test/tools/llvm-readobj/ARM/attributes.s create mode 100644 test/tools/llvm-readobj/Inputs/bad-relocs.obj.coff-i386 create mode 100644 test/tools/llvm-readobj/Inputs/basereloc.obj.coff-i386 create mode 100644 test/tools/llvm-readobj/Inputs/bigobj.coff-x86-64 create mode 100755 test/tools/llvm-readobj/Inputs/comdat-function-linetables.obj.coff-2012-i386 create mode 100755 test/tools/llvm-readobj/Inputs/comdat-function-linetables.obj.coff-2013-i386 create mode 100644 test/tools/llvm-readobj/Inputs/directives.obj.coff-x86_64 create mode 100755 test/tools/llvm-readobj/Inputs/export-arm.dll create mode 100755 test/tools/llvm-readobj/Inputs/export-x64.dll create mode 100755 test/tools/llvm-readobj/Inputs/export-x86.dll create mode 100644 test/tools/llvm-readobj/Inputs/imports.exe.coff-i386 create mode 100644 test/tools/llvm-readobj/Inputs/imports.exe.coff-x86-64 create mode 100644 test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2013-i368 create mode 100644 test/tools/llvm-readobj/Inputs/multifile-linetables.obj.coff-2013-x86_64 create mode 100644 test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2013-i368 create mode 100644 test/tools/llvm-readobj/Inputs/multifunction-linetables.obj.coff-2013-x86_64 create mode 100644 test/tools/llvm-readobj/Inputs/relocs-no-symtab.obj.coff-i386 create mode 100644 test/tools/llvm-readobj/bigobj.test create mode 100644 test/tools/llvm-readobj/coff-basereloc.test create mode 100644 test/tools/llvm-readobj/coff-directives.test create mode 100644 test/tools/llvm-readobj/coff-exports.test create mode 100644 test/tools/llvm-readobj/imports.test create mode 100755 test/tools/llvm-symbolizer/Inputs/dsym-test-exe create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe-differentname.dSYM/Contents/Info.plist create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe-differentname.dSYM/Contents/Resources/DWARF/dsym-test-exe-second create mode 100755 test/tools/llvm-symbolizer/Inputs/dsym-test-exe-second create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe.dSYM/Contents/Info.plist create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test-exe.dSYM/Contents/Resources/DWARF/dsym-test-exe create mode 100644 test/tools/llvm-symbolizer/Inputs/dsym-test.c create mode 100755 test/tools/llvm-symbolizer/Inputs/ppc64 create mode 100644 test/tools/llvm-symbolizer/dsym.test create mode 100644 test/tools/llvm-symbolizer/ppc64.test create mode 100644 test/tools/llvm-vtabledump/Inputs/trivial.obj.coff-i386 create mode 100644 test/tools/llvm-vtabledump/Inputs/trivial.obj.elf-i386 create mode 100644 test/tools/llvm-vtabledump/trivial.test create mode 100644 tools/dsymutil/BinaryHolder.cpp create mode 100644 tools/dsymutil/BinaryHolder.h create mode 100644 tools/dsymutil/CMakeLists.txt create mode 100644 tools/dsymutil/DebugMap.cpp create mode 100644 tools/dsymutil/DebugMap.h create mode 100644 tools/dsymutil/DwarfLinker.cpp create mode 100644 tools/dsymutil/LLVMBuild.txt create mode 100644 tools/dsymutil/MachODebugMapParser.cpp create mode 100644 tools/dsymutil/Makefile create mode 100644 tools/dsymutil/dsymutil.cpp create mode 100644 tools/dsymutil/dsymutil.h create mode 100644 tools/llvm-ar/install_symlink.cmake create mode 100644 tools/llvm-cov/CodeCoverage.cpp create mode 100644 tools/llvm-cov/CoverageFilters.cpp create mode 100644 tools/llvm-cov/CoverageFilters.h create mode 100644 tools/llvm-cov/CoverageReport.cpp create mode 100644 tools/llvm-cov/CoverageReport.h create mode 100644 tools/llvm-cov/CoverageSummary.cpp create mode 100644 tools/llvm-cov/CoverageSummary.h create mode 100644 tools/llvm-cov/CoverageSummaryInfo.cpp create mode 100644 tools/llvm-cov/CoverageSummaryInfo.h create mode 100644 tools/llvm-cov/CoverageViewOptions.h create mode 100644 tools/llvm-cov/RenderingSupport.h create mode 100644 tools/llvm-cov/SourceCoverageView.cpp create mode 100644 tools/llvm-cov/SourceCoverageView.h create mode 100644 tools/llvm-cov/TestingSupport.cpp create mode 100644 tools/llvm-cov/gcov.cpp create mode 100644 tools/llvm-go/CMakeLists.txt create mode 100644 tools/llvm-go/Makefile create mode 100644 tools/llvm-go/llvm-go.go create mode 100644 tools/llvm-shlib/CMakeLists.txt create mode 100644 tools/llvm-shlib/libllvm.cpp create mode 100644 tools/llvm-vtabledump/CMakeLists.txt create mode 100644 tools/llvm-vtabledump/Error.cpp create mode 100644 tools/llvm-vtabledump/Error.h create mode 100644 tools/llvm-vtabledump/LLVMBuild.txt create mode 100644 tools/llvm-vtabledump/Makefile create mode 100644 tools/llvm-vtabledump/llvm-vtabledump.cpp create mode 100644 tools/llvm-vtabledump/llvm-vtabledump.h create mode 100644 tools/msbuild/toolset-vs2014.targets create mode 100644 tools/msbuild/toolset-vs2014_xp.targets create mode 100644 tools/verify-uselistorder/CMakeLists.txt create mode 100644 tools/verify-uselistorder/LLVMBuild.txt create mode 100644 tools/verify-uselistorder/Makefile create mode 100644 tools/verify-uselistorder/verify-uselistorder.cpp create mode 100644 unittests/ADT/FunctionRefTest.cpp create mode 100644 unittests/ADT/PostOrderIteratorTest.cpp create mode 100644 unittests/Analysis/CallGraphTest.cpp create mode 100644 unittests/Bitcode/BitstreamReaderTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/CMakeLists.txt delete mode 100644 unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h delete mode 100644 unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITTests.def delete mode 100644 unittests/ExecutionEngine/JIT/Makefile delete mode 100644 unittests/ExecutionEngine/JIT/MultiJITTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp create mode 100644 unittests/IR/DebugInfoTest.cpp delete mode 100644 unittests/IR/LeakDetectorTest.cpp create mode 100644 unittests/IR/UseTest.cpp create mode 100644 unittests/MC/Disassembler.cpp delete mode 100644 unittests/MC/MCAtomTest.cpp create mode 100644 unittests/Support/StreamingMemoryObject.cpp delete mode 100644 unittests/Transforms/DebugIR/CMakeLists.txt delete mode 100644 unittests/Transforms/DebugIR/DebugIR.cpp delete mode 100644 unittests/Transforms/DebugIR/Makefile create mode 100755 utils/bisect create mode 100644 utils/lit/tests/xunit-output.py create mode 100755 utils/shuffle_fuzz.py create mode 100755 utils/update_llc_test_checks.py diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..3186da4 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1 @@ +Checks: '-*,clang-diagnostic-*,llvm-*,misc-*' diff --git a/.gitignore b/.gitignore index eeebe0d..1f3f1a9 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,13 @@ #==============================================================================# # Explicit files to ignore (only matches one). #==============================================================================# +# Various tag programs +/tags +/TAGS +/GPATH +/GRTAGS +/GSYMS +/GTAGS .gitusers autom4te.cache cscope.files @@ -45,7 +52,15 @@ tools/clang tools/lldb # lld, which is tracked independently. tools/lld +# llgo, which is tracked independently. +tools/llgo # Polly, which is tracked independently. tools/polly # Sphinx build tree, if building in-source dir. docs/_build + +#==============================================================================# +# Files created in tree by the Go bindings. +#==============================================================================# +bindings/go/llvm/llvm_config.go +bindings/go/llvm/workdir diff --git a/CMakeLists.txt b/CMakeLists.txt index 728a4da..cfa32cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,29 @@ else() endif() endif() +if(CMAKE_VERSION VERSION_LESS 3.1.20141117) + set(cmake_3_2_USES_TERMINAL) +else() + set(cmake_3_2_USES_TERMINAL USES_TERMINAL) +endif() + project(LLVM) +# The following only works with the Ninja generator in CMake >= 3.0. +set(LLVM_PARALLEL_COMPILE_JOBS "" CACHE STRING + "Define the maximum number of concurrent compilation jobs.") +if(LLVM_PARALLEL_COMPILE_JOBS) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${LLVM_PARALLEL_COMPILE_JOBS}) + set(CMAKE_JOB_POOL_COMPILE compile_job_pool) +endif() + +set(LLVM_PARALLEL_LINK_JOBS "" CACHE STRING + "Define the maximum number of concurrent link jobs.") +if(LLVM_PARALLEL_LINK_JOBS) + set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${LLVM_PARALLEL_LINK_JOBS}) + set(CMAKE_JOB_POOL_LINK link_job_pool) +endif() + # Add path for custom modules set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} @@ -26,11 +47,11 @@ set(CMAKE_MODULE_PATH ) set(LLVM_VERSION_MAJOR 3) -set(LLVM_VERSION_MINOR 5) -set(LLVM_VERSION_PATCH 1) +set(LLVM_VERSION_MINOR 6) +set(LLVM_VERSION_PATCH 0) if (NOT PACKAGE_VERSION) - set(PACKAGE_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}svn") + set(PACKAGE_VERSION "${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}.${LLVM_VERSION_PATCH}") endif() option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF) @@ -111,9 +132,11 @@ endif() string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) +set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" ) + # They are used as destination of target generators. set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) -set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) +set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) if(WIN32 OR CYGWIN) # DLL platform -- put DLLs into bin. set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) @@ -130,7 +153,6 @@ set(LLVM_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} ) # --prefix set(LLVM_EXAMPLES_BINARY_DIR ${LLVM_BINARY_DIR}/examples) set(LLVM_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) -set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name (32/64)" ) set(LLVM_ALL_TARGETS AArch64 @@ -208,6 +230,7 @@ else() option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." ON) endif() +option(LLVM_ENABLE_MODULES "Compile with C++ modules enabled." OFF) option(LLVM_ENABLE_CXX1Y "Compile with C++1y enabled." OFF) option(LLVM_ENABLE_LIBCXX "Use libc++ if available." OFF) option(LLVM_ENABLE_PEDANTIC "Compile with pedantic enabled." ON) @@ -301,6 +324,12 @@ option (LLVM_ENABLE_SPHINX "Use Sphinx to generate llvm documentation." OFF) option (LLVM_BUILD_EXTERNAL_COMPILER_RT "Build compiler-rt as an external project." OFF) +option(LLVM_BUILD_LLVM_DYLIB "Build libllvm dynamic library" OFF) +option(LLVM_DISABLE_LLVM_DYLIB_ATEXIT "Disable llvm-shlib's atexit destructors." ON) +if(LLVM_DISABLE_LLVM_DYLIB_ATEXIT) + set(DISABLE_LLVM_DYLIB_ATEXIT 1) +endif() + # All options referred to from HandleLLVMOptions have to be specified # BEFORE this include, otherwise options will not be correctly set on # first cmake run @@ -315,7 +344,9 @@ set(TARGET_TRIPLE "${LLVM_DEFAULT_TARGET_TRIPLE}") include(HandleLLVMOptions) # Verify that we can find a Python 2 interpreter. Python 3 is unsupported. -set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5) +# FIXME: We should support systems with only Python 3, but that requires work +# on LLDB. +set(Python_ADDITIONAL_VERSIONS 2.7) include(FindPythonInterp) if( NOT PYTHONINTERP_FOUND ) message(FATAL_ERROR @@ -324,6 +355,10 @@ if( NOT PYTHONINTERP_FOUND ) Please install Python or specify the PYTHON_EXECUTABLE CMake variable.") endif() +if( ${PYTHON_VERSION_STRING} VERSION_LESS 2.7 ) + message(FATAL_ERROR "Python 2.7 or newer is required") +endif() + ###### # LLVMBuild Integration # @@ -449,8 +484,8 @@ configure_file( # They are not referenced. See set_output_directory(). set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/bin ) -set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) -set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib ) +set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX} ) +set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX} ) set(CMAKE_BUILD_WITH_INSTALL_RPATH ON) if (APPLE) @@ -458,17 +493,33 @@ if (APPLE) set(CMAKE_INSTALL_RPATH "@executable_path/../lib") else(UNIX) if(NOT DEFINED CMAKE_INSTALL_RPATH) - set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib") + set(CMAKE_INSTALL_RPATH "\$ORIGIN/../lib${LLVM_LIBDIR_SUFFIX}") if (${CMAKE_SYSTEM_NAME} MATCHES FreeBSD) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,origin") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,origin") endif() endif(NOT DEFINED CMAKE_INSTALL_RPATH) endif() +# Work around a broken bfd ld behavior. When linking a binary with a +# foo.so library, it will try to find any library that foo.so uses and +# check its symbols. This is wasteful (the check was done when foo.so +# was created) and can fail since it is not the dynamic linker and +# doesn't know how to handle search paths correctly. +if (UNIX AND NOT APPLE) + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -Wl,-allow-shlib-undefined") +endif() + set(CMAKE_INCLUDE_CURRENT_DIR ON) include_directories( ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR}) +# when crosscompiling import the executable targets from a file +if(CMAKE_CROSSCOMPILING) + include(CrossCompile) +endif(CMAKE_CROSSCOMPILING) + if( ${CMAKE_SYSTEM_NAME} MATCHES FreeBSD ) # On FreeBSD, /usr/local/* is not used by default. In order to build LLVM # with libxml2, iconv.h, etc., we must add /usr/local paths. @@ -521,6 +572,12 @@ if(LLVM_INCLUDE_TESTS) add_subdirectory(utils/unittest) endif() +foreach( binding ${LLVM_BINDINGS_LIST} ) + if( EXISTS "${LLVM_MAIN_SRC_DIR}/bindings/${binding}/CMakeLists.txt" ) + add_subdirectory(bindings/${binding}) + endif() +endforeach() + add_subdirectory(projects) if(WITH_POLLY) diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT index 86d401e..d35134f 100644 --- a/CODE_OWNERS.TXT +++ b/CODE_OWNERS.TXT @@ -6,7 +6,7 @@ what goes in or not. The list is sorted by surname and formatted to allow easy grepping and beautification by scripts. The fields are: name (N), email (E), web-address (W), PGP key ID and fingerprint (P), description (D), and snail-mail address -(S). +(S). Each entry should contain at least the (N), (E) and (D) fields. N: Joe Abbey E: jabbey@arxan.com @@ -20,6 +20,10 @@ N: Rafael Avila de Espindola E: rafael.espindola@gmail.com D: Gold plugin (tools/gold/*) +N: Justin Bogner +E: mail@justinbogner.com +D: InstrProfiling and related parts of ProfileData + N: Chandler Carruth E: chandlerc@gmail.com E: chandlerc@google.com @@ -29,43 +33,50 @@ N: Evan Cheng E: evan.cheng@apple.com D: ARM target, parts of code generator not covered by someone else -N: Renato Golin -E: renato.golin@linaro.org -D: ARM Linux support - N: Eric Christopher E: echristo@gmail.com D: Debug Information, autotools/configure/make build, inline assembly N: Greg Clayton +E: gclayton@apple.com D: LLDB +N: Marshall Clow +E: mclow.lists@gmail.com +D: libc++ + N: Peter Collingbourne -D: libclc +E: peter@pcc.me.uk +D: llgo N: Anshuman Dasgupta E: adasgupt@codeaurora.org D: Hexagon Backend +N: Duncan P. N. Exon Smith +E: dexonsmith@apple.com +D: Branch weights and BlockFrequencyInfo + N: Hal Finkel E: hfinkel@anl.gov -D: BBVectorize, the loop reroller and the PowerPC target +D: BBVectorize, the loop reroller, alias analysis and the PowerPC target + +N: Renato Golin +E: renato.golin@linaro.org +D: ARM Linux support N: Venkatraman Govindaraju E: venkatra@cs.wisc.edu D: Sparc Backend (lib/Target/Sparc/*) N: Tobias Grosser +E: tobias@grosser.es D: Polly N: James Grosbach E: grosbach@apple.com D: MC layer -N: Marshall Clow -E: mclow.lists@gmail.com -D: libc++ - N: Justin Holewinski E: jholewinski@nvidia.com D: NVPTX Target (lib/Target/NVPTX/*) @@ -99,7 +110,12 @@ N: Tim Northover E: t.p.northover@gmail.com D: AArch64 backend +N: Diego Novillo +E: dnovillo@google.com +D: SampleProfile and related parts of ProfileData + N: Jakob Olesen +E: stoklund@2pi.dk D: Register allocators and TableGen N: Richard Osborne @@ -118,10 +134,6 @@ N: Daniel Sanders E: daniel.sanders@imgtec.com D: MIPS Backend (lib/Target/Mips/*) -N: Richard Sandiford -E: rsandifo@linux.vnet.ibm.com -D: SystemZ Backend - N: Duncan Sands E: baldrick@free.fr D: DragonEgg @@ -137,7 +149,7 @@ D: Windows parts of Support, Object, ar, nm, objdump, ranlib, size N: Tom Stellard E: thomas.stellard@amd.com E: mesa-dev@lists.freedesktop.org -D: R600 Backend +D: Release manager for the 3.5 branch, R600 Backend, libclc N: Evgeniy Stepanov E: eugenis@google.com @@ -147,6 +159,10 @@ N: Andrew Trick E: atrick@apple.com D: IndVar Simplify, Loop Strength Reduction, Instruction Scheduling +N: Ulrich Weigand +E: uweigand@de.ibm.com +D: SystemZ Backend + N: Bill Wendling E: isanbard@gmail.com D: libLTO, IR Linker diff --git a/CREDITS.TXT b/CREDITS.TXT index 0447c40..40d67f4 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -119,6 +119,10 @@ N: Hal Finkel E: hfinkel@anl.gov D: Basic-block autovectorization, PowerPC backend improvements +N: Eric Fiselier +E: eric@efcs.ca +D: LIT patches and documentation. + N: Ryan Flynn E: pizza@parseerror.com D: Miscellaneous bug fixes @@ -281,8 +285,11 @@ D: Backend for Qualcomm's Hexagon VLIW processor. N: Bruno Cardoso Lopes E: bruno.cardoso@gmail.com -W: http://www.brunocardoso.org -D: The Mips backend +I: bruno +W: http://brunocardoso.cc +D: Mips backend +D: Random ARM integrated assembler and assembly parser improvements +D: General X86 AVX1 support N: Duraid Madina E: duraid@octopus.com.au @@ -456,3 +463,4 @@ D: Bunches of stuff N: Bob Wilson E: bob.wilson@acm.org D: Advanced SIMD (NEON) support in the ARM backend. + diff --git a/Makefile.config.in b/Makefile.config.in index b98ebc6..d34a2d5 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -202,10 +202,8 @@ DOT := @DOT@ DOXYGEN := @DOXYGEN@ GROFF := @GROFF@ GZIPBIN := @GZIPBIN@ -OCAMLC := @OCAMLC@ -OCAMLOPT := @OCAMLOPT@ -OCAMLDEP := @OCAMLDEP@ -OCAMLDOC := @OCAMLDOC@ +GO := @GO@ +OCAMLFIND := @OCAMLFIND@ GAS := @GAS@ POD2HTML := @POD2HTML@ POD2MAN := @POD2MAN@ @@ -217,6 +215,9 @@ HAVE_DLOPEN := @HAVE_DLOPEN@ HAVE_PTHREAD := @HAVE_PTHREAD@ HAVE_TERMINFO := @HAVE_TERMINFO@ +HAVE_OCAMLOPT := @HAVE_OCAMLOPT@ +HAVE_OCAML_OUNIT := @HAVE_OCAML_OUNIT@ + LIBS := @LIBS@ # Targets that are possible to build @@ -370,7 +371,6 @@ HUGE_VAL_SANITY = @HUGE_VAL_SANITY@ # Bindings that we should build BINDINGS_TO_BUILD := @BINDINGS_TO_BUILD@ -ALL_BINDINGS := @ALL_BINDINGS@ OCAML_LIBDIR := @OCAML_LIBDIR@ # When compiling under Mingw/Cygwin, executables such as tblgen @@ -396,6 +396,8 @@ COVERED_SWITCH_DEFAULT = @COVERED_SWITCH_DEFAULT@ NO_UNINITIALIZED = @NO_UNINITIALIZED@ # -Wno-maybe-uninitialized NO_MAYBE_UNINITIALIZED = @NO_MAYBE_UNINITIALIZED@ +# -Wno-comment +NO_COMMENT = @NO_COMMENT@ # Was polly found in tools/polly? LLVM_HAS_POLLY = @LLVM_HAS_POLLY@ diff --git a/Makefile.rules b/Makefile.rules index ebebc0a..c8c971f 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -449,7 +449,6 @@ ifeq ($(HOST_OS),MingW) endif endif -CXX.Flags += -Woverloaded-virtual CPP.BaseFlags += $(CPP.Defines) AR.Flags := cru @@ -680,7 +679,7 @@ endif CompileCommonOpts += -Wall -W -Wno-unused-parameter -Wwrite-strings \ $(EXTRA_OPTIONS) $(COVERED_SWITCH_DEFAULT) \ $(NO_UNINITIALIZED) $(NO_MAYBE_UNINITIALIZED) \ - $(NO_MISSING_FIELD_INITIALIZERS) + $(NO_MISSING_FIELD_INITIALIZERS) $(NO_COMMENT) # Enable cast-qual for C++; the workaround is to use const_cast. CXX.Flags += -Wcast-qual @@ -727,10 +726,6 @@ ifeq ($(HOST_OS),SunOS) CPP.BaseFlags += -include llvm/Support/Solaris.h endif -ifeq ($(HOST_OS),AuroraUX) -CPP.BaseFlags += -include llvm/Support/Solaris.h -endif # !HOST_OS - AuroraUX. - # On Windows, SharedLibDir != LibDir. The order is important. ifeq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) LD.Flags += -L$(SharedLibDir) -L$(LibDir) -L$(LLVMToolDir) -L$(LLVMLibDir) @@ -1673,18 +1668,13 @@ $(ObjDir)/%GenAsmMatcher.inc.tmp : %.td $(ObjDir)/.dir $(LLVM_TBLGEN) $(TARGET:%=$(ObjDir)/%GenMCCodeEmitter.inc.tmp): \ $(ObjDir)/%GenMCCodeEmitter.inc.tmp: %.td $(ObjDir)/.dir $(LLVM_TBLGEN) $(Echo) "Building $(= 2.5]) +AC_MSG_CHECKING([for python >= 2.7]) ac_python_version=`$PYTHON -V 2>&1 | cut -d' ' -f2` ac_python_version_major=`echo $ac_python_version | cut -d'.' -f1` ac_python_version_minor=`echo $ac_python_version | cut -d'.' -f2` ac_python_version_patch=`echo $ac_python_version | cut -d'.' -f3` if test "$ac_python_version_major" -gt "2" || \ (test "$ac_python_version_major" -eq "2" && \ - test "$ac_python_version_minor" -ge "5") ; then + test "$ac_python_version_minor" -ge "7") ; then AC_MSG_RESULT([$PYTHON ($ac_python_version)]) else AC_MSG_RESULT([not found]) - AC_MSG_FAILURE([found python $ac_python_version ($PYTHON); required >= 2.5]) + AC_MSG_FAILURE([found python $ac_python_version ($PYTHON); required >= 2.7]) fi dnl===-----------------------------------------------------------------------=== @@ -1530,7 +1542,7 @@ AC_ARG_WITH(oprofile, fi ;; *) AC_MSG_ERROR([OProfile support is available on Linux only.]) ;; - esac + esac ], [ AC_SUBST(USE_OPROFILE, [0]) @@ -1598,8 +1610,12 @@ AC_HEADER_SYS_WAIT AC_HEADER_TIME AC_LANG_PUSH([C++]) -AC_CHECK_HEADERS([cxxabi.h]) +dnl size_t must be defined before including cxxabi.h on FreeBSD 10.0. +AC_CHECK_HEADERS([cxxabi.h], [], [], +[#include +]) AC_LANG_POP([C++]) + AC_CHECK_HEADERS([dlfcn.h execinfo.h fcntl.h inttypes.h link.h]) AC_CHECK_HEADERS([malloc.h setjmp.h signal.h stdint.h termios.h unistd.h]) AC_CHECK_HEADERS([utime.h]) @@ -1871,37 +1887,52 @@ AC_DEFINE_UNQUOTED(LLVM_DEFAULT_TARGET_TRIPLE, "$target", dnl Determine which bindings to build. if test "$BINDINGS_TO_BUILD" = auto ; then BINDINGS_TO_BUILD="" - if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + if test "x$OCAMLFIND" != x ; then BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" fi + if test "x$GO" != x ; then + if $GO run ${srcdir}/bindings/go/conftest.go ; then + BINDINGS_TO_BUILD="go $BINDINGS_TO_BUILD" + fi + fi fi AC_SUBST(BINDINGS_TO_BUILD,$BINDINGS_TO_BUILD) -dnl This isn't really configurey, but it avoids having to repeat the list in -dnl other files. -AC_SUBST(ALL_BINDINGS,ocaml) - dnl Do any work necessary to ensure that bindings have what they need. binding_prereqs_failed=0 for a_binding in $BINDINGS_TO_BUILD ; do case "$a_binding" in ocaml) - if test "x$OCAMLC" = x ; then - AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc]) + if test "x$OCAMLFIND" = x ; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlfind not found. Try configure OCAMLFIND=/path/to/ocamlfind]) binding_prereqs_failed=1 fi - if test "x$OCAMLDEP" = x ; then - AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep]) + + if $OCAMLFIND opt -version >/dev/null 2>/dev/null ; then + HAVE_OCAMLOPT=1 + else + HAVE_OCAMLOPT=0 + fi + AC_SUBST(HAVE_OCAMLOPT) + + if ! $OCAMLFIND query ctypes >/dev/null 2>/dev/null; then + AC_MSG_WARN([--enable-bindings=ocaml specified, but ctypes is not installed]) binding_prereqs_failed=1 fi - if test "x$OCAMLOPT" = x ; then - AC_MSG_WARN([--enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt]) - dnl ocamlopt is optional! + + if $OCAMLFIND query oUnit >/dev/null 2>/dev/null; then + HAVE_OCAML_OUNIT=1 + else + HAVE_OCAML_OUNIT=0 + AC_MSG_WARN([--enable-bindings=ocaml specified, but OUnit 2 is not installed. Tests will not run]) + dnl oUnit is optional! fi + AC_SUBST(HAVE_OCAML_OUNIT) + if test "x$with_ocaml_libdir" != xauto ; then AC_SUBST(OCAML_LIBDIR,$with_ocaml_libdir) else - ocaml_stdlib="`"$OCAMLC" -where`" + ocaml_stdlib="`"$OCAMLFIND" ocamlc -where`" if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" then # ocaml stdlib is beneath our prefix; use stdlib @@ -1912,6 +1943,19 @@ for a_binding in $BINDINGS_TO_BUILD ; do fi fi ;; + go) + if test "x$GO" = x ; then + AC_MSG_WARN([--enable-bindings=go specified, but go not found. Try configure GO=/path/to/go]) + binding_prereqs_failed=1 + else + if $GO run ${srcdir}/bindings/go/conftest.go ; then + : + else + AC_MSG_WARN([--enable-bindings=go specified, but need at least Go 1.2. Try configure GO=/path/to/go]) + binding_prereqs_failed=1 + fi + fi + ;; esac done if test "$binding_prereqs_failed" = 1 ; then @@ -1973,6 +2017,11 @@ if test "${clang_src_root}" = ""; then clang_src_root="$srcdir/tools/clang" fi if test -f ${clang_src_root}/README.txt; then + dnl Clang supports build systems which use the multilib libdir suffix. + dnl The autoconf system doesn't support this so stub out that variable. + AC_DEFINE_UNQUOTED(CLANG_LIBDIR_SUFFIX,"", + [Multilib suffix for libdir.]) + dnl Use variables to stay under 80 columns. configh="include/clang/Config/config.h" doxy="docs/doxygen.cfg" diff --git a/bindings/Makefile b/bindings/Makefile index c545b28..70e9e6c 100644 --- a/bindings/Makefile +++ b/bindings/Makefile @@ -11,6 +11,10 @@ LEVEL := .. include $(LEVEL)/Makefile.config -PARALLEL_DIRS = $(BINDINGS_TO_BUILD) +PARALLEL_DIRS = + +ifneq (,$(filter ocaml,$(BINDINGS_TO_BUILD))) +PARALLEL_DIRS += ocaml +endif include $(LEVEL)/Makefile.common diff --git a/bindings/go/README.txt b/bindings/go/README.txt new file mode 100644 index 0000000..2fc4afa --- /dev/null +++ b/bindings/go/README.txt @@ -0,0 +1,53 @@ +This directory contains LLVM bindings for the Go programming language +(http://golang.org). + +Prerequisites +------------- + +* Go 1.2+. +* CMake (to build LLVM). + +Using the bindings +------------------ + +The package path "llvm.org/llvm/bindings/go/llvm" can be used to +import the latest development version of LLVM from SVN. Paths such as +"llvm.org/llvm.v36/bindings/go/llvm" refer to released versions of LLVM. + +It is recommended to use the "-d" flag with "go get" to download the +package or a dependency, as an additional step is required to build LLVM +(see "Building LLVM" below). + +Building LLVM +------------- + +The script "build.sh" in this directory can be used to build LLVM and prepare +it to be used by the bindings. If you receive an error message from "go build" +like this: + + ./analysis.go:4:84: fatal error: llvm-c/Analysis.h: No such file or directory + #include // If you are getting an error here read bindings/go/README.txt + +or like this: + + ./llvm_dep.go:5: undefined: run_build_sh + +it means that LLVM needs to be built or updated by running the script. + + $ $GOPATH/src/llvm.org/llvm/bindings/go/build.sh + +Any command line arguments supplied to the script are passed to LLVM's CMake +build system. A good set of arguments to use during development are: + + $ $GOPATH/src/llvm.org/llvm/bindings/go/build.sh -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD=host -DBUILD_SHARED_LIBS=ON + +Note that CMake keeps a cache of build settings so once you have built +LLVM there is no need to pass these arguments again after updating. + +Alternatively, you can build LLVM yourself, but you must then set the +CGO_CPPFLAGS, CGO_CXXFLAGS and CGO_LDFLAGS environment variables: + + $ export CGO_CPPFLAGS="`/path/to/llvm-build/bin/llvm-config --cppflags`" + $ export CGO_CXXFLAGS=-std=c++11 + $ export CGO_LDFLAGS="`/path/to/llvm-build/bin/llvm-config --ldflags --libs --system-libs all`" + $ go build -tags byollvm diff --git a/bindings/go/build.sh b/bindings/go/build.sh new file mode 100755 index 0000000..3177852 --- /dev/null +++ b/bindings/go/build.sh @@ -0,0 +1,28 @@ +#!/bin/sh -xe + +gollvmdir=$(dirname "$0")/llvm + +workdir=$gollvmdir/workdir +llvmdir=$gollvmdir/../../.. +llvm_builddir=$workdir/llvm_build + +mkdir -p $llvm_builddir + +cmake_flags="../../../../.. $@" +llvm_config="$llvm_builddir/bin/llvm-config" +llvm_go="$llvm_builddir/bin/llvm-go" + +if test -n "`which ninja`" ; then + # If Ninja is available, we can speed up the build by building only the + # required subset of LLVM. + (cd $llvm_builddir && cmake -G Ninja $cmake_flags) + ninja -C $llvm_builddir llvm-config llvm-go + llvm_components="$($llvm_go print-components)" + llvm_buildtargets="$($llvm_config --libs $llvm_components | sed -e 's/-l//g')" + ninja -C $llvm_builddir $llvm_buildtargets FileCheck +else + (cd $llvm_builddir && cmake $cmake_flags) + make -C $llvm_builddir -j4 +fi + +$llvm_go print-config > $gollvmdir/llvm_config.go diff --git a/bindings/go/conftest.go b/bindings/go/conftest.go new file mode 100644 index 0000000..d97fb89 --- /dev/null +++ b/bindings/go/conftest.go @@ -0,0 +1,16 @@ +package main + +import ( + "go/build" + "os" +) + +// Tests that the Go compiler is at least version 1.2. +func main() { + for _, tag := range build.Default.ReleaseTags { + if tag == "go1.2" { + os.Exit(0) + } + } + os.Exit(1) +} diff --git a/bindings/go/llvm/DIBuilderBindings.cpp b/bindings/go/llvm/DIBuilderBindings.cpp new file mode 100644 index 0000000..5671866 --- /dev/null +++ b/bindings/go/llvm/DIBuilderBindings.cpp @@ -0,0 +1,242 @@ +//===- DIBuilderBindings.cpp - Bindings for DIBuilder ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the DIBuilder class. +// +//===----------------------------------------------------------------------===// + +#include "DIBuilderBindings.h" + +#include "IRBindings.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/DIBuilder.h" + +using namespace llvm; + +DEFINE_SIMPLE_CONVERSION_FUNCTIONS(DIBuilder, LLVMDIBuilderRef) + +namespace { +template T unwrapDI(LLVMMetadataRef v) { + return v ? T(unwrap(v)) : T(); +} +} + +LLVMDIBuilderRef LLVMNewDIBuilder(LLVMModuleRef mref) { + Module *m = unwrap(mref); + return wrap(new DIBuilder(*m)); +} + +void LLVMDIBuilderDestroy(LLVMDIBuilderRef dref) { + DIBuilder *d = unwrap(dref); + delete d; +} + +void LLVMDIBuilderFinalize(LLVMDIBuilderRef dref) { unwrap(dref)->finalize(); } + +LLVMMetadataRef LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef Dref, + unsigned Lang, const char *File, + const char *Dir, + const char *Producer, + int Optimized, const char *Flags, + unsigned RuntimeVersion) { + DIBuilder *D = unwrap(Dref); + DICompileUnit CU = D->createCompileUnit(Lang, File, Dir, Producer, Optimized, + Flags, RuntimeVersion); + return wrap(CU); +} + +LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Dref, const char *File, + const char *Dir) { + DIBuilder *D = unwrap(Dref); + DIFile F = D->createFile(File, Dir); + return wrap(F); +} + +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef Dref, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Line, + unsigned Column) { + DIBuilder *D = unwrap(Dref); + DILexicalBlock LB = D->createLexicalBlock( + unwrapDI(Scope), unwrapDI(File), Line, Column); + return wrap(LB); +} + +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef Dref, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Discriminator) { + DIBuilder *D = unwrap(Dref); + DILexicalBlockFile LBF = D->createLexicalBlockFile( + unwrapDI(Scope), unwrapDI(File), Discriminator); + return wrap(LBF); +} + +LLVMMetadataRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef Dref, LLVMMetadataRef Scope, const char *Name, + const char *LinkageName, LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef CompositeType, int IsLocalToUnit, int IsDefinition, + unsigned ScopeLine, unsigned Flags, int IsOptimized, LLVMValueRef Func) { + DIBuilder *D = unwrap(Dref); + DISubprogram SP = D->createFunction( + unwrapDI(Scope), Name, LinkageName, unwrapDI(File), + Line, unwrapDI(CompositeType), IsLocalToUnit, + IsDefinition, ScopeLine, Flags, IsOptimized, unwrap(Func)); + return wrap(SP); +} + +LLVMMetadataRef LLVMDIBuilderCreateLocalVariable( + LLVMDIBuilderRef Dref, unsigned Tag, LLVMMetadataRef Scope, + const char *Name, LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty, + int AlwaysPreserve, unsigned Flags, unsigned ArgNo) { + DIBuilder *D = unwrap(Dref); + DIVariable V = D->createLocalVariable( + Tag, unwrapDI(Scope), Name, unwrapDI(File), Line, + unwrapDI(Ty), AlwaysPreserve, Flags, ArgNo); + return wrap(V); +} + +LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref, + const char *Name, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding) { + DIBuilder *D = unwrap(Dref); + DIBasicType T = D->createBasicType(Name, SizeInBits, AlignInBits, Encoding); + return wrap(T); +} + +LLVMMetadataRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef Dref, + LLVMMetadataRef PointeeType, + uint64_t SizeInBits, + uint64_t AlignInBits, + const char *Name) { + DIBuilder *D = unwrap(Dref); + DIDerivedType T = D->createPointerType(unwrapDI(PointeeType), + SizeInBits, AlignInBits, Name); + return wrap(T); +} + +LLVMMetadataRef +LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef Dref, LLVMMetadataRef File, + LLVMMetadataRef ParameterTypes) { + DIBuilder *D = unwrap(Dref); + DICompositeType CT = D->createSubroutineType( + unwrapDI(File), unwrapDI(ParameterTypes)); + return wrap(CT); +} + +LLVMMetadataRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef Dref, LLVMMetadataRef Scope, const char *Name, + LLVMMetadataRef File, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef DerivedFrom, + LLVMMetadataRef ElementTypes) { + DIBuilder *D = unwrap(Dref); + DICompositeType CT = D->createStructType( + unwrapDI(Scope), Name, unwrapDI(File), Line, + SizeInBits, AlignInBits, Flags, unwrapDI(DerivedFrom), + unwrapDI(ElementTypes)); + return wrap(CT); +} + +LLVMMetadataRef +LLVMDIBuilderCreateMemberType(LLVMDIBuilderRef Dref, LLVMMetadataRef Scope, + const char *Name, LLVMMetadataRef File, + unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, LLVMMetadataRef Ty) { + DIBuilder *D = unwrap(Dref); + DIDerivedType DT = D->createMemberType( + unwrapDI(Scope), Name, unwrapDI(File), Line, + SizeInBits, AlignInBits, OffsetInBits, Flags, unwrapDI(Ty)); + return wrap(DT); +} + +LLVMMetadataRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef Dref, + uint64_t SizeInBits, + uint64_t AlignInBits, + LLVMMetadataRef ElementType, + LLVMMetadataRef Subscripts) { + DIBuilder *D = unwrap(Dref); + DICompositeType CT = + D->createArrayType(SizeInBits, AlignInBits, unwrapDI(ElementType), + unwrapDI(Subscripts)); + return wrap(CT); +} + +LLVMMetadataRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef Dref, + LLVMMetadataRef Ty, const char *Name, + LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef Context) { + DIBuilder *D = unwrap(Dref); + DIDerivedType DT = + D->createTypedef(unwrapDI(Ty), Name, unwrapDI(File), Line, + unwrapDI(Context)); + return wrap(DT); +} + +LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef Dref, + int64_t Lo, int64_t Count) { + DIBuilder *D = unwrap(Dref); + DISubrange S = D->getOrCreateSubrange(Lo, Count); + return wrap(S); +} + +LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef Dref, + LLVMMetadataRef *Data, + size_t Length) { + DIBuilder *D = unwrap(Dref); + Metadata **DataValue = unwrap(Data); + ArrayRef Elements(DataValue, Length); + DIArray A = D->getOrCreateArray(Elements); + return wrap(A); +} + +LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef Dref, + LLVMMetadataRef *Data, + size_t Length) { + DIBuilder *D = unwrap(Dref); + Metadata **DataValue = unwrap(Data); + ArrayRef Elements(DataValue, Length); + DITypeArray A = D->getOrCreateTypeArray(Elements); + return wrap(A); +} + +LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, + int64_t *Addr, size_t Length) { + DIBuilder *D = unwrap(Dref); + DIExpression Expr = D->createExpression(ArrayRef(Addr, Length)); + return wrap(Expr); +} + +LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef Dref, + LLVMValueRef Storage, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMBasicBlockRef Block) { + DIBuilder *D = unwrap(Dref); + Instruction *Instr = + D->insertDeclare(unwrap(Storage), unwrapDI(VarInfo), + unwrapDI(Expr), unwrap(Block)); + return wrap(Instr); +} + +LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef Dref, + LLVMValueRef Val, uint64_t Offset, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMBasicBlockRef Block) { + DIBuilder *D = unwrap(Dref); + Instruction *Instr = D->insertDbgValueIntrinsic( + unwrap(Val), Offset, unwrapDI(VarInfo), + unwrapDI(Expr), unwrap(Block)); + return wrap(Instr); +} diff --git a/bindings/go/llvm/DIBuilderBindings.h b/bindings/go/llvm/DIBuilderBindings.h new file mode 100644 index 0000000..8a8ce3f --- /dev/null +++ b/bindings/go/llvm/DIBuilderBindings.h @@ -0,0 +1,135 @@ +//===- DIBuilderBindings.h - Bindings for DIBuilder -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the DIBuilder class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_DIBUILDERBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_DIBUILDERBINDINGS_H + +#include "llvm-c/Core.h" +#include "IRBindings.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// FIXME: These bindings shouldn't be Go-specific and should eventually move to +// a (somewhat) less stable collection of C APIs for use in creating bindings of +// LLVM in other languages. + +typedef struct LLVMOpaqueDIBuilder *LLVMDIBuilderRef; + +LLVMDIBuilderRef LLVMNewDIBuilder(LLVMModuleRef m); + +void LLVMDIBuilderDestroy(LLVMDIBuilderRef d); +void LLVMDIBuilderFinalize(LLVMDIBuilderRef d); + +LLVMMetadataRef +LLVMDIBuilderCreateCompileUnit(LLVMDIBuilderRef D, unsigned Language, + const char *File, const char *Dir, + const char *Producer, int Optimized, + const char *Flags, unsigned RuntimeVersion); + +LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef D, const char *File, + const char *Dir); + +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlock(LLVMDIBuilderRef D, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Line, unsigned Column); + +LLVMMetadataRef LLVMDIBuilderCreateLexicalBlockFile(LLVMDIBuilderRef D, + LLVMMetadataRef Scope, + LLVMMetadataRef File, + unsigned Discriminator); + +LLVMMetadataRef LLVMDIBuilderCreateFunction( + LLVMDIBuilderRef D, LLVMMetadataRef Scope, const char *Name, + const char *LinkageName, LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef CompositeType, int IsLocalToUnit, int IsDefinition, + unsigned ScopeLine, unsigned Flags, int IsOptimized, LLVMValueRef Function); + +LLVMMetadataRef LLVMDIBuilderCreateLocalVariable( + LLVMDIBuilderRef D, unsigned Tag, LLVMMetadataRef Scope, const char *Name, + LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty, int AlwaysPreserve, + unsigned Flags, unsigned ArgNo); + +LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef D, + const char *Name, + uint64_t SizeInBits, + uint64_t AlignInBits, + unsigned Encoding); + +LLVMMetadataRef LLVMDIBuilderCreatePointerType(LLVMDIBuilderRef D, + LLVMMetadataRef PointeeType, + uint64_t SizeInBits, + uint64_t AlignInBits, + const char *Name); + +LLVMMetadataRef +LLVMDIBuilderCreateSubroutineType(LLVMDIBuilderRef D, LLVMMetadataRef File, + LLVMMetadataRef ParameterTypes); + +LLVMMetadataRef LLVMDIBuilderCreateStructType( + LLVMDIBuilderRef D, LLVMMetadataRef Scope, const char *Name, + LLVMMetadataRef File, unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Flags, LLVMMetadataRef DerivedFrom, + LLVMMetadataRef ElementTypes); + +LLVMMetadataRef +LLVMDIBuilderCreateMemberType(LLVMDIBuilderRef D, LLVMMetadataRef Scope, + const char *Name, LLVMMetadataRef File, + unsigned Line, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, LLVMMetadataRef Ty); + +LLVMMetadataRef LLVMDIBuilderCreateArrayType(LLVMDIBuilderRef D, + uint64_t SizeInBits, + uint64_t AlignInBits, + LLVMMetadataRef ElementType, + LLVMMetadataRef Subscripts); + +LLVMMetadataRef LLVMDIBuilderCreateTypedef(LLVMDIBuilderRef D, + LLVMMetadataRef Ty, const char *Name, + LLVMMetadataRef File, unsigned Line, + LLVMMetadataRef Context); + +LLVMMetadataRef LLVMDIBuilderGetOrCreateSubrange(LLVMDIBuilderRef D, int64_t Lo, + int64_t Count); + +LLVMMetadataRef LLVMDIBuilderGetOrCreateArray(LLVMDIBuilderRef D, + LLVMMetadataRef *Data, + size_t Length); + +LLVMMetadataRef LLVMDIBuilderGetOrCreateTypeArray(LLVMDIBuilderRef D, + LLVMMetadataRef *Data, + size_t Length); + +LLVMMetadataRef LLVMDIBuilderCreateExpression(LLVMDIBuilderRef Dref, + int64_t *Addr, size_t Length); + +LLVMValueRef LLVMDIBuilderInsertDeclareAtEnd(LLVMDIBuilderRef D, + LLVMValueRef Storage, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMBasicBlockRef Block); + +LLVMValueRef LLVMDIBuilderInsertValueAtEnd(LLVMDIBuilderRef D, LLVMValueRef Val, + uint64_t Offset, + LLVMMetadataRef VarInfo, + LLVMMetadataRef Expr, + LLVMBasicBlockRef Block); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/bindings/go/llvm/IRBindings.cpp b/bindings/go/llvm/IRBindings.cpp new file mode 100644 index 0000000..fac4126 --- /dev/null +++ b/bindings/go/llvm/IRBindings.cpp @@ -0,0 +1,100 @@ +//===- IRBindings.cpp - Additional bindings for ir ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the ir component. +// +//===----------------------------------------------------------------------===// + +#include "IRBindings.h" + +#include "llvm/IR/Attributes.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" + +using namespace llvm; + +void LLVMAddFunctionAttr2(LLVMValueRef Fn, uint64_t PA) { + Function *Func = unwrap(Fn); + const AttributeSet PAL = Func->getAttributes(); + AttrBuilder B(PA); + const AttributeSet PALnew = + PAL.addAttributes(Func->getContext(), AttributeSet::FunctionIndex, + AttributeSet::get(Func->getContext(), + AttributeSet::FunctionIndex, B)); + Func->setAttributes(PALnew); +} + +uint64_t LLVMGetFunctionAttr2(LLVMValueRef Fn) { + Function *Func = unwrap(Fn); + const AttributeSet PAL = Func->getAttributes(); + return PAL.Raw(AttributeSet::FunctionIndex); +} + +void LLVMRemoveFunctionAttr2(LLVMValueRef Fn, uint64_t PA) { + Function *Func = unwrap(Fn); + const AttributeSet PAL = Func->getAttributes(); + AttrBuilder B(PA); + const AttributeSet PALnew = + PAL.removeAttributes(Func->getContext(), AttributeSet::FunctionIndex, + AttributeSet::get(Func->getContext(), + AttributeSet::FunctionIndex, B)); + Func->setAttributes(PALnew); +} + +LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef C) { + return wrap(ConstantAsMetadata::get(unwrap(C))); +} + +LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen) { + return wrap(MDString::get(*unwrap(C), StringRef(Str, SLen))); +} + +LLVMMetadataRef LLVMMDNode2(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count) { + return wrap( + MDNode::get(*unwrap(C), ArrayRef(unwrap(MDs), Count))); +} + +LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count) { + return wrap(MDNode::getTemporary(*unwrap(C), + ArrayRef(unwrap(MDs), Count))); +} + +void LLVMAddNamedMetadataOperand2(LLVMModuleRef M, const char *name, + LLVMMetadataRef Val) { + NamedMDNode *N = unwrap(M)->getOrInsertNamedMetadata(name); + if (!N) + return; + if (!Val) + return; + N->addOperand(unwrap(Val)); +} + +void LLVMSetMetadata2(LLVMValueRef Inst, unsigned KindID, LLVMMetadataRef MD) { + MDNode *N = MD ? unwrap(MD) : nullptr; + unwrap(Inst)->setMetadata(KindID, N); +} + +void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef MD, LLVMMetadataRef New) { + auto *Node = unwrap(MD); + Node->replaceAllUsesWith(unwrap(New)); + MDNode::deleteTemporary(Node); +} + +void LLVMSetCurrentDebugLocation2(LLVMBuilderRef Bref, unsigned Line, + unsigned Col, LLVMMetadataRef Scope, + LLVMMetadataRef InlinedAt) { + unwrap(Bref)->SetCurrentDebugLocation( + DebugLoc::get(Line, Col, Scope ? unwrap(Scope) : nullptr, + InlinedAt ? unwrap(InlinedAt) : nullptr)); +} diff --git a/bindings/go/llvm/IRBindings.h b/bindings/go/llvm/IRBindings.h new file mode 100644 index 0000000..a53e178 --- /dev/null +++ b/bindings/go/llvm/IRBindings.h @@ -0,0 +1,73 @@ +//===- IRBindings.h - Additional bindings for IR ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the IR component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_IRBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_IRBINDINGS_H + +#include "llvm-c/Core.h" +#ifdef __cplusplus +#include "llvm/IR/Metadata.h" +#include "llvm/Support/CBindingWrapping.h" +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct LLVMOpaqueMetadata *LLVMMetadataRef; + +// These functions duplicate the LLVM*FunctionAttr functions in the stable C +// API. We cannot use the existing functions because they take 32-bit attribute +// values, and the Go bindings expose all of the LLVM attributes, some of which +// have values >= 1<<32. + +void LLVMAddFunctionAttr2(LLVMValueRef Fn, uint64_t PA); +uint64_t LLVMGetFunctionAttr2(LLVMValueRef Fn); +void LLVMRemoveFunctionAttr2(LLVMValueRef Fn, uint64_t PA); + +LLVMMetadataRef LLVMConstantAsMetadata(LLVMValueRef Val); + +LLVMMetadataRef LLVMMDString2(LLVMContextRef C, const char *Str, unsigned SLen); +LLVMMetadataRef LLVMMDNode2(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count); +LLVMMetadataRef LLVMTemporaryMDNode(LLVMContextRef C, LLVMMetadataRef *MDs, + unsigned Count); + +void LLVMAddNamedMetadataOperand2(LLVMModuleRef M, const char *name, + LLVMMetadataRef Val); +void LLVMSetMetadata2(LLVMValueRef Inst, unsigned KindID, LLVMMetadataRef MD); + +void LLVMMetadataReplaceAllUsesWith(LLVMMetadataRef MD, LLVMMetadataRef New); + +void LLVMSetCurrentDebugLocation2(LLVMBuilderRef Bref, unsigned Line, + unsigned Col, LLVMMetadataRef Scope, + LLVMMetadataRef InlinedAt); + +#ifdef __cplusplus +} + +namespace llvm { + +DEFINE_ISA_CONVERSION_FUNCTIONS(Metadata, LLVMMetadataRef) + +inline Metadata **unwrap(LLVMMetadataRef *Vals) { + return reinterpret_cast(Vals); +} + +} + +#endif + +#endif diff --git a/bindings/go/llvm/InstrumentationBindings.cpp b/bindings/go/llvm/InstrumentationBindings.cpp new file mode 100644 index 0000000..b604abb --- /dev/null +++ b/bindings/go/llvm/InstrumentationBindings.cpp @@ -0,0 +1,42 @@ +//===- InstrumentationBindings.cpp - instrumentation bindings -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the instrumentation component. +// +//===----------------------------------------------------------------------===// + +#include "InstrumentationBindings.h" + +#include "llvm-c/Core.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Transforms/Instrumentation.h" + +using namespace llvm; + +void LLVMAddAddressSanitizerFunctionPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createAddressSanitizerFunctionPass()); +} + +void LLVMAddAddressSanitizerModulePass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createAddressSanitizerModulePass()); +} + +void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createThreadSanitizerPass()); +} + +void LLVMAddMemorySanitizerPass(LLVMPassManagerRef PM) { + unwrap(PM)->add(createMemorySanitizerPass()); +} + +void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, + const char *ABIListFile) { + unwrap(PM)->add(createDataFlowSanitizerPass(ABIListFile)); +} diff --git a/bindings/go/llvm/InstrumentationBindings.h b/bindings/go/llvm/InstrumentationBindings.h new file mode 100644 index 0000000..e8dbd59 --- /dev/null +++ b/bindings/go/llvm/InstrumentationBindings.h @@ -0,0 +1,38 @@ +//===- InstrumentationBindings.h - instrumentation bindings -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines C bindings for the Transforms/Instrumentation component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_INSTRUMENTATIONBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_INSTRUMENTATIONBINDINGS_H + +#include "llvm-c/Core.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// FIXME: These bindings shouldn't be Go-specific and should eventually move to +// a (somewhat) less stable collection of C APIs for use in creating bindings of +// LLVM in other languages. + +void LLVMAddAddressSanitizerFunctionPass(LLVMPassManagerRef PM); +void LLVMAddAddressSanitizerModulePass(LLVMPassManagerRef PM); +void LLVMAddThreadSanitizerPass(LLVMPassManagerRef PM); +void LLVMAddMemorySanitizerPass(LLVMPassManagerRef PM); +void LLVMAddDataFlowSanitizerPass(LLVMPassManagerRef PM, + const char *ABIListFile); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bindings/go/llvm/SupportBindings.cpp b/bindings/go/llvm/SupportBindings.cpp new file mode 100644 index 0000000..df5f865 --- /dev/null +++ b/bindings/go/llvm/SupportBindings.cpp @@ -0,0 +1,27 @@ +//===- SupportBindings.cpp - Additional bindings for support --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the support component. +// +//===----------------------------------------------------------------------===// + +#include "SupportBindings.h" + +#include "llvm/Support/DynamicLibrary.h" +#include +#include + +void LLVMLoadLibraryPermanently2(const char *Filename, char **ErrMsg) { + std::string ErrMsgStr; + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Filename, &ErrMsgStr)) { + *ErrMsg = static_cast(malloc(ErrMsgStr.size() + 1)); + memcpy(static_cast(*ErrMsg), + static_cast(ErrMsgStr.c_str()), ErrMsgStr.size() + 1); + } +} diff --git a/bindings/go/llvm/SupportBindings.h b/bindings/go/llvm/SupportBindings.h new file mode 100644 index 0000000..efcd667 --- /dev/null +++ b/bindings/go/llvm/SupportBindings.h @@ -0,0 +1,30 @@ +//===- SupportBindings.h - Additional bindings for Support ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines additional C bindings for the Support component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BINDINGS_GO_LLVM_SUPPORTBINDINGS_H +#define LLVM_BINDINGS_GO_LLVM_SUPPORTBINDINGS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// This function duplicates the LLVMLoadLibraryPermanently function in the +// stable C API and adds an extra ErrMsg parameter to retrieve the error +// message. +void LLVMLoadLibraryPermanently2(const char *Filename, char **ErrMsg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bindings/go/llvm/analysis.go b/bindings/go/llvm/analysis.go new file mode 100644 index 0000000..7b0d8e3 --- /dev/null +++ b/bindings/go/llvm/analysis.go @@ -0,0 +1,68 @@ +//===- analysis.go - Bindings for analysis --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the analysis component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Analysis.h" // If you are getting an error here read bindings/go/README.txt +#include +*/ +import "C" +import "errors" + +type VerifierFailureAction C.LLVMVerifierFailureAction + +const ( + // verifier will print to stderr and abort() + AbortProcessAction VerifierFailureAction = C.LLVMAbortProcessAction + // verifier will print to stderr and return 1 + PrintMessageAction VerifierFailureAction = C.LLVMPrintMessageAction + // verifier will just return 1 + ReturnStatusAction VerifierFailureAction = C.LLVMReturnStatusAction +) + +// Verifies that a module is valid, taking the specified action if not. +// Optionally returns a human-readable description of any invalid constructs. +func VerifyModule(m Module, a VerifierFailureAction) error { + var cmsg *C.char + broken := C.LLVMVerifyModule(m.C, C.LLVMVerifierFailureAction(a), &cmsg) + + // C++'s verifyModule means isModuleBroken, so it returns false if + // there are no errors + if broken != 0 { + err := errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + return err + } + return nil +} + +var verifyFunctionError = errors.New("Function is broken") + +// Verifies that a single function is valid, taking the specified action. +// Useful for debugging. +func VerifyFunction(f Value, a VerifierFailureAction) error { + broken := C.LLVMVerifyFunction(f.C, C.LLVMVerifierFailureAction(a)) + + // C++'s verifyFunction means isFunctionBroken, so it returns false if + // there are no errors + if broken != 0 { + return verifyFunctionError + } + return nil +} + +// Open up a ghostview window that displays the CFG of the current function. +// Useful for debugging. +func ViewFunctionCFG(f Value) { C.LLVMViewFunctionCFG(f.C) } +func ViewFunctionCFGOnly(f Value) { C.LLVMViewFunctionCFGOnly(f.C) } diff --git a/bindings/go/llvm/bitreader.go b/bindings/go/llvm/bitreader.go new file mode 100644 index 0000000..98112a9 --- /dev/null +++ b/bindings/go/llvm/bitreader.go @@ -0,0 +1,50 @@ +//===- bitreader.go - Bindings for bitreader ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the bitreader component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/BitReader.h" +#include +*/ +import "C" + +import ( + "errors" + "unsafe" +) + +// ParseBitcodeFile parses the LLVM IR (bitcode) in the file with the +// specified name, and returns a new LLVM module. +func ParseBitcodeFile(name string) (Module, error) { + var buf C.LLVMMemoryBufferRef + var errmsg *C.char + var cfilename *C.char = C.CString(name) + defer C.free(unsafe.Pointer(cfilename)) + result := C.LLVMCreateMemoryBufferWithContentsOfFile(cfilename, &buf, &errmsg) + if result != 0 { + err := errors.New(C.GoString(errmsg)) + C.free(unsafe.Pointer(errmsg)) + return Module{}, err + } + defer C.LLVMDisposeMemoryBuffer(buf) + + var m Module + if C.LLVMParseBitcode(buf, &m.C, &errmsg) == 0 { + return m, nil + } + + err := errors.New(C.GoString(errmsg)) + C.free(unsafe.Pointer(errmsg)) + return Module{}, err +} diff --git a/bindings/go/llvm/bitwriter.go b/bindings/go/llvm/bitwriter.go new file mode 100644 index 0000000..e03699c --- /dev/null +++ b/bindings/go/llvm/bitwriter.go @@ -0,0 +1,39 @@ +//===- bitwriter.go - Bindings for bitwriter ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the bitwriter component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/BitWriter.h" +#include +*/ +import "C" +import "os" +import "errors" + +var writeBitcodeToFileErr = errors.New("Failed to write bitcode to file") + +func WriteBitcodeToFile(m Module, file *os.File) error { + fail := C.LLVMWriteBitcodeToFD(m.C, C.int(file.Fd()), C.int(0), C.int(0)) + if fail != 0 { + return writeBitcodeToFileErr + } + return nil +} + +func WriteBitcodeToMemoryBuffer(m Module) MemoryBuffer { + mb := C.LLVMWriteBitcodeToMemoryBuffer(m.C) + return MemoryBuffer{mb} +} + +// TODO(nsf): Figure out way how to make it work with io.Writer diff --git a/bindings/go/llvm/dibuilder.go b/bindings/go/llvm/dibuilder.go new file mode 100644 index 0000000..3b1a1a6 --- /dev/null +++ b/bindings/go/llvm/dibuilder.go @@ -0,0 +1,491 @@ +//===- dibuilder.go - Bindings for DIBuilder ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the DIBuilder class. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "DIBuilderBindings.h" +#include +*/ +import "C" + +import ( + "debug/dwarf" + "unsafe" +) + +type DwarfTag uint32 + +const ( + DW_TAG_lexical_block DwarfTag = 0x0b + DW_TAG_compile_unit DwarfTag = 0x11 + DW_TAG_variable DwarfTag = 0x34 + DW_TAG_base_type DwarfTag = 0x24 + DW_TAG_pointer_type DwarfTag = 0x0F + DW_TAG_structure_type DwarfTag = 0x13 + DW_TAG_subroutine_type DwarfTag = 0x15 + DW_TAG_file_type DwarfTag = 0x29 + DW_TAG_subprogram DwarfTag = 0x2E + DW_TAG_auto_variable DwarfTag = 0x100 + DW_TAG_arg_variable DwarfTag = 0x101 +) + +const ( + FlagPrivate = 1 << iota + FlagProtected + FlagFwdDecl + FlagAppleBlock + FlagBlockByrefStruct + FlagVirtual + FlagArtificial + FlagExplicit + FlagPrototyped + FlagObjcClassComplete + FlagObjectPointer + FlagVector + FlagStaticMember + FlagIndirectVariable +) + +type DwarfLang uint32 + +const ( + // http://dwarfstd.org/ShowIssue.php?issue=101014.1&type=open + DW_LANG_Go DwarfLang = 0x0016 +) + +type DwarfTypeEncoding uint32 + +const ( + DW_ATE_address DwarfTypeEncoding = 0x01 + DW_ATE_boolean DwarfTypeEncoding = 0x02 + DW_ATE_complex_float DwarfTypeEncoding = 0x03 + DW_ATE_float DwarfTypeEncoding = 0x04 + DW_ATE_signed DwarfTypeEncoding = 0x05 + DW_ATE_signed_char DwarfTypeEncoding = 0x06 + DW_ATE_unsigned DwarfTypeEncoding = 0x07 + DW_ATE_unsigned_char DwarfTypeEncoding = 0x08 + DW_ATE_imaginary_float DwarfTypeEncoding = 0x09 + DW_ATE_packed_decimal DwarfTypeEncoding = 0x0a + DW_ATE_numeric_string DwarfTypeEncoding = 0x0b + DW_ATE_edited DwarfTypeEncoding = 0x0c + DW_ATE_signed_fixed DwarfTypeEncoding = 0x0d + DW_ATE_unsigned_fixed DwarfTypeEncoding = 0x0e + DW_ATE_decimal_float DwarfTypeEncoding = 0x0f + DW_ATE_UTF DwarfTypeEncoding = 0x10 + DW_ATE_lo_user DwarfTypeEncoding = 0x80 + DW_ATE_hi_user DwarfTypeEncoding = 0xff +) + +// DIBuilder is a wrapper for the LLVM DIBuilder class. +type DIBuilder struct { + ref C.LLVMDIBuilderRef + m Module +} + +// NewDIBuilder creates a new DIBuilder, associated with the given module. +func NewDIBuilder(m Module) *DIBuilder { + d := C.LLVMNewDIBuilder(m.C) + return &DIBuilder{ref: d, m: m} +} + +// Destroy destroys the DIBuilder. +func (d *DIBuilder) Destroy() { + C.LLVMDIBuilderDestroy(d.ref) +} + +// FInalize finalizes the debug information generated by the DIBuilder. +func (d *DIBuilder) Finalize() { + C.LLVMDIBuilderFinalize(d.ref) +} + +// DICompileUnit holds the values for creating compile unit debug metadata. +type DICompileUnit struct { + Language DwarfLang + File string + Dir string + Producer string + Optimized bool + Flags string + RuntimeVersion int +} + +// CreateCompileUnit creates compile unit debug metadata. +func (d *DIBuilder) CreateCompileUnit(cu DICompileUnit) Metadata { + file := C.CString(cu.File) + defer C.free(unsafe.Pointer(file)) + dir := C.CString(cu.Dir) + defer C.free(unsafe.Pointer(dir)) + producer := C.CString(cu.Producer) + defer C.free(unsafe.Pointer(producer)) + flags := C.CString(cu.Flags) + defer C.free(unsafe.Pointer(flags)) + result := C.LLVMDIBuilderCreateCompileUnit( + d.ref, + C.unsigned(cu.Language), + file, dir, + producer, + boolToCInt(cu.Optimized), + flags, + C.unsigned(cu.RuntimeVersion), + ) + return Metadata{C: result} +} + +// CreateCompileUnit creates file debug metadata. +func (d *DIBuilder) CreateFile(filename, dir string) Metadata { + cfilename := C.CString(filename) + defer C.free(unsafe.Pointer(cfilename)) + cdir := C.CString(dir) + defer C.free(unsafe.Pointer(cdir)) + result := C.LLVMDIBuilderCreateFile(d.ref, cfilename, cdir) + return Metadata{C: result} +} + +// DILexicalBlock holds the values for creating lexical block debug metadata. +type DILexicalBlock struct { + File Metadata + Line int + Column int +} + +// CreateCompileUnit creates lexical block debug metadata. +func (d *DIBuilder) CreateLexicalBlock(diScope Metadata, b DILexicalBlock) Metadata { + result := C.LLVMDIBuilderCreateLexicalBlock( + d.ref, + diScope.C, + b.File.C, + C.unsigned(b.Line), + C.unsigned(b.Column), + ) + return Metadata{C: result} +} + +func (d *DIBuilder) CreateLexicalBlockFile(diScope Metadata, diFile Metadata, discriminator int) Metadata { + result := C.LLVMDIBuilderCreateLexicalBlockFile(d.ref, diScope.C, diFile.C, + C.unsigned(discriminator)) + return Metadata{C: result} +} + +// DIFunction holds the values for creating function debug metadata. +type DIFunction struct { + Name string + LinkageName string + File Metadata + Line int + Type Metadata + LocalToUnit bool + IsDefinition bool + ScopeLine int + Flags int + Optimized bool + Function Value +} + +// CreateCompileUnit creates function debug metadata. +func (d *DIBuilder) CreateFunction(diScope Metadata, f DIFunction) Metadata { + name := C.CString(f.Name) + defer C.free(unsafe.Pointer(name)) + linkageName := C.CString(f.LinkageName) + defer C.free(unsafe.Pointer(linkageName)) + result := C.LLVMDIBuilderCreateFunction( + d.ref, + diScope.C, + name, + linkageName, + f.File.C, + C.unsigned(f.Line), + f.Type.C, + boolToCInt(f.LocalToUnit), + boolToCInt(f.IsDefinition), + C.unsigned(f.ScopeLine), + C.unsigned(f.Flags), + boolToCInt(f.Optimized), + f.Function.C, + ) + return Metadata{C: result} +} + +// DILocalVariable holds the values for creating local variable debug metadata. +type DILocalVariable struct { + Tag dwarf.Tag + Name string + File Metadata + Line int + Type Metadata + AlwaysPreserve bool + Flags int + + // ArgNo is the 1-based index of the argument in the function's + // parameter list if it is an argument, or 0 otherwise. + ArgNo int +} + +// CreateLocalVariable creates local variable debug metadata. +func (d *DIBuilder) CreateLocalVariable(scope Metadata, v DILocalVariable) Metadata { + name := C.CString(v.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateLocalVariable( + d.ref, + C.unsigned(v.Tag), + scope.C, + name, + v.File.C, + C.unsigned(v.Line), + v.Type.C, + boolToCInt(v.AlwaysPreserve), + C.unsigned(v.Flags), + C.unsigned(v.ArgNo), + ) + return Metadata{C: result} +} + +// DIBasicType holds the values for creating basic type debug metadata. +type DIBasicType struct { + Name string + SizeInBits uint64 + AlignInBits uint64 + Encoding DwarfTypeEncoding +} + +// CreateBasicType creates basic type debug metadata. +func (d *DIBuilder) CreateBasicType(t DIBasicType) Metadata { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateBasicType( + d.ref, + name, + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + C.unsigned(t.Encoding), + ) + return Metadata{C: result} +} + +// DIPointerType holds the values for creating pointer type debug metadata. +type DIPointerType struct { + Pointee Metadata + SizeInBits uint64 + AlignInBits uint64 // optional + Name string // optional +} + +// CreateBasicType creates basic type debug metadata. +func (d *DIBuilder) CreatePointerType(t DIPointerType) Metadata { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreatePointerType( + d.ref, + t.Pointee.C, + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + name, + ) + return Metadata{C: result} +} + +// DISubroutineType holds the values for creating subroutine type debug metadata. +type DISubroutineType struct { + // File is the file in which the subroutine type is defined. + File Metadata + + // Parameters contains the subroutine parameter types, + // including the return type at the 0th index. + Parameters []Metadata +} + +// CreateSubroutineType creates subroutine type debug metadata. +func (d *DIBuilder) CreateSubroutineType(t DISubroutineType) Metadata { + params := d.getOrCreateTypeArray(t.Parameters) + result := C.LLVMDIBuilderCreateSubroutineType(d.ref, t.File.C, params.C) + return Metadata{C: result} +} + +// DIStructType holds the values for creating struct type debug metadata. +type DIStructType struct { + Name string + File Metadata + Line int + SizeInBits uint64 + AlignInBits uint64 + Flags int + DerivedFrom Metadata + Elements []Metadata +} + +// CreateStructType creates struct type debug metadata. +func (d *DIBuilder) CreateStructType(scope Metadata, t DIStructType) Metadata { + elements := d.getOrCreateArray(t.Elements) + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateStructType( + d.ref, + scope.C, + name, + t.File.C, + C.unsigned(t.Line), + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + C.unsigned(t.Flags), + t.DerivedFrom.C, + elements.C, + ) + return Metadata{C: result} +} + +// DIMemberType holds the values for creating member type debug metadata. +type DIMemberType struct { + Name string + File Metadata + Line int + SizeInBits uint64 + AlignInBits uint64 + OffsetInBits uint64 + Flags int + Type Metadata +} + +// CreateMemberType creates struct type debug metadata. +func (d *DIBuilder) CreateMemberType(scope Metadata, t DIMemberType) Metadata { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateMemberType( + d.ref, + scope.C, + name, + t.File.C, + C.unsigned(t.Line), + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + C.uint64_t(t.OffsetInBits), + C.unsigned(t.Flags), + t.Type.C, + ) + return Metadata{C: result} +} + +// DISubrange describes an integer value range. +type DISubrange struct { + Lo int64 + Count int64 +} + +// DIArrayType holds the values for creating array type debug metadata. +type DIArrayType struct { + SizeInBits uint64 + AlignInBits uint64 + ElementType Metadata + Subscripts []DISubrange +} + +// CreateArrayType creates struct type debug metadata. +func (d *DIBuilder) CreateArrayType(t DIArrayType) Metadata { + subscriptsSlice := make([]Metadata, len(t.Subscripts)) + for i, s := range t.Subscripts { + subscriptsSlice[i] = d.getOrCreateSubrange(s.Lo, s.Count) + } + subscripts := d.getOrCreateArray(subscriptsSlice) + result := C.LLVMDIBuilderCreateArrayType( + d.ref, + C.uint64_t(t.SizeInBits), + C.uint64_t(t.AlignInBits), + t.ElementType.C, + subscripts.C, + ) + return Metadata{C: result} +} + +// DITypedef holds the values for creating typedef type debug metadata. +type DITypedef struct { + Type Metadata + Name string + File Metadata + Line int + Context Metadata +} + +// CreateTypedef creates typedef type debug metadata. +func (d *DIBuilder) CreateTypedef(t DITypedef) Metadata { + name := C.CString(t.Name) + defer C.free(unsafe.Pointer(name)) + result := C.LLVMDIBuilderCreateTypedef( + d.ref, + t.Type.C, + name, + t.File.C, + C.unsigned(t.Line), + t.Context.C, + ) + return Metadata{C: result} +} + +// getOrCreateSubrange gets a metadata node for the specified subrange, +// creating if required. +func (d *DIBuilder) getOrCreateSubrange(lo, count int64) Metadata { + result := C.LLVMDIBuilderGetOrCreateSubrange(d.ref, C.int64_t(lo), C.int64_t(count)) + return Metadata{C: result} +} + +// getOrCreateArray gets a metadata node containing the specified values, +// creating if required. +func (d *DIBuilder) getOrCreateArray(values []Metadata) Metadata { + if len(values) == 0 { + return Metadata{} + } + data, length := llvmMetadataRefs(values) + result := C.LLVMDIBuilderGetOrCreateArray(d.ref, data, C.size_t(length)) + return Metadata{C: result} +} + +// getOrCreateTypeArray gets a metadata node for a type array containing the +// specified values, creating if required. +func (d *DIBuilder) getOrCreateTypeArray(values []Metadata) Metadata { + if len(values) == 0 { + return Metadata{} + } + data, length := llvmMetadataRefs(values) + result := C.LLVMDIBuilderGetOrCreateTypeArray(d.ref, data, C.size_t(length)) + return Metadata{C: result} +} + +// CreateExpression creates a new descriptor for the specified +// variable which has a complex address expression for its address. +func (d *DIBuilder) CreateExpression(addr []int64) Metadata { + var data *C.int64_t + if len(addr) > 0 { + data = (*C.int64_t)(unsafe.Pointer(&addr[0])) + } + result := C.LLVMDIBuilderCreateExpression(d.ref, data, C.size_t(len(addr))) + return Metadata{C: result} +} + +// InsertDeclareAtEnd inserts a call to llvm.dbg.declare at the end of the +// specified basic block for the given value and associated debug metadata. +func (d *DIBuilder) InsertDeclareAtEnd(v Value, diVarInfo, expr Metadata, bb BasicBlock) Value { + result := C.LLVMDIBuilderInsertDeclareAtEnd(d.ref, v.C, diVarInfo.C, expr.C, bb.C) + return Value{C: result} +} + +// InsertValueAtEnd inserts a call to llvm.dbg.value at the end of the +// specified basic block for the given value and associated debug metadata. +func (d *DIBuilder) InsertValueAtEnd(v Value, diVarInfo, expr Metadata, offset uint64, bb BasicBlock) Value { + result := C.LLVMDIBuilderInsertValueAtEnd(d.ref, v.C, C.uint64_t(offset), diVarInfo.C, expr.C, bb.C) + return Value{C: result} +} + +func boolToCInt(v bool) C.int { + if v { + return 1 + } + return 0 +} diff --git a/bindings/go/llvm/executionengine.go b/bindings/go/llvm/executionengine.go new file mode 100644 index 0000000..94d4e83 --- /dev/null +++ b/bindings/go/llvm/executionengine.go @@ -0,0 +1,177 @@ +//===- executionengine.go - Bindings for executionengine ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the executionengine component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/ExecutionEngine.h" +#include +*/ +import "C" +import "unsafe" +import "errors" + +func LinkInMCJIT() { C.LLVMLinkInMCJIT() } +func LinkInInterpreter() { C.LLVMLinkInInterpreter() } + +type GenericValue struct { + C C.LLVMGenericValueRef +} +type ExecutionEngine struct { + C C.LLVMExecutionEngineRef +} + +type MCJITCompilerOptions struct { + C C.struct_LLVMMCJITCompilerOptions +} + +func (options *MCJITCompilerOptions) SetMCJITOptimizationLevel(level uint) { + options.C.OptLevel = C.uint(level) +} + +func (options *MCJITCompilerOptions) SetMCJITNoFramePointerElim(nfp bool) { + options.C.NoFramePointerElim = boolToLLVMBool(nfp) +} + +func (options *MCJITCompilerOptions) SetMCJITEnableFastISel(fastisel bool) { + options.C.EnableFastISel = boolToLLVMBool(fastisel) +} + +func (options *MCJITCompilerOptions) SetMCJITCodeModel(CodeModel CodeModel) { + options.C.CodeModel = C.LLVMCodeModel(CodeModel) +} + +// helpers +func llvmGenericValueRefPtr(t *GenericValue) *C.LLVMGenericValueRef { + return (*C.LLVMGenericValueRef)(unsafe.Pointer(t)) +} + +//------------------------------------------------------------------------- +// llvm.GenericValue +//------------------------------------------------------------------------- + +func NewGenericValueFromInt(t Type, n uint64, signed bool) (g GenericValue) { + g.C = C.LLVMCreateGenericValueOfInt(t.C, C.ulonglong(n), boolToLLVMBool(signed)) + return +} +func NewGenericValueFromPointer(p unsafe.Pointer) (g GenericValue) { + g.C = C.LLVMCreateGenericValueOfPointer(p) + return +} +func NewGenericValueFromFloat(t Type, n float64) (g GenericValue) { + g.C = C.LLVMCreateGenericValueOfFloat(t.C, C.double(n)) + return +} +func (g GenericValue) IntWidth() int { return int(C.LLVMGenericValueIntWidth(g.C)) } +func (g GenericValue) Int(signed bool) uint64 { + return uint64(C.LLVMGenericValueToInt(g.C, boolToLLVMBool(signed))) +} +func (g GenericValue) Float(t Type) float64 { + return float64(C.LLVMGenericValueToFloat(t.C, g.C)) +} +func (g GenericValue) Pointer() unsafe.Pointer { + return C.LLVMGenericValueToPointer(g.C) +} +func (g GenericValue) Dispose() { C.LLVMDisposeGenericValue(g.C) } + +//------------------------------------------------------------------------- +// llvm.ExecutionEngine +//------------------------------------------------------------------------- + +func NewExecutionEngine(m Module) (ee ExecutionEngine, err error) { + var cmsg *C.char + fail := C.LLVMCreateExecutionEngineForModule(&ee.C, m.C, &cmsg) + if fail != 0 { + ee.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func NewInterpreter(m Module) (ee ExecutionEngine, err error) { + var cmsg *C.char + fail := C.LLVMCreateInterpreterForModule(&ee.C, m.C, &cmsg) + if fail != 0 { + ee.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func NewMCJITCompilerOptions() MCJITCompilerOptions { + var options C.struct_LLVMMCJITCompilerOptions + C.LLVMInitializeMCJITCompilerOptions(&options, C.size_t(unsafe.Sizeof(C.struct_LLVMMCJITCompilerOptions{}))) + return MCJITCompilerOptions{options} +} + +func NewMCJITCompiler(m Module, options MCJITCompilerOptions) (ee ExecutionEngine, err error) { + var cmsg *C.char + fail := C.LLVMCreateMCJITCompilerForModule(&ee.C, m.C, &options.C, C.size_t(unsafe.Sizeof(C.struct_LLVMMCJITCompilerOptions{})), &cmsg) + if fail != 0 { + ee.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func (ee ExecutionEngine) Dispose() { C.LLVMDisposeExecutionEngine(ee.C) } +func (ee ExecutionEngine) RunStaticConstructors() { C.LLVMRunStaticConstructors(ee.C) } +func (ee ExecutionEngine) RunStaticDestructors() { C.LLVMRunStaticDestructors(ee.C) } + +func (ee ExecutionEngine) RunFunction(f Value, args []GenericValue) (g GenericValue) { + nargs := len(args) + var argptr *GenericValue + if nargs > 0 { + argptr = &args[0] + } + g.C = C.LLVMRunFunction(ee.C, f.C, + C.unsigned(nargs), llvmGenericValueRefPtr(argptr)) + return +} + +func (ee ExecutionEngine) FreeMachineCodeForFunction(f Value) { + C.LLVMFreeMachineCodeForFunction(ee.C, f.C) +} +func (ee ExecutionEngine) AddModule(m Module) { C.LLVMAddModule(ee.C, m.C) } + +func (ee ExecutionEngine) RemoveModule(m Module) { + var modtmp C.LLVMModuleRef + C.LLVMRemoveModule(ee.C, m.C, &modtmp, nil) +} + +func (ee ExecutionEngine) FindFunction(name string) (f Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMFindFunction(ee.C, cname, &f.C) + return +} + +func (ee ExecutionEngine) RecompileAndRelinkFunction(f Value) unsafe.Pointer { + return C.LLVMRecompileAndRelinkFunction(ee.C, f.C) +} + +func (ee ExecutionEngine) TargetData() (td TargetData) { + td.C = C.LLVMGetExecutionEngineTargetData(ee.C) + return +} + +func (ee ExecutionEngine) AddGlobalMapping(global Value, addr unsafe.Pointer) { + C.LLVMAddGlobalMapping(ee.C, global.C, addr) +} + +func (ee ExecutionEngine) PointerToGlobal(global Value) unsafe.Pointer { + return C.LLVMGetPointerToGlobal(ee.C, global.C) +} diff --git a/bindings/go/llvm/executionengine_test.go b/bindings/go/llvm/executionengine_test.go new file mode 100644 index 0000000..2b6a3caf --- /dev/null +++ b/bindings/go/llvm/executionengine_test.go @@ -0,0 +1,98 @@ +//===- executionengine_test.go - Tests for executionengine ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests bindings for the executionengine component. +// +//===----------------------------------------------------------------------===// + +package llvm + +import ( + "testing" +) + +func TestFactorial(t *testing.T) { + LinkInMCJIT() + InitializeNativeTarget() + InitializeNativeAsmPrinter() + + mod := NewModule("fac_module") + + fac_args := []Type{Int32Type()} + fac_type := FunctionType(Int32Type(), fac_args, false) + fac := AddFunction(mod, "fac", fac_type) + fac.SetFunctionCallConv(CCallConv) + n := fac.Param(0) + + entry := AddBasicBlock(fac, "entry") + iftrue := AddBasicBlock(fac, "iftrue") + iffalse := AddBasicBlock(fac, "iffalse") + end := AddBasicBlock(fac, "end") + + builder := NewBuilder() + defer builder.Dispose() + + builder.SetInsertPointAtEnd(entry) + If := builder.CreateICmp(IntEQ, n, ConstInt(Int32Type(), 0, false), "cmptmp") + builder.CreateCondBr(If, iftrue, iffalse) + + builder.SetInsertPointAtEnd(iftrue) + res_iftrue := ConstInt(Int32Type(), 1, false) + builder.CreateBr(end) + + builder.SetInsertPointAtEnd(iffalse) + n_minus := builder.CreateSub(n, ConstInt(Int32Type(), 1, false), "subtmp") + call_fac_args := []Value{n_minus} + call_fac := builder.CreateCall(fac, call_fac_args, "calltmp") + res_iffalse := builder.CreateMul(n, call_fac, "multmp") + builder.CreateBr(end) + + builder.SetInsertPointAtEnd(end) + res := builder.CreatePHI(Int32Type(), "result") + phi_vals := []Value{res_iftrue, res_iffalse} + phi_blocks := []BasicBlock{iftrue, iffalse} + res.AddIncoming(phi_vals, phi_blocks) + builder.CreateRet(res) + + err := VerifyModule(mod, ReturnStatusAction) + if err != nil { + t.Errorf("Error verifying module: %s", err) + return + } + + options := NewMCJITCompilerOptions() + options.SetMCJITOptimizationLevel(2) + options.SetMCJITEnableFastISel(true) + options.SetMCJITNoFramePointerElim(true) + options.SetMCJITCodeModel(CodeModelJITDefault) + engine, err := NewMCJITCompiler(mod, options) + if err != nil { + t.Errorf("Error creating JIT: %s", err) + return + } + defer engine.Dispose() + + pass := NewPassManager() + defer pass.Dispose() + + pass.Add(engine.TargetData()) + pass.AddConstantPropagationPass() + pass.AddInstructionCombiningPass() + pass.AddPromoteMemoryToRegisterPass() + pass.AddGVNPass() + pass.AddCFGSimplificationPass() + pass.Run(mod) + + exec_args := []GenericValue{NewGenericValueFromInt(Int32Type(), 10, false)} + exec_res := engine.RunFunction(fac, exec_args) + var fac10 uint64 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 + if exec_res.Int(false) != fac10 { + t.Errorf("Expected %d, got %d", fac10, exec_res.Int(false)) + } +} diff --git a/bindings/go/llvm/ir.go b/bindings/go/llvm/ir.go new file mode 100644 index 0000000..e5916a1 --- /dev/null +++ b/bindings/go/llvm/ir.go @@ -0,0 +1,1846 @@ +//===- ir.go - Bindings for ir --------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the ir component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Core.h" +#include "IRBindings.h" +#include +*/ +import "C" +import "unsafe" +import "errors" + +type ( + // We use these weird structs here because *Ref types are pointers and + // Go's spec says that a pointer cannot be used as a receiver base type. + Context struct { + C C.LLVMContextRef + } + Module struct { + C C.LLVMModuleRef + } + Type struct { + C C.LLVMTypeRef + } + Value struct { + C C.LLVMValueRef + } + BasicBlock struct { + C C.LLVMBasicBlockRef + } + Builder struct { + C C.LLVMBuilderRef + } + ModuleProvider struct { + C C.LLVMModuleProviderRef + } + MemoryBuffer struct { + C C.LLVMMemoryBufferRef + } + PassManager struct { + C C.LLVMPassManagerRef + } + Use struct { + C C.LLVMUseRef + } + Metadata struct { + C C.LLVMMetadataRef + } + Attribute uint64 + Opcode C.LLVMOpcode + TypeKind C.LLVMTypeKind + Linkage C.LLVMLinkage + Visibility C.LLVMVisibility + CallConv C.LLVMCallConv + IntPredicate C.LLVMIntPredicate + FloatPredicate C.LLVMRealPredicate + LandingPadClause C.LLVMLandingPadClauseTy +) + +func (c Context) IsNil() bool { return c.C == nil } +func (c Module) IsNil() bool { return c.C == nil } +func (c Type) IsNil() bool { return c.C == nil } +func (c Value) IsNil() bool { return c.C == nil } +func (c BasicBlock) IsNil() bool { return c.C == nil } +func (c Builder) IsNil() bool { return c.C == nil } +func (c ModuleProvider) IsNil() bool { return c.C == nil } +func (c MemoryBuffer) IsNil() bool { return c.C == nil } +func (c PassManager) IsNil() bool { return c.C == nil } +func (c Use) IsNil() bool { return c.C == nil } + +// helpers +func llvmTypeRefPtr(t *Type) *C.LLVMTypeRef { return (*C.LLVMTypeRef)(unsafe.Pointer(t)) } +func llvmValueRefPtr(t *Value) *C.LLVMValueRef { return (*C.LLVMValueRef)(unsafe.Pointer(t)) } +func llvmMetadataRefPtr(t *Metadata) *C.LLVMMetadataRef { + return (*C.LLVMMetadataRef)(unsafe.Pointer(t)) +} +func llvmBasicBlockRefPtr(t *BasicBlock) *C.LLVMBasicBlockRef { + return (*C.LLVMBasicBlockRef)(unsafe.Pointer(t)) +} +func boolToLLVMBool(b bool) C.LLVMBool { + if b { + return C.LLVMBool(1) + } + return C.LLVMBool(0) +} + +func llvmValueRefs(values []Value) (*C.LLVMValueRef, C.unsigned) { + var pt *C.LLVMValueRef + ptlen := C.unsigned(len(values)) + if ptlen > 0 { + pt = llvmValueRefPtr(&values[0]) + } + return pt, ptlen +} + +func llvmMetadataRefs(mds []Metadata) (*C.LLVMMetadataRef, C.unsigned) { + var pt *C.LLVMMetadataRef + ptlen := C.unsigned(len(mds)) + if ptlen > 0 { + pt = llvmMetadataRefPtr(&mds[0]) + } + return pt, ptlen +} + +//------------------------------------------------------------------------- +// llvm.Attribute +//------------------------------------------------------------------------- + +const ( + NoneAttribute Attribute = 0 + ZExtAttribute Attribute = C.LLVMZExtAttribute + SExtAttribute Attribute = C.LLVMSExtAttribute + NoReturnAttribute Attribute = C.LLVMNoReturnAttribute + InRegAttribute Attribute = C.LLVMInRegAttribute + StructRetAttribute Attribute = C.LLVMStructRetAttribute + NoUnwindAttribute Attribute = C.LLVMNoUnwindAttribute + NoAliasAttribute Attribute = C.LLVMNoAliasAttribute + ByValAttribute Attribute = C.LLVMByValAttribute + NestAttribute Attribute = C.LLVMNestAttribute + ReadNoneAttribute Attribute = C.LLVMReadNoneAttribute + ReadOnlyAttribute Attribute = C.LLVMReadOnlyAttribute + NoInlineAttribute Attribute = C.LLVMNoInlineAttribute + AlwaysInlineAttribute Attribute = C.LLVMAlwaysInlineAttribute + OptimizeForSizeAttribute Attribute = C.LLVMOptimizeForSizeAttribute + StackProtectAttribute Attribute = C.LLVMStackProtectAttribute + StackProtectReqAttribute Attribute = C.LLVMStackProtectReqAttribute + Alignment Attribute = C.LLVMAlignment + NoCaptureAttribute Attribute = C.LLVMNoCaptureAttribute + NoRedZoneAttribute Attribute = C.LLVMNoRedZoneAttribute + NoImplicitFloatAttribute Attribute = C.LLVMNoImplicitFloatAttribute + NakedAttribute Attribute = C.LLVMNakedAttribute + InlineHintAttribute Attribute = C.LLVMInlineHintAttribute + StackAlignment Attribute = C.LLVMStackAlignment + ReturnsTwiceAttribute Attribute = C.LLVMReturnsTwice + UWTableAttribute Attribute = C.LLVMUWTable + NonLazyBindAttribute Attribute = 1 << 31 + SanitizeAddressAttribute Attribute = 1 << 32 + MinSizeAttribute Attribute = 1 << 33 + NoDuplicateAttribute Attribute = 1 << 34 + StackProtectStrongAttribute Attribute = 1 << 35 + SanitizeThreadAttribute Attribute = 1 << 36 + SanitizeMemoryAttribute Attribute = 1 << 37 + NoBuiltinAttribute Attribute = 1 << 38 + ReturnedAttribute Attribute = 1 << 39 + ColdAttribute Attribute = 1 << 40 + BuiltinAttribute Attribute = 1 << 41 + OptimizeNoneAttribute Attribute = 1 << 42 + InAllocaAttribute Attribute = 1 << 43 + NonNullAttribute Attribute = 1 << 44 + JumpTableAttribute Attribute = 1 << 45 +) + +//------------------------------------------------------------------------- +// llvm.Opcode +//------------------------------------------------------------------------- + +const ( + Ret Opcode = C.LLVMRet + Br Opcode = C.LLVMBr + Switch Opcode = C.LLVMSwitch + IndirectBr Opcode = C.LLVMIndirectBr + Invoke Opcode = C.LLVMInvoke + Unreachable Opcode = C.LLVMUnreachable + + // Standard Binary Operators + Add Opcode = C.LLVMAdd + FAdd Opcode = C.LLVMFAdd + Sub Opcode = C.LLVMSub + FSub Opcode = C.LLVMFSub + Mul Opcode = C.LLVMMul + FMul Opcode = C.LLVMFMul + UDiv Opcode = C.LLVMUDiv + SDiv Opcode = C.LLVMSDiv + FDiv Opcode = C.LLVMFDiv + URem Opcode = C.LLVMURem + SRem Opcode = C.LLVMSRem + FRem Opcode = C.LLVMFRem + + // Logical Operators + Shl Opcode = C.LLVMShl + LShr Opcode = C.LLVMLShr + AShr Opcode = C.LLVMAShr + And Opcode = C.LLVMAnd + Or Opcode = C.LLVMOr + Xor Opcode = C.LLVMXor + + // Memory Operators + Alloca Opcode = C.LLVMAlloca + Load Opcode = C.LLVMLoad + Store Opcode = C.LLVMStore + GetElementPtr Opcode = C.LLVMGetElementPtr + + // Cast Operators + Trunc Opcode = C.LLVMTrunc + ZExt Opcode = C.LLVMZExt + SExt Opcode = C.LLVMSExt + FPToUI Opcode = C.LLVMFPToUI + FPToSI Opcode = C.LLVMFPToSI + UIToFP Opcode = C.LLVMUIToFP + SIToFP Opcode = C.LLVMSIToFP + FPTrunc Opcode = C.LLVMFPTrunc + FPExt Opcode = C.LLVMFPExt + PtrToInt Opcode = C.LLVMPtrToInt + IntToPtr Opcode = C.LLVMIntToPtr + BitCast Opcode = C.LLVMBitCast + + // Other Operators + ICmp Opcode = C.LLVMICmp + FCmp Opcode = C.LLVMFCmp + PHI Opcode = C.LLVMPHI + Call Opcode = C.LLVMCall + Select Opcode = C.LLVMSelect + // UserOp1 + // UserOp2 + VAArg Opcode = C.LLVMVAArg + ExtractElement Opcode = C.LLVMExtractElement + InsertElement Opcode = C.LLVMInsertElement + ShuffleVector Opcode = C.LLVMShuffleVector + ExtractValue Opcode = C.LLVMExtractValue + InsertValue Opcode = C.LLVMInsertValue +) + +//------------------------------------------------------------------------- +// llvm.TypeKind +//------------------------------------------------------------------------- + +const ( + VoidTypeKind TypeKind = C.LLVMVoidTypeKind + FloatTypeKind TypeKind = C.LLVMFloatTypeKind + DoubleTypeKind TypeKind = C.LLVMDoubleTypeKind + X86_FP80TypeKind TypeKind = C.LLVMX86_FP80TypeKind + FP128TypeKind TypeKind = C.LLVMFP128TypeKind + PPC_FP128TypeKind TypeKind = C.LLVMPPC_FP128TypeKind + LabelTypeKind TypeKind = C.LLVMLabelTypeKind + IntegerTypeKind TypeKind = C.LLVMIntegerTypeKind + FunctionTypeKind TypeKind = C.LLVMFunctionTypeKind + StructTypeKind TypeKind = C.LLVMStructTypeKind + ArrayTypeKind TypeKind = C.LLVMArrayTypeKind + PointerTypeKind TypeKind = C.LLVMPointerTypeKind + VectorTypeKind TypeKind = C.LLVMVectorTypeKind + MetadataTypeKind TypeKind = C.LLVMMetadataTypeKind +) + +//------------------------------------------------------------------------- +// llvm.Linkage +//------------------------------------------------------------------------- + +const ( + ExternalLinkage Linkage = C.LLVMExternalLinkage + AvailableExternallyLinkage Linkage = C.LLVMAvailableExternallyLinkage + LinkOnceAnyLinkage Linkage = C.LLVMLinkOnceAnyLinkage + LinkOnceODRLinkage Linkage = C.LLVMLinkOnceODRLinkage + WeakAnyLinkage Linkage = C.LLVMWeakAnyLinkage + WeakODRLinkage Linkage = C.LLVMWeakODRLinkage + AppendingLinkage Linkage = C.LLVMAppendingLinkage + InternalLinkage Linkage = C.LLVMInternalLinkage + PrivateLinkage Linkage = C.LLVMPrivateLinkage + ExternalWeakLinkage Linkage = C.LLVMExternalWeakLinkage + CommonLinkage Linkage = C.LLVMCommonLinkage +) + +//------------------------------------------------------------------------- +// llvm.Visibility +//------------------------------------------------------------------------- + +const ( + DefaultVisibility Visibility = C.LLVMDefaultVisibility + HiddenVisibility Visibility = C.LLVMHiddenVisibility + ProtectedVisibility Visibility = C.LLVMProtectedVisibility +) + +//------------------------------------------------------------------------- +// llvm.CallConv +//------------------------------------------------------------------------- + +const ( + CCallConv CallConv = C.LLVMCCallConv + FastCallConv CallConv = C.LLVMFastCallConv + ColdCallConv CallConv = C.LLVMColdCallConv + X86StdcallCallConv CallConv = C.LLVMX86StdcallCallConv + X86FastcallCallConv CallConv = C.LLVMX86FastcallCallConv +) + +//------------------------------------------------------------------------- +// llvm.IntPredicate +//------------------------------------------------------------------------- + +const ( + IntEQ IntPredicate = C.LLVMIntEQ + IntNE IntPredicate = C.LLVMIntNE + IntUGT IntPredicate = C.LLVMIntUGT + IntUGE IntPredicate = C.LLVMIntUGE + IntULT IntPredicate = C.LLVMIntULT + IntULE IntPredicate = C.LLVMIntULE + IntSGT IntPredicate = C.LLVMIntSGT + IntSGE IntPredicate = C.LLVMIntSGE + IntSLT IntPredicate = C.LLVMIntSLT + IntSLE IntPredicate = C.LLVMIntSLE +) + +//------------------------------------------------------------------------- +// llvm.FloatPredicate +//------------------------------------------------------------------------- + +const ( + FloatPredicateFalse FloatPredicate = C.LLVMRealPredicateFalse + FloatOEQ FloatPredicate = C.LLVMRealOEQ + FloatOGT FloatPredicate = C.LLVMRealOGT + FloatOGE FloatPredicate = C.LLVMRealOGE + FloatOLT FloatPredicate = C.LLVMRealOLT + FloatOLE FloatPredicate = C.LLVMRealOLE + FloatONE FloatPredicate = C.LLVMRealONE + FloatORD FloatPredicate = C.LLVMRealORD + FloatUNO FloatPredicate = C.LLVMRealUNO + FloatUEQ FloatPredicate = C.LLVMRealUEQ + FloatUGT FloatPredicate = C.LLVMRealUGT + FloatUGE FloatPredicate = C.LLVMRealUGE + FloatULT FloatPredicate = C.LLVMRealULT + FloatULE FloatPredicate = C.LLVMRealULE + FloatUNE FloatPredicate = C.LLVMRealUNE + FloatPredicateTrue FloatPredicate = C.LLVMRealPredicateTrue +) + +//------------------------------------------------------------------------- +// llvm.LandingPadClause +//------------------------------------------------------------------------- + +const ( + LandingPadCatch LandingPadClause = C.LLVMLandingPadCatch + LandingPadFilter LandingPadClause = C.LLVMLandingPadFilter +) + +//------------------------------------------------------------------------- +// llvm.Context +//------------------------------------------------------------------------- + +func NewContext() Context { return Context{C.LLVMContextCreate()} } +func GlobalContext() Context { return Context{C.LLVMGetGlobalContext()} } +func (c Context) Dispose() { C.LLVMContextDispose(c.C) } + +func (c Context) MDKindID(name string) (id int) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + id = int(C.LLVMGetMDKindIDInContext(c.C, cname, C.unsigned(len(name)))) + return +} + +func MDKindID(name string) (id int) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + id = int(C.LLVMGetMDKindID(cname, C.unsigned(len(name)))) + return +} + +//------------------------------------------------------------------------- +// llvm.Module +//------------------------------------------------------------------------- + +// Create and destroy modules. +// See llvm::Module::Module. +func NewModule(name string) (m Module) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + m.C = C.LLVMModuleCreateWithName(cname) + return +} + +func (c Context) NewModule(name string) (m Module) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + m.C = C.LLVMModuleCreateWithNameInContext(cname, c.C) + return +} + +// See llvm::Module::~Module +func (m Module) Dispose() { C.LLVMDisposeModule(m.C) } + +// Data layout. See Module::getDataLayout. +func (m Module) DataLayout() string { + clayout := C.LLVMGetDataLayout(m.C) + return C.GoString(clayout) +} + +func (m Module) SetDataLayout(layout string) { + clayout := C.CString(layout) + defer C.free(unsafe.Pointer(clayout)) + C.LLVMSetDataLayout(m.C, clayout) +} + +// Target triple. See Module::getTargetTriple. +func (m Module) Target() string { + ctarget := C.LLVMGetTarget(m.C) + return C.GoString(ctarget) +} +func (m Module) SetTarget(target string) { + ctarget := C.CString(target) + defer C.free(unsafe.Pointer(ctarget)) + C.LLVMSetTarget(m.C, ctarget) +} + +func (m Module) GetTypeByName(name string) (t Type) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + t.C = C.LLVMGetTypeByName(m.C, cname) + return +} + +// See Module::dump. +func (m Module) Dump() { + C.LLVMDumpModule(m.C) +} + +func (m Module) String() string { + cir := C.LLVMPrintModuleToString(m.C) + defer C.free(unsafe.Pointer(cir)) + ir := C.GoString(cir) + return ir +} + +// See Module::setModuleInlineAsm. +func (m Module) SetInlineAsm(asm string) { + casm := C.CString(asm) + defer C.free(unsafe.Pointer(casm)) + C.LLVMSetModuleInlineAsm(m.C, casm) +} + +func (m Module) AddNamedMetadataOperand(name string, operand Metadata) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMAddNamedMetadataOperand2(m.C, cname, operand.C) +} + +func (m Module) Context() (c Context) { + c.C = C.LLVMGetModuleContext(m.C) + return +} + +//------------------------------------------------------------------------- +// llvm.Type +//------------------------------------------------------------------------- + +// LLVM types conform to the following hierarchy: +// +// types: +// integer type +// real type +// function type +// sequence types: +// array type +// pointer type +// vector type +// void type +// label type +// opaque type + +// See llvm::LLVMTypeKind::getTypeID. +func (t Type) TypeKind() TypeKind { return TypeKind(C.LLVMGetTypeKind(t.C)) } + +// See llvm::LLVMType::getContext. +func (t Type) Context() (c Context) { + c.C = C.LLVMGetTypeContext(t.C) + return +} + +// Operations on integer types +func (c Context) Int1Type() (t Type) { t.C = C.LLVMInt1TypeInContext(c.C); return } +func (c Context) Int8Type() (t Type) { t.C = C.LLVMInt8TypeInContext(c.C); return } +func (c Context) Int16Type() (t Type) { t.C = C.LLVMInt16TypeInContext(c.C); return } +func (c Context) Int32Type() (t Type) { t.C = C.LLVMInt32TypeInContext(c.C); return } +func (c Context) Int64Type() (t Type) { t.C = C.LLVMInt64TypeInContext(c.C); return } +func (c Context) IntType(numbits int) (t Type) { + t.C = C.LLVMIntTypeInContext(c.C, C.unsigned(numbits)) + return +} + +func Int1Type() (t Type) { t.C = C.LLVMInt1Type(); return } +func Int8Type() (t Type) { t.C = C.LLVMInt8Type(); return } +func Int16Type() (t Type) { t.C = C.LLVMInt16Type(); return } +func Int32Type() (t Type) { t.C = C.LLVMInt32Type(); return } +func Int64Type() (t Type) { t.C = C.LLVMInt64Type(); return } + +func IntType(numbits int) (t Type) { + t.C = C.LLVMIntType(C.unsigned(numbits)) + return +} + +func (t Type) IntTypeWidth() int { + return int(C.LLVMGetIntTypeWidth(t.C)) +} + +// Operations on real types +func (c Context) FloatType() (t Type) { t.C = C.LLVMFloatTypeInContext(c.C); return } +func (c Context) DoubleType() (t Type) { t.C = C.LLVMDoubleTypeInContext(c.C); return } +func (c Context) X86FP80Type() (t Type) { t.C = C.LLVMX86FP80TypeInContext(c.C); return } +func (c Context) FP128Type() (t Type) { t.C = C.LLVMFP128TypeInContext(c.C); return } +func (c Context) PPCFP128Type() (t Type) { t.C = C.LLVMPPCFP128TypeInContext(c.C); return } + +func FloatType() (t Type) { t.C = C.LLVMFloatType(); return } +func DoubleType() (t Type) { t.C = C.LLVMDoubleType(); return } +func X86FP80Type() (t Type) { t.C = C.LLVMX86FP80Type(); return } +func FP128Type() (t Type) { t.C = C.LLVMFP128Type(); return } +func PPCFP128Type() (t Type) { t.C = C.LLVMPPCFP128Type(); return } + +// Operations on function types +func FunctionType(returnType Type, paramTypes []Type, isVarArg bool) (t Type) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(paramTypes) > 0 { + pt = llvmTypeRefPtr(¶mTypes[0]) + ptlen = C.unsigned(len(paramTypes)) + } + t.C = C.LLVMFunctionType(returnType.C, + pt, + ptlen, + boolToLLVMBool(isVarArg)) + return +} + +func (t Type) IsFunctionVarArg() bool { return C.LLVMIsFunctionVarArg(t.C) != 0 } +func (t Type) ReturnType() (rt Type) { rt.C = C.LLVMGetReturnType(t.C); return } +func (t Type) ParamTypesCount() int { return int(C.LLVMCountParamTypes(t.C)) } +func (t Type) ParamTypes() []Type { + count := t.ParamTypesCount() + if count > 0 { + out := make([]Type, count) + C.LLVMGetParamTypes(t.C, llvmTypeRefPtr(&out[0])) + return out + } + return nil +} + +// Operations on struct types +func (c Context) StructType(elementTypes []Type, packed bool) (t Type) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(elementTypes) > 0 { + pt = llvmTypeRefPtr(&elementTypes[0]) + ptlen = C.unsigned(len(elementTypes)) + } + t.C = C.LLVMStructTypeInContext(c.C, + pt, + ptlen, + boolToLLVMBool(packed)) + return +} + +func StructType(elementTypes []Type, packed bool) (t Type) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(elementTypes) > 0 { + pt = llvmTypeRefPtr(&elementTypes[0]) + ptlen = C.unsigned(len(elementTypes)) + } + t.C = C.LLVMStructType(pt, ptlen, boolToLLVMBool(packed)) + return +} + +func (c Context) StructCreateNamed(name string) (t Type) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + t.C = C.LLVMStructCreateNamed(c.C, cname) + return +} + +func (t Type) StructName() string { + return C.GoString(C.LLVMGetStructName(t.C)) +} + +func (t Type) StructSetBody(elementTypes []Type, packed bool) { + var pt *C.LLVMTypeRef + var ptlen C.unsigned + if len(elementTypes) > 0 { + pt = llvmTypeRefPtr(&elementTypes[0]) + ptlen = C.unsigned(len(elementTypes)) + } + C.LLVMStructSetBody(t.C, pt, ptlen, boolToLLVMBool(packed)) +} + +func (t Type) IsStructPacked() bool { return C.LLVMIsPackedStruct(t.C) != 0 } +func (t Type) StructElementTypesCount() int { return int(C.LLVMCountStructElementTypes(t.C)) } +func (t Type) StructElementTypes() []Type { + out := make([]Type, t.StructElementTypesCount()) + if len(out) > 0 { + C.LLVMGetStructElementTypes(t.C, llvmTypeRefPtr(&out[0])) + } + return out +} + +// Operations on array, pointer, and vector types (sequence types) +func ArrayType(elementType Type, elementCount int) (t Type) { + t.C = C.LLVMArrayType(elementType.C, C.unsigned(elementCount)) + return +} +func PointerType(elementType Type, addressSpace int) (t Type) { + t.C = C.LLVMPointerType(elementType.C, C.unsigned(addressSpace)) + return +} +func VectorType(elementType Type, elementCount int) (t Type) { + t.C = C.LLVMVectorType(elementType.C, C.unsigned(elementCount)) + return +} + +func (t Type) ElementType() (rt Type) { rt.C = C.LLVMGetElementType(t.C); return } +func (t Type) ArrayLength() int { return int(C.LLVMGetArrayLength(t.C)) } +func (t Type) PointerAddressSpace() int { return int(C.LLVMGetPointerAddressSpace(t.C)) } +func (t Type) VectorSize() int { return int(C.LLVMGetVectorSize(t.C)) } + +// Operations on other types +func (c Context) VoidType() (t Type) { t.C = C.LLVMVoidTypeInContext(c.C); return } +func (c Context) LabelType() (t Type) { t.C = C.LLVMLabelTypeInContext(c.C); return } + +func VoidType() (t Type) { t.C = C.LLVMVoidType(); return } +func LabelType() (t Type) { t.C = C.LLVMLabelType(); return } + +//------------------------------------------------------------------------- +// llvm.Value +//------------------------------------------------------------------------- + +// Operations on all values +func (v Value) Type() (t Type) { t.C = C.LLVMTypeOf(v.C); return } +func (v Value) Name() string { return C.GoString(C.LLVMGetValueName(v.C)) } +func (v Value) SetName(name string) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMSetValueName(v.C, cname) +} +func (v Value) Dump() { C.LLVMDumpValue(v.C) } +func (v Value) ReplaceAllUsesWith(nv Value) { C.LLVMReplaceAllUsesWith(v.C, nv.C) } +func (v Value) HasMetadata() bool { return C.LLVMHasMetadata(v.C) != 0 } +func (v Value) Metadata(kind int) (rv Value) { + rv.C = C.LLVMGetMetadata(v.C, C.unsigned(kind)) + return +} +func (v Value) SetMetadata(kind int, node Metadata) { + C.LLVMSetMetadata2(v.C, C.unsigned(kind), node.C) +} + +// Conversion functions. +// Return the input value if it is an instance of the specified class, otherwise NULL. +// See llvm::dyn_cast_or_null<>. +func (v Value) IsAArgument() (rv Value) { rv.C = C.LLVMIsAArgument(v.C); return } +func (v Value) IsABasicBlock() (rv Value) { rv.C = C.LLVMIsABasicBlock(v.C); return } +func (v Value) IsAInlineAsm() (rv Value) { rv.C = C.LLVMIsAInlineAsm(v.C); return } +func (v Value) IsAUser() (rv Value) { rv.C = C.LLVMIsAUser(v.C); return } +func (v Value) IsAConstant() (rv Value) { rv.C = C.LLVMIsAConstant(v.C); return } +func (v Value) IsAConstantAggregateZero() (rv Value) { + rv.C = C.LLVMIsAConstantAggregateZero(v.C) + return +} +func (v Value) IsAConstantArray() (rv Value) { rv.C = C.LLVMIsAConstantArray(v.C); return } +func (v Value) IsAConstantExpr() (rv Value) { rv.C = C.LLVMIsAConstantExpr(v.C); return } +func (v Value) IsAConstantFP() (rv Value) { rv.C = C.LLVMIsAConstantFP(v.C); return } +func (v Value) IsAConstantInt() (rv Value) { rv.C = C.LLVMIsAConstantInt(v.C); return } +func (v Value) IsAConstantPointerNull() (rv Value) { rv.C = C.LLVMIsAConstantPointerNull(v.C); return } +func (v Value) IsAConstantStruct() (rv Value) { rv.C = C.LLVMIsAConstantStruct(v.C); return } +func (v Value) IsAConstantVector() (rv Value) { rv.C = C.LLVMIsAConstantVector(v.C); return } +func (v Value) IsAGlobalValue() (rv Value) { rv.C = C.LLVMIsAGlobalValue(v.C); return } +func (v Value) IsAFunction() (rv Value) { rv.C = C.LLVMIsAFunction(v.C); return } +func (v Value) IsAGlobalAlias() (rv Value) { rv.C = C.LLVMIsAGlobalAlias(v.C); return } +func (v Value) IsAGlobalVariable() (rv Value) { rv.C = C.LLVMIsAGlobalVariable(v.C); return } +func (v Value) IsAUndefValue() (rv Value) { rv.C = C.LLVMIsAUndefValue(v.C); return } +func (v Value) IsAInstruction() (rv Value) { rv.C = C.LLVMIsAInstruction(v.C); return } +func (v Value) IsABinaryOperator() (rv Value) { rv.C = C.LLVMIsABinaryOperator(v.C); return } +func (v Value) IsACallInst() (rv Value) { rv.C = C.LLVMIsACallInst(v.C); return } +func (v Value) IsAIntrinsicInst() (rv Value) { rv.C = C.LLVMIsAIntrinsicInst(v.C); return } +func (v Value) IsADbgInfoIntrinsic() (rv Value) { rv.C = C.LLVMIsADbgInfoIntrinsic(v.C); return } +func (v Value) IsADbgDeclareInst() (rv Value) { rv.C = C.LLVMIsADbgDeclareInst(v.C); return } +func (v Value) IsAMemIntrinsic() (rv Value) { rv.C = C.LLVMIsAMemIntrinsic(v.C); return } +func (v Value) IsAMemCpyInst() (rv Value) { rv.C = C.LLVMIsAMemCpyInst(v.C); return } +func (v Value) IsAMemMoveInst() (rv Value) { rv.C = C.LLVMIsAMemMoveInst(v.C); return } +func (v Value) IsAMemSetInst() (rv Value) { rv.C = C.LLVMIsAMemSetInst(v.C); return } +func (v Value) IsACmpInst() (rv Value) { rv.C = C.LLVMIsACmpInst(v.C); return } +func (v Value) IsAFCmpInst() (rv Value) { rv.C = C.LLVMIsAFCmpInst(v.C); return } +func (v Value) IsAICmpInst() (rv Value) { rv.C = C.LLVMIsAICmpInst(v.C); return } +func (v Value) IsAExtractElementInst() (rv Value) { rv.C = C.LLVMIsAExtractElementInst(v.C); return } +func (v Value) IsAGetElementPtrInst() (rv Value) { rv.C = C.LLVMIsAGetElementPtrInst(v.C); return } +func (v Value) IsAInsertElementInst() (rv Value) { rv.C = C.LLVMIsAInsertElementInst(v.C); return } +func (v Value) IsAInsertValueInst() (rv Value) { rv.C = C.LLVMIsAInsertValueInst(v.C); return } +func (v Value) IsAPHINode() (rv Value) { rv.C = C.LLVMIsAPHINode(v.C); return } +func (v Value) IsASelectInst() (rv Value) { rv.C = C.LLVMIsASelectInst(v.C); return } +func (v Value) IsAShuffleVectorInst() (rv Value) { rv.C = C.LLVMIsAShuffleVectorInst(v.C); return } +func (v Value) IsAStoreInst() (rv Value) { rv.C = C.LLVMIsAStoreInst(v.C); return } +func (v Value) IsATerminatorInst() (rv Value) { rv.C = C.LLVMIsATerminatorInst(v.C); return } +func (v Value) IsABranchInst() (rv Value) { rv.C = C.LLVMIsABranchInst(v.C); return } +func (v Value) IsAInvokeInst() (rv Value) { rv.C = C.LLVMIsAInvokeInst(v.C); return } +func (v Value) IsAReturnInst() (rv Value) { rv.C = C.LLVMIsAReturnInst(v.C); return } +func (v Value) IsASwitchInst() (rv Value) { rv.C = C.LLVMIsASwitchInst(v.C); return } +func (v Value) IsAUnreachableInst() (rv Value) { rv.C = C.LLVMIsAUnreachableInst(v.C); return } +func (v Value) IsAUnaryInstruction() (rv Value) { rv.C = C.LLVMIsAUnaryInstruction(v.C); return } +func (v Value) IsAAllocaInst() (rv Value) { rv.C = C.LLVMIsAAllocaInst(v.C); return } +func (v Value) IsACastInst() (rv Value) { rv.C = C.LLVMIsACastInst(v.C); return } +func (v Value) IsABitCastInst() (rv Value) { rv.C = C.LLVMIsABitCastInst(v.C); return } +func (v Value) IsAFPExtInst() (rv Value) { rv.C = C.LLVMIsAFPExtInst(v.C); return } +func (v Value) IsAFPToSIInst() (rv Value) { rv.C = C.LLVMIsAFPToSIInst(v.C); return } +func (v Value) IsAFPToUIInst() (rv Value) { rv.C = C.LLVMIsAFPToUIInst(v.C); return } +func (v Value) IsAFPTruncInst() (rv Value) { rv.C = C.LLVMIsAFPTruncInst(v.C); return } +func (v Value) IsAIntToPtrInst() (rv Value) { rv.C = C.LLVMIsAIntToPtrInst(v.C); return } +func (v Value) IsAPtrToIntInst() (rv Value) { rv.C = C.LLVMIsAPtrToIntInst(v.C); return } +func (v Value) IsASExtInst() (rv Value) { rv.C = C.LLVMIsASExtInst(v.C); return } +func (v Value) IsASIToFPInst() (rv Value) { rv.C = C.LLVMIsASIToFPInst(v.C); return } +func (v Value) IsATruncInst() (rv Value) { rv.C = C.LLVMIsATruncInst(v.C); return } +func (v Value) IsAUIToFPInst() (rv Value) { rv.C = C.LLVMIsAUIToFPInst(v.C); return } +func (v Value) IsAZExtInst() (rv Value) { rv.C = C.LLVMIsAZExtInst(v.C); return } +func (v Value) IsAExtractValueInst() (rv Value) { rv.C = C.LLVMIsAExtractValueInst(v.C); return } +func (v Value) IsALoadInst() (rv Value) { rv.C = C.LLVMIsALoadInst(v.C); return } +func (v Value) IsAVAArgInst() (rv Value) { rv.C = C.LLVMIsAVAArgInst(v.C); return } + +// Operations on Uses +func (v Value) FirstUse() (u Use) { u.C = C.LLVMGetFirstUse(v.C); return } +func (u Use) NextUse() (ru Use) { ru.C = C.LLVMGetNextUse(u.C); return } +func (u Use) User() (v Value) { v.C = C.LLVMGetUser(u.C); return } +func (u Use) UsedValue() (v Value) { v.C = C.LLVMGetUsedValue(u.C); return } + +// Operations on Users +func (v Value) Operand(i int) (rv Value) { rv.C = C.LLVMGetOperand(v.C, C.unsigned(i)); return } +func (v Value) SetOperand(i int, op Value) { C.LLVMSetOperand(v.C, C.unsigned(i), op.C) } +func (v Value) OperandsCount() int { return int(C.LLVMGetNumOperands(v.C)) } + +// Operations on constants of any type +func ConstNull(t Type) (v Value) { v.C = C.LLVMConstNull(t.C); return } +func ConstAllOnes(t Type) (v Value) { v.C = C.LLVMConstAllOnes(t.C); return } +func Undef(t Type) (v Value) { v.C = C.LLVMGetUndef(t.C); return } +func (v Value) IsConstant() bool { return C.LLVMIsConstant(v.C) != 0 } +func (v Value) IsNull() bool { return C.LLVMIsNull(v.C) != 0 } +func (v Value) IsUndef() bool { return C.LLVMIsUndef(v.C) != 0 } +func ConstPointerNull(t Type) (v Value) { v.C = C.LLVMConstPointerNull(t.C); return } + +// Operations on metadata +func (c Context) MDString(str string) (md Metadata) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + md.C = C.LLVMMDString2(c.C, cstr, C.unsigned(len(str))) + return +} +func (c Context) MDNode(mds []Metadata) (md Metadata) { + ptr, nvals := llvmMetadataRefs(mds) + md.C = C.LLVMMDNode2(c.C, ptr, nvals) + return +} +func (c Context) TemporaryMDNode(mds []Metadata) (md Metadata) { + ptr, nvals := llvmMetadataRefs(mds) + md.C = C.LLVMTemporaryMDNode(c.C, ptr, nvals) + return +} +func (v Value) ConstantAsMetadata() (md Metadata) { + md.C = C.LLVMConstantAsMetadata(v.C) + return +} + +// Operations on scalar constants +func ConstInt(t Type, n uint64, signExtend bool) (v Value) { + v.C = C.LLVMConstInt(t.C, + C.ulonglong(n), + boolToLLVMBool(signExtend)) + return +} +func ConstIntFromString(t Type, str string, radix int) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstIntOfString(t.C, cstr, C.uint8_t(radix)) + return +} +func ConstFloat(t Type, n float64) (v Value) { + v.C = C.LLVMConstReal(t.C, C.double(n)) + return +} +func ConstFloatFromString(t Type, str string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstRealOfString(t.C, cstr) + return +} + +func (v Value) ZExtValue() uint64 { return uint64(C.LLVMConstIntGetZExtValue(v.C)) } +func (v Value) SExtValue() int64 { return int64(C.LLVMConstIntGetSExtValue(v.C)) } + +// Operations on composite constants +func (c Context) ConstString(str string, addnull bool) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstStringInContext(c.C, cstr, + C.unsigned(len(str)), boolToLLVMBool(!addnull)) + return +} +func (c Context) ConstStruct(constVals []Value, packed bool) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstStructInContext(c.C, ptr, nvals, + boolToLLVMBool(packed)) + return +} +func ConstNamedStruct(t Type, constVals []Value) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstNamedStruct(t.C, ptr, nvals) + return +} +func ConstString(str string, addnull bool) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + v.C = C.LLVMConstString(cstr, + C.unsigned(len(str)), boolToLLVMBool(!addnull)) + return +} +func ConstArray(t Type, constVals []Value) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstArray(t.C, ptr, nvals) + return +} +func ConstStruct(constVals []Value, packed bool) (v Value) { + ptr, nvals := llvmValueRefs(constVals) + v.C = C.LLVMConstStruct(ptr, nvals, boolToLLVMBool(packed)) + return +} +func ConstVector(scalarConstVals []Value, packed bool) (v Value) { + ptr, nvals := llvmValueRefs(scalarConstVals) + v.C = C.LLVMConstVector(ptr, nvals) + return +} + +// Constant expressions +func (v Value) Opcode() Opcode { return Opcode(C.LLVMGetConstOpcode(v.C)) } +func (v Value) InstructionOpcode() Opcode { return Opcode(C.LLVMGetInstructionOpcode(v.C)) } +func AlignOf(t Type) (v Value) { v.C = C.LLVMAlignOf(t.C); return } +func SizeOf(t Type) (v Value) { v.C = C.LLVMSizeOf(t.C); return } +func ConstNeg(v Value) (rv Value) { rv.C = C.LLVMConstNeg(v.C); return } +func ConstNSWNeg(v Value) (rv Value) { rv.C = C.LLVMConstNSWNeg(v.C); return } +func ConstNUWNeg(v Value) (rv Value) { rv.C = C.LLVMConstNUWNeg(v.C); return } +func ConstFNeg(v Value) (rv Value) { rv.C = C.LLVMConstFNeg(v.C); return } +func ConstNot(v Value) (rv Value) { rv.C = C.LLVMConstNot(v.C); return } +func ConstAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstAdd(lhs.C, rhs.C); return } +func ConstNSWAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNSWAdd(lhs.C, rhs.C); return } +func ConstNUWAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNUWAdd(lhs.C, rhs.C); return } +func ConstFAdd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFAdd(lhs.C, rhs.C); return } +func ConstSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstSub(lhs.C, rhs.C); return } +func ConstNSWSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNSWSub(lhs.C, rhs.C); return } +func ConstNUWSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNUWSub(lhs.C, rhs.C); return } +func ConstFSub(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFSub(lhs.C, rhs.C); return } +func ConstMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstMul(lhs.C, rhs.C); return } +func ConstNSWMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNSWMul(lhs.C, rhs.C); return } +func ConstNUWMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstNUWMul(lhs.C, rhs.C); return } +func ConstFMul(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFMul(lhs.C, rhs.C); return } +func ConstUDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstUDiv(lhs.C, rhs.C); return } +func ConstSDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstSDiv(lhs.C, rhs.C); return } +func ConstExactSDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstExactSDiv(lhs.C, rhs.C); return } +func ConstFDiv(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFDiv(lhs.C, rhs.C); return } +func ConstURem(lhs, rhs Value) (v Value) { v.C = C.LLVMConstURem(lhs.C, rhs.C); return } +func ConstSRem(lhs, rhs Value) (v Value) { v.C = C.LLVMConstSRem(lhs.C, rhs.C); return } +func ConstFRem(lhs, rhs Value) (v Value) { v.C = C.LLVMConstFRem(lhs.C, rhs.C); return } +func ConstAnd(lhs, rhs Value) (v Value) { v.C = C.LLVMConstAnd(lhs.C, rhs.C); return } +func ConstOr(lhs, rhs Value) (v Value) { v.C = C.LLVMConstOr(lhs.C, rhs.C); return } +func ConstXor(lhs, rhs Value) (v Value) { v.C = C.LLVMConstXor(lhs.C, rhs.C); return } + +func ConstICmp(pred IntPredicate, lhs, rhs Value) (v Value) { + v.C = C.LLVMConstICmp(C.LLVMIntPredicate(pred), lhs.C, rhs.C) + return +} +func ConstFCmp(pred FloatPredicate, lhs, rhs Value) (v Value) { + v.C = C.LLVMConstFCmp(C.LLVMRealPredicate(pred), lhs.C, rhs.C) + return +} + +func ConstShl(lhs, rhs Value) (v Value) { v.C = C.LLVMConstShl(lhs.C, rhs.C); return } +func ConstLShr(lhs, rhs Value) (v Value) { v.C = C.LLVMConstLShr(lhs.C, rhs.C); return } +func ConstAShr(lhs, rhs Value) (v Value) { v.C = C.LLVMConstAShr(lhs.C, rhs.C); return } + +func ConstGEP(v Value, indices []Value) (rv Value) { + ptr, nvals := llvmValueRefs(indices) + rv.C = C.LLVMConstGEP(v.C, ptr, nvals) + return +} +func ConstInBoundsGEP(v Value, indices []Value) (rv Value) { + ptr, nvals := llvmValueRefs(indices) + rv.C = C.LLVMConstInBoundsGEP(v.C, ptr, nvals) + return +} +func ConstTrunc(v Value, t Type) (rv Value) { rv.C = C.LLVMConstTrunc(v.C, t.C); return } +func ConstSExt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstSExt(v.C, t.C); return } +func ConstZExt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstZExt(v.C, t.C); return } +func ConstFPTrunc(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPTrunc(v.C, t.C); return } +func ConstFPExt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPExt(v.C, t.C); return } +func ConstUIToFP(v Value, t Type) (rv Value) { rv.C = C.LLVMConstUIToFP(v.C, t.C); return } +func ConstSIToFP(v Value, t Type) (rv Value) { rv.C = C.LLVMConstSIToFP(v.C, t.C); return } +func ConstFPToUI(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPToUI(v.C, t.C); return } +func ConstFPToSI(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPToSI(v.C, t.C); return } +func ConstPtrToInt(v Value, t Type) (rv Value) { rv.C = C.LLVMConstPtrToInt(v.C, t.C); return } +func ConstIntToPtr(v Value, t Type) (rv Value) { rv.C = C.LLVMConstIntToPtr(v.C, t.C); return } +func ConstBitCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstBitCast(v.C, t.C); return } +func ConstZExtOrBitCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstZExtOrBitCast(v.C, t.C); return } +func ConstSExtOrBitCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstSExtOrBitCast(v.C, t.C); return } +func ConstTruncOrBitCast(v Value, t Type) (rv Value) { + rv.C = C.LLVMConstTruncOrBitCast(v.C, t.C) + return +} +func ConstPointerCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstPointerCast(v.C, t.C); return } +func ConstIntCast(v Value, t Type, signed bool) (rv Value) { + rv.C = C.LLVMConstIntCast(v.C, t.C, boolToLLVMBool(signed)) + return +} +func ConstFPCast(v Value, t Type) (rv Value) { rv.C = C.LLVMConstFPCast(v.C, t.C); return } +func ConstSelect(cond, iftrue, iffalse Value) (rv Value) { + rv.C = C.LLVMConstSelect(cond.C, iftrue.C, iffalse.C) + return +} +func ConstExtractElement(vec, i Value) (rv Value) { + rv.C = C.LLVMConstExtractElement(vec.C, i.C) + return +} +func ConstInsertElement(vec, elem, i Value) (rv Value) { + rv.C = C.LLVMConstInsertElement(vec.C, elem.C, i.C) + return +} +func ConstShuffleVector(veca, vecb, mask Value) (rv Value) { + rv.C = C.LLVMConstShuffleVector(veca.C, vecb.C, mask.C) + return +} + +//TODO +//LLVMValueRef LLVMConstExtractValue(LLVMValueRef AggConstant, unsigned *IdxList, +// unsigned NumIdx); + +func ConstExtractValue(agg Value, indices []uint32) (rv Value) { + n := len(indices) + if n == 0 { + panic("one or more indices are required") + } + ptr := (*C.unsigned)(&indices[0]) + rv.C = C.LLVMConstExtractValue(agg.C, ptr, C.unsigned(n)) + return +} + +func ConstInsertValue(agg, val Value, indices []uint32) (rv Value) { + n := len(indices) + if n == 0 { + panic("one or more indices are required") + } + ptr := (*C.unsigned)(&indices[0]) + rv.C = C.LLVMConstInsertValue(agg.C, val.C, ptr, C.unsigned(n)) + return +} + +func BlockAddress(f Value, bb BasicBlock) (v Value) { + v.C = C.LLVMBlockAddress(f.C, bb.C) + return +} + +// Operations on global variables, functions, and aliases (globals) +func (v Value) GlobalParent() (m Module) { m.C = C.LLVMGetGlobalParent(v.C); return } +func (v Value) IsDeclaration() bool { return C.LLVMIsDeclaration(v.C) != 0 } +func (v Value) Linkage() Linkage { return Linkage(C.LLVMGetLinkage(v.C)) } +func (v Value) SetLinkage(l Linkage) { C.LLVMSetLinkage(v.C, C.LLVMLinkage(l)) } +func (v Value) Section() string { return C.GoString(C.LLVMGetSection(v.C)) } +func (v Value) SetSection(str string) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + C.LLVMSetSection(v.C, cstr) +} +func (v Value) Visibility() Visibility { return Visibility(C.LLVMGetVisibility(v.C)) } +func (v Value) SetVisibility(vi Visibility) { C.LLVMSetVisibility(v.C, C.LLVMVisibility(vi)) } +func (v Value) Alignment() int { return int(C.LLVMGetAlignment(v.C)) } +func (v Value) SetAlignment(a int) { C.LLVMSetAlignment(v.C, C.unsigned(a)) } +func (v Value) SetUnnamedAddr(ua bool) { C.LLVMSetUnnamedAddr(v.C, boolToLLVMBool(ua)) } + +// Operations on global variables +func AddGlobal(m Module, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddGlobal(m.C, t.C, cname) + return +} +func AddGlobalInAddressSpace(m Module, t Type, name string, addressSpace int) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddGlobalInAddressSpace(m.C, t.C, cname, C.unsigned(addressSpace)) + return +} +func (m Module) NamedGlobal(name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMGetNamedGlobal(m.C, cname) + return +} + +func (m Module) FirstGlobal() (v Value) { v.C = C.LLVMGetFirstGlobal(m.C); return } +func (m Module) LastGlobal() (v Value) { v.C = C.LLVMGetLastGlobal(m.C); return } +func NextGlobal(v Value) (rv Value) { rv.C = C.LLVMGetNextGlobal(v.C); return } +func PrevGlobal(v Value) (rv Value) { rv.C = C.LLVMGetPreviousGlobal(v.C); return } +func (v Value) EraseFromParentAsGlobal() { C.LLVMDeleteGlobal(v.C) } +func (v Value) Initializer() (rv Value) { rv.C = C.LLVMGetInitializer(v.C); return } +func (v Value) SetInitializer(cv Value) { C.LLVMSetInitializer(v.C, cv.C) } +func (v Value) IsThreadLocal() bool { return C.LLVMIsThreadLocal(v.C) != 0 } +func (v Value) SetThreadLocal(tl bool) { C.LLVMSetThreadLocal(v.C, boolToLLVMBool(tl)) } +func (v Value) IsGlobalConstant() bool { return C.LLVMIsGlobalConstant(v.C) != 0 } +func (v Value) SetGlobalConstant(gc bool) { C.LLVMSetGlobalConstant(v.C, boolToLLVMBool(gc)) } + +// Operations on aliases +func AddAlias(m Module, t Type, aliasee Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddAlias(m.C, t.C, aliasee.C, cname) + return +} + +// Operations on functions +func AddFunction(m Module, name string, ft Type) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMAddFunction(m.C, cname, ft.C) + return +} + +func (m Module) NamedFunction(name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMGetNamedFunction(m.C, cname) + return +} + +func (m Module) FirstFunction() (v Value) { v.C = C.LLVMGetFirstFunction(m.C); return } +func (m Module) LastFunction() (v Value) { v.C = C.LLVMGetLastFunction(m.C); return } +func NextFunction(v Value) (rv Value) { rv.C = C.LLVMGetNextFunction(v.C); return } +func PrevFunction(v Value) (rv Value) { rv.C = C.LLVMGetPreviousFunction(v.C); return } +func (v Value) EraseFromParentAsFunction() { C.LLVMDeleteFunction(v.C) } +func (v Value) IntrinsicID() int { return int(C.LLVMGetIntrinsicID(v.C)) } +func (v Value) FunctionCallConv() CallConv { + return CallConv(C.LLVMCallConv(C.LLVMGetFunctionCallConv(v.C))) +} +func (v Value) SetFunctionCallConv(cc CallConv) { C.LLVMSetFunctionCallConv(v.C, C.unsigned(cc)) } +func (v Value) GC() string { return C.GoString(C.LLVMGetGC(v.C)) } +func (v Value) SetGC(name string) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMSetGC(v.C, cname) +} +func (v Value) AddFunctionAttr(a Attribute) { C.LLVMAddFunctionAttr2(v.C, C.uint64_t(a)) } +func (v Value) FunctionAttr() Attribute { return Attribute(C.LLVMGetFunctionAttr2(v.C)) } +func (v Value) RemoveFunctionAttr(a Attribute) { C.LLVMRemoveFunctionAttr2(v.C, C.uint64_t(a)) } +func (v Value) AddTargetDependentFunctionAttr(attr, value string) { + cattr := C.CString(attr) + defer C.free(unsafe.Pointer(cattr)) + cvalue := C.CString(value) + defer C.free(unsafe.Pointer(cvalue)) + C.LLVMAddTargetDependentFunctionAttr(v.C, cattr, cvalue) +} + +// Operations on parameters +func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) } +func (v Value) Params() []Value { + out := make([]Value, v.ParamsCount()) + if len(out) > 0 { + C.LLVMGetParams(v.C, llvmValueRefPtr(&out[0])) + } + return out +} +func (v Value) Param(i int) (rv Value) { rv.C = C.LLVMGetParam(v.C, C.unsigned(i)); return } +func (v Value) ParamParent() (rv Value) { rv.C = C.LLVMGetParamParent(v.C); return } +func (v Value) FirstParam() (rv Value) { rv.C = C.LLVMGetFirstParam(v.C); return } +func (v Value) LastParam() (rv Value) { rv.C = C.LLVMGetLastParam(v.C); return } +func NextParam(v Value) (rv Value) { rv.C = C.LLVMGetNextParam(v.C); return } +func PrevParam(v Value) (rv Value) { rv.C = C.LLVMGetPreviousParam(v.C); return } +func (v Value) AddAttribute(a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMAddAttribute(v.C, C.LLVMAttribute(a)) +} +func (v Value) RemoveAttribute(a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMRemoveAttribute(v.C, C.LLVMAttribute(a)) +} +func (v Value) Attribute() Attribute { return Attribute(C.LLVMGetAttribute(v.C)) } +func (v Value) SetParamAlignment(align int) { C.LLVMSetParamAlignment(v.C, C.unsigned(align)) } + +// Operations on basic blocks +func (bb BasicBlock) AsValue() (v Value) { v.C = C.LLVMBasicBlockAsValue(bb.C); return } +func (v Value) IsBasicBlock() bool { return C.LLVMValueIsBasicBlock(v.C) != 0 } +func (v Value) AsBasicBlock() (bb BasicBlock) { bb.C = C.LLVMValueAsBasicBlock(v.C); return } +func (bb BasicBlock) Parent() (v Value) { v.C = C.LLVMGetBasicBlockParent(bb.C); return } +func (v Value) BasicBlocksCount() int { return int(C.LLVMCountBasicBlocks(v.C)) } +func (v Value) BasicBlocks() []BasicBlock { + out := make([]BasicBlock, v.BasicBlocksCount()) + C.LLVMGetBasicBlocks(v.C, llvmBasicBlockRefPtr(&out[0])) + return out +} +func (v Value) FirstBasicBlock() (bb BasicBlock) { bb.C = C.LLVMGetFirstBasicBlock(v.C); return } +func (v Value) LastBasicBlock() (bb BasicBlock) { bb.C = C.LLVMGetLastBasicBlock(v.C); return } +func NextBasicBlock(bb BasicBlock) (rbb BasicBlock) { rbb.C = C.LLVMGetNextBasicBlock(bb.C); return } +func PrevBasicBlock(bb BasicBlock) (rbb BasicBlock) { rbb.C = C.LLVMGetPreviousBasicBlock(bb.C); return } +func (v Value) EntryBasicBlock() (bb BasicBlock) { bb.C = C.LLVMGetEntryBasicBlock(v.C); return } +func (c Context) AddBasicBlock(f Value, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMAppendBasicBlockInContext(c.C, f.C, cname) + return +} +func (c Context) InsertBasicBlock(ref BasicBlock, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMInsertBasicBlockInContext(c.C, ref.C, cname) + return +} +func AddBasicBlock(f Value, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMAppendBasicBlock(f.C, cname) + return +} +func InsertBasicBlock(ref BasicBlock, name string) (bb BasicBlock) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + bb.C = C.LLVMInsertBasicBlock(ref.C, cname) + return +} +func (bb BasicBlock) EraseFromParent() { C.LLVMDeleteBasicBlock(bb.C) } +func (bb BasicBlock) MoveBefore(pos BasicBlock) { C.LLVMMoveBasicBlockBefore(bb.C, pos.C) } +func (bb BasicBlock) MoveAfter(pos BasicBlock) { C.LLVMMoveBasicBlockAfter(bb.C, pos.C) } + +// Operations on instructions +func (v Value) InstructionParent() (bb BasicBlock) { bb.C = C.LLVMGetInstructionParent(v.C); return } +func (bb BasicBlock) FirstInstruction() (v Value) { v.C = C.LLVMGetFirstInstruction(bb.C); return } +func (bb BasicBlock) LastInstruction() (v Value) { v.C = C.LLVMGetLastInstruction(bb.C); return } +func NextInstruction(v Value) (rv Value) { rv.C = C.LLVMGetNextInstruction(v.C); return } +func PrevInstruction(v Value) (rv Value) { rv.C = C.LLVMGetPreviousInstruction(v.C); return } + +// Operations on call sites +func (v Value) SetInstructionCallConv(cc CallConv) { + C.LLVMSetInstructionCallConv(v.C, C.unsigned(cc)) +} +func (v Value) InstructionCallConv() CallConv { + return CallConv(C.LLVMCallConv(C.LLVMGetInstructionCallConv(v.C))) +} +func (v Value) AddInstrAttribute(i int, a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMAddInstrAttribute(v.C, C.unsigned(i), C.LLVMAttribute(a)) +} +func (v Value) RemoveInstrAttribute(i int, a Attribute) { + if a >= 1<<32 { + panic("attribute value currently unsupported") + } + C.LLVMRemoveInstrAttribute(v.C, C.unsigned(i), C.LLVMAttribute(a)) +} +func (v Value) SetInstrParamAlignment(i int, align int) { + C.LLVMSetInstrParamAlignment(v.C, C.unsigned(i), C.unsigned(align)) +} + +// Operations on call instructions (only) +func (v Value) IsTailCall() bool { return C.LLVMIsTailCall(v.C) != 0 } +func (v Value) SetTailCall(is bool) { C.LLVMSetTailCall(v.C, boolToLLVMBool(is)) } + +// Operations on phi nodes +func (v Value) AddIncoming(vals []Value, blocks []BasicBlock) { + ptr, nvals := llvmValueRefs(vals) + C.LLVMAddIncoming(v.C, ptr, llvmBasicBlockRefPtr(&blocks[0]), nvals) +} +func (v Value) IncomingCount() int { return int(C.LLVMCountIncoming(v.C)) } +func (v Value) IncomingValue(i int) (rv Value) { + rv.C = C.LLVMGetIncomingValue(v.C, C.unsigned(i)) + return +} +func (v Value) IncomingBlock(i int) (bb BasicBlock) { + bb.C = C.LLVMGetIncomingBlock(v.C, C.unsigned(i)) + return +} + +//------------------------------------------------------------------------- +// llvm.Builder +//------------------------------------------------------------------------- + +// An instruction builder represents a point within a basic block, and is the +// exclusive means of building instructions using the C interface. + +func (c Context) NewBuilder() (b Builder) { b.C = C.LLVMCreateBuilderInContext(c.C); return } +func NewBuilder() (b Builder) { b.C = C.LLVMCreateBuilder(); return } +func (b Builder) SetInsertPoint(block BasicBlock, instr Value) { + C.LLVMPositionBuilder(b.C, block.C, instr.C) +} +func (b Builder) SetInsertPointBefore(instr Value) { C.LLVMPositionBuilderBefore(b.C, instr.C) } +func (b Builder) SetInsertPointAtEnd(block BasicBlock) { C.LLVMPositionBuilderAtEnd(b.C, block.C) } +func (b Builder) GetInsertBlock() (bb BasicBlock) { bb.C = C.LLVMGetInsertBlock(b.C); return } +func (b Builder) ClearInsertionPoint() { C.LLVMClearInsertionPosition(b.C) } +func (b Builder) Insert(instr Value) { C.LLVMInsertIntoBuilder(b.C, instr.C) } +func (b Builder) InsertWithName(instr Value, name string) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + C.LLVMInsertIntoBuilderWithName(b.C, instr.C, cname) +} +func (b Builder) Dispose() { C.LLVMDisposeBuilder(b.C) } + +// Metadata +func (b Builder) SetCurrentDebugLocation(line, col uint, scope, inlinedAt Metadata) { + C.LLVMSetCurrentDebugLocation2(b.C, C.unsigned(line), C.unsigned(col), scope.C, inlinedAt.C) +} +func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) } +func (b Builder) InsertDeclare(module Module, storage Value, md Value) Value { + f := module.NamedFunction("llvm.dbg.declare") + if f.IsNil() { + ftyp := FunctionType(VoidType(), []Type{storage.Type(), md.Type()}, false) + f = AddFunction(module, "llvm.dbg.declare", ftyp) + } + return b.CreateCall(f, []Value{storage, md}, "") +} + +// Terminators +func (b Builder) CreateRetVoid() (rv Value) { rv.C = C.LLVMBuildRetVoid(b.C); return } +func (b Builder) CreateRet(v Value) (rv Value) { rv.C = C.LLVMBuildRet(b.C, v.C); return } +func (b Builder) CreateAggregateRet(vs []Value) (rv Value) { + ptr, nvals := llvmValueRefs(vs) + rv.C = C.LLVMBuildAggregateRet(b.C, ptr, nvals) + return +} +func (b Builder) CreateBr(bb BasicBlock) (rv Value) { rv.C = C.LLVMBuildBr(b.C, bb.C); return } +func (b Builder) CreateCondBr(ifv Value, thenb, elseb BasicBlock) (rv Value) { + rv.C = C.LLVMBuildCondBr(b.C, ifv.C, thenb.C, elseb.C) + return +} +func (b Builder) CreateSwitch(v Value, elseb BasicBlock, numCases int) (rv Value) { + rv.C = C.LLVMBuildSwitch(b.C, v.C, elseb.C, C.unsigned(numCases)) + return +} +func (b Builder) CreateIndirectBr(addr Value, numDests int) (rv Value) { + rv.C = C.LLVMBuildIndirectBr(b.C, addr.C, C.unsigned(numDests)) + return +} +func (b Builder) CreateInvoke(fn Value, args []Value, then, catch BasicBlock, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(args) + rv.C = C.LLVMBuildInvoke(b.C, fn.C, ptr, nvals, then.C, catch.C, cname) + return +} +func (b Builder) CreateUnreachable() (rv Value) { rv.C = C.LLVMBuildUnreachable(b.C); return } + +// Add a case to the switch instruction +func (v Value) AddCase(on Value, dest BasicBlock) { C.LLVMAddCase(v.C, on.C, dest.C) } + +// Add a destination to the indirectbr instruction +func (v Value) AddDest(dest BasicBlock) { C.LLVMAddDestination(v.C, dest.C) } + +// Arithmetic +func (b Builder) CreateAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNSWAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNSWAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNUWAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNUWAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFAdd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFAdd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSub(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNSWSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNSWSub(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNUWSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNUWSub(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFSub(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + v.C = C.LLVMBuildFSub(b.C, lhs.C, rhs.C, cname) + C.free(unsafe.Pointer(cname)) + return +} +func (b Builder) CreateMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNSWMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNSWMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNUWMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildNUWMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFMul(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFMul(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateUDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildUDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateSDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateExactSDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildExactSDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFDiv(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFDiv(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateURem(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildURem(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateSRem(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSRem(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFRem(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFRem(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateShl(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildShl(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateLShr(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildLShr(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateAShr(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAShr(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateAnd(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAnd(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateOr(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildOr(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateXor(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildXor(b.C, lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateBinOp(op Opcode, lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildBinOp(b.C, C.LLVMOpcode(op), lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateNSWNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNSWNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateNUWNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNUWNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateFNeg(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildFNeg(b.C, v.C, cname) + return +} +func (b Builder) CreateNot(v Value, name string) (rv Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + rv.C = C.LLVMBuildNot(b.C, v.C, cname) + return +} + +// Memory + +func (b Builder) CreateMalloc(t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildMalloc(b.C, t.C, cname) + return +} +func (b Builder) CreateArrayMalloc(t Type, val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildArrayMalloc(b.C, t.C, val.C, cname) + return +} +func (b Builder) CreateAlloca(t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildAlloca(b.C, t.C, cname) + return +} +func (b Builder) CreateArrayAlloca(t Type, val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildArrayAlloca(b.C, t.C, val.C, cname) + return +} +func (b Builder) CreateFree(p Value) (v Value) { + v.C = C.LLVMBuildFree(b.C, p.C) + return +} +func (b Builder) CreateLoad(p Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildLoad(b.C, p.C, cname) + return +} +func (b Builder) CreateStore(val Value, p Value) (v Value) { + v.C = C.LLVMBuildStore(b.C, val.C, p.C) + return +} +func (b Builder) CreateGEP(p Value, indices []Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(indices) + v.C = C.LLVMBuildGEP(b.C, p.C, ptr, nvals, cname) + return +} +func (b Builder) CreateInBoundsGEP(p Value, indices []Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(indices) + v.C = C.LLVMBuildInBoundsGEP(b.C, p.C, ptr, nvals, cname) + return +} +func (b Builder) CreateStructGEP(p Value, i int, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildStructGEP(b.C, p.C, C.unsigned(i), cname) + return +} +func (b Builder) CreateGlobalString(str, name string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildGlobalString(b.C, cstr, cname) + return +} +func (b Builder) CreateGlobalStringPtr(str, name string) (v Value) { + cstr := C.CString(str) + defer C.free(unsafe.Pointer(cstr)) + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildGlobalStringPtr(b.C, cstr, cname) + return +} + +// Casts +func (b Builder) CreateTrunc(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildTrunc(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateZExt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildZExt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateSExt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSExt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPToUI(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPToUI(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPToSI(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPToSI(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateUIToFP(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildUIToFP(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateSIToFP(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSIToFP(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPTrunc(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPTrunc(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPExt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPExt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreatePtrToInt(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPtrToInt(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateIntToPtr(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIntToPtr(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateZExtOrBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildZExtOrBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateSExtOrBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSExtOrBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateTruncOrBitCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildTruncOrBitCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateCast(val Value, op Opcode, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildCast(b.C, C.LLVMOpcode(op), val.C, t.C, cname) + return +} // +func (b Builder) CreatePointerCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPointerCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateIntCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIntCast(b.C, val.C, t.C, cname) + return +} +func (b Builder) CreateFPCast(val Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFPCast(b.C, val.C, t.C, cname) + return +} + +// Comparisons +func (b Builder) CreateICmp(pred IntPredicate, lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildICmp(b.C, C.LLVMIntPredicate(pred), lhs.C, rhs.C, cname) + return +} +func (b Builder) CreateFCmp(pred FloatPredicate, lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildFCmp(b.C, C.LLVMRealPredicate(pred), lhs.C, rhs.C, cname) + return +} + +// Miscellaneous instructions +func (b Builder) CreatePHI(t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPhi(b.C, t.C, cname) + return +} +func (b Builder) CreateCall(fn Value, args []Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + ptr, nvals := llvmValueRefs(args) + v.C = C.LLVMBuildCall(b.C, fn.C, ptr, nvals, cname) + return +} + +func (b Builder) CreateSelect(ifv, thenv, elsev Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildSelect(b.C, ifv.C, thenv.C, elsev.C, cname) + return +} + +func (b Builder) CreateVAArg(list Value, t Type, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildVAArg(b.C, list.C, t.C, cname) + return +} +func (b Builder) CreateExtractElement(vec, i Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildExtractElement(b.C, vec.C, i.C, cname) + return +} +func (b Builder) CreateInsertElement(vec, elt, i Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildInsertElement(b.C, vec.C, elt.C, i.C, cname) + return +} +func (b Builder) CreateShuffleVector(v1, v2, mask Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildShuffleVector(b.C, v1.C, v2.C, mask.C, cname) + return +} +func (b Builder) CreateExtractValue(agg Value, i int, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildExtractValue(b.C, agg.C, C.unsigned(i), cname) + return +} +func (b Builder) CreateInsertValue(agg, elt Value, i int, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildInsertValue(b.C, agg.C, elt.C, C.unsigned(i), cname) + return +} + +func (b Builder) CreateIsNull(val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIsNull(b.C, val.C, cname) + return +} +func (b Builder) CreateIsNotNull(val Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildIsNotNull(b.C, val.C, cname) + return +} +func (b Builder) CreatePtrDiff(lhs, rhs Value, name string) (v Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + v.C = C.LLVMBuildPtrDiff(b.C, lhs.C, rhs.C, cname) + return +} + +func (b Builder) CreateLandingPad(t Type, personality Value, nclauses int, name string) (l Value) { + cname := C.CString(name) + defer C.free(unsafe.Pointer(cname)) + l.C = C.LLVMBuildLandingPad(b.C, t.C, personality.C, C.unsigned(nclauses), cname) + return l +} + +func (l Value) AddClause(v Value) { + C.LLVMAddClause(l.C, v.C) +} + +func (l Value) SetCleanup(cleanup bool) { + C.LLVMSetCleanup(l.C, boolToLLVMBool(cleanup)) +} + +func (b Builder) CreateResume(ex Value) (v Value) { + v.C = C.LLVMBuildResume(b.C, ex.C) + return +} + +//------------------------------------------------------------------------- +// llvm.ModuleProvider +//------------------------------------------------------------------------- + +// Changes the type of M so it can be passed to FunctionPassManagers and the +// JIT. They take ModuleProviders for historical reasons. +func NewModuleProviderForModule(m Module) (mp ModuleProvider) { + mp.C = C.LLVMCreateModuleProviderForExistingModule(m.C) + return +} + +// Destroys the module M. +func (mp ModuleProvider) Dispose() { C.LLVMDisposeModuleProvider(mp.C) } + +//------------------------------------------------------------------------- +// llvm.MemoryBuffer +//------------------------------------------------------------------------- + +func NewMemoryBufferFromFile(path string) (b MemoryBuffer, err error) { + var cmsg *C.char + cpath := C.CString(path) + defer C.free(unsafe.Pointer(cpath)) + fail := C.LLVMCreateMemoryBufferWithContentsOfFile(cpath, &b.C, &cmsg) + if fail != 0 { + b.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func NewMemoryBufferFromStdin() (b MemoryBuffer, err error) { + var cmsg *C.char + fail := C.LLVMCreateMemoryBufferWithSTDIN(&b.C, &cmsg) + if fail != 0 { + b.C = nil + err = errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + } + return +} + +func (b MemoryBuffer) Bytes() []byte { + cstart := C.LLVMGetBufferStart(b.C) + csize := C.LLVMGetBufferSize(b.C) + return C.GoBytes(unsafe.Pointer(cstart), C.int(csize)) +} + +func (b MemoryBuffer) Dispose() { C.LLVMDisposeMemoryBuffer(b.C) } + +//------------------------------------------------------------------------- +// llvm.PassManager +//------------------------------------------------------------------------- + +// Constructs a new whole-module pass pipeline. This type of pipeline is +// suitable for link-time optimization and whole-module transformations. +// See llvm::PassManager::PassManager. +func NewPassManager() (pm PassManager) { pm.C = C.LLVMCreatePassManager(); return } + +// Constructs a new function-by-function pass pipeline over the module +// provider. It does not take ownership of the module provider. This type of +// pipeline is suitable for code generation and JIT compilation tasks. +// See llvm::FunctionPassManager::FunctionPassManager. +func NewFunctionPassManagerForModule(m Module) (pm PassManager) { + pm.C = C.LLVMCreateFunctionPassManagerForModule(m.C) + return +} + +// Initializes, executes on the provided module, and finalizes all of the +// passes scheduled in the pass manager. Returns 1 if any of the passes +// modified the module, 0 otherwise. See llvm::PassManager::run(Module&). +func (pm PassManager) Run(m Module) bool { return C.LLVMRunPassManager(pm.C, m.C) != 0 } + +// Initializes all of the function passes scheduled in the function pass +// manager. Returns 1 if any of the passes modified the module, 0 otherwise. +// See llvm::FunctionPassManager::doInitialization. +func (pm PassManager) InitializeFunc() bool { return C.LLVMInitializeFunctionPassManager(pm.C) != 0 } + +// Executes all of the function passes scheduled in the function pass manager +// on the provided function. Returns 1 if any of the passes modified the +// function, false otherwise. +// See llvm::FunctionPassManager::run(Function&). +func (pm PassManager) RunFunc(f Value) bool { return C.LLVMRunFunctionPassManager(pm.C, f.C) != 0 } + +// Finalizes all of the function passes scheduled in in the function pass +// manager. Returns 1 if any of the passes modified the module, 0 otherwise. +// See llvm::FunctionPassManager::doFinalization. +func (pm PassManager) FinalizeFunc() bool { return C.LLVMFinalizeFunctionPassManager(pm.C) != 0 } + +// Frees the memory of a pass pipeline. For function pipelines, does not free +// the module provider. +// See llvm::PassManagerBase::~PassManagerBase. +func (pm PassManager) Dispose() { C.LLVMDisposePassManager(pm.C) } + +//------------------------------------------------------------------------- +// llvm.Metadata +//------------------------------------------------------------------------- + +func (md Metadata) ReplaceAllUsesWith(new Metadata) { + C.LLVMMetadataReplaceAllUsesWith(md.C, new.C) +} diff --git a/bindings/go/llvm/ir_test.go b/bindings/go/llvm/ir_test.go new file mode 100644 index 0000000..981c94a --- /dev/null +++ b/bindings/go/llvm/ir_test.go @@ -0,0 +1,95 @@ +//===- ir_test.go - Tests for ir ------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests bindings for the ir component. +// +//===----------------------------------------------------------------------===// + +package llvm + +import ( + "strings" + "testing" +) + +func testAttribute(t *testing.T, attr Attribute, name string) { + mod := NewModule("") + defer mod.Dispose() + + ftyp := FunctionType(VoidType(), nil, false) + fn := AddFunction(mod, "foo", ftyp) + + fn.AddFunctionAttr(attr) + newattr := fn.FunctionAttr() + if attr != newattr { + t.Errorf("got attribute mask %d, want %d", newattr, attr) + } + + text := mod.String() + if !strings.Contains(text, " "+name+" ") { + t.Errorf("expected attribute '%s', got:\n%s", name, text) + } + + fn.RemoveFunctionAttr(attr) + newattr = fn.FunctionAttr() + if newattr != 0 { + t.Errorf("got attribute mask %d, want 0", newattr) + } +} + +func TestAttributes(t *testing.T) { + // Tests that our attribute constants haven't drifted from LLVM's. + attrTests := []struct { + attr Attribute + name string + }{ + {SanitizeAddressAttribute, "sanitize_address"}, + {AlwaysInlineAttribute, "alwaysinline"}, + {BuiltinAttribute, "builtin"}, + {ByValAttribute, "byval"}, + {InAllocaAttribute, "inalloca"}, + {InlineHintAttribute, "inlinehint"}, + {InRegAttribute, "inreg"}, + {JumpTableAttribute, "jumptable"}, + {MinSizeAttribute, "minsize"}, + {NakedAttribute, "naked"}, + {NestAttribute, "nest"}, + {NoAliasAttribute, "noalias"}, + {NoBuiltinAttribute, "nobuiltin"}, + {NoCaptureAttribute, "nocapture"}, + {NoDuplicateAttribute, "noduplicate"}, + {NoImplicitFloatAttribute, "noimplicitfloat"}, + {NoInlineAttribute, "noinline"}, + {NonLazyBindAttribute, "nonlazybind"}, + {NonNullAttribute, "nonnull"}, + {NoRedZoneAttribute, "noredzone"}, + {NoReturnAttribute, "noreturn"}, + {NoUnwindAttribute, "nounwind"}, + {OptimizeNoneAttribute, "optnone"}, + {OptimizeForSizeAttribute, "optsize"}, + {ReadNoneAttribute, "readnone"}, + {ReadOnlyAttribute, "readonly"}, + {ReturnedAttribute, "returned"}, + {ReturnsTwiceAttribute, "returns_twice"}, + {SExtAttribute, "signext"}, + {StackProtectAttribute, "ssp"}, + {StackProtectReqAttribute, "sspreq"}, + {StackProtectStrongAttribute, "sspstrong"}, + {StructRetAttribute, "sret"}, + {SanitizeThreadAttribute, "sanitize_thread"}, + {SanitizeMemoryAttribute, "sanitize_memory"}, + {UWTableAttribute, "uwtable"}, + {ZExtAttribute, "zeroext"}, + {ColdAttribute, "cold"}, + } + + for _, a := range attrTests { + testAttribute(t, a.attr, a.name) + } +} diff --git a/bindings/go/llvm/linker.go b/bindings/go/llvm/linker.go new file mode 100644 index 0000000..64d794e --- /dev/null +++ b/bindings/go/llvm/linker.go @@ -0,0 +1,32 @@ +//===- linker.go - Bindings for linker ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the linker component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Linker.h" +#include +*/ +import "C" +import "errors" + +func LinkModules(Dest, Src Module) error { + var cmsg *C.char + failed := C.LLVMLinkModules(Dest.C, Src.C, 0, &cmsg) + if failed != 0 { + err := errors.New(C.GoString(cmsg)) + C.LLVMDisposeMessage(cmsg) + return err + } + return nil +} diff --git a/bindings/go/llvm/llvm_config.go.in b/bindings/go/llvm/llvm_config.go.in new file mode 100644 index 0000000..41854fa --- /dev/null +++ b/bindings/go/llvm/llvm_config.go.in @@ -0,0 +1,12 @@ +// +build !byollvm + +package llvm + +/* +#cgo CXXFLAGS: -std=c++11 +#cgo CPPFLAGS: @LLVM_CFLAGS@ +#cgo LDFLAGS: @LLVM_LDFLAGS@ +*/ +import "C" + +type (run_build_sh int) diff --git a/bindings/go/llvm/llvm_dep.go b/bindings/go/llvm/llvm_dep.go new file mode 100644 index 0000000..39b4675 --- /dev/null +++ b/bindings/go/llvm/llvm_dep.go @@ -0,0 +1,19 @@ +//===- llvm_dep.go - creates LLVM dependency ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file ensures that the LLVM libraries are built before using the +// bindings. +// +//===----------------------------------------------------------------------===// + +// +build !byollvm + +package llvm + +var _ run_build_sh diff --git a/bindings/go/llvm/string.go b/bindings/go/llvm/string.go new file mode 100644 index 0000000..bfe869d --- /dev/null +++ b/bindings/go/llvm/string.go @@ -0,0 +1,105 @@ +//===- string.go - Stringer implementation for Type -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the Stringer interface for the Type type. +// +//===----------------------------------------------------------------------===// + +package llvm + +import "fmt" + +func (t TypeKind) String() string { + switch t { + case VoidTypeKind: + return "VoidTypeKind" + case FloatTypeKind: + return "FloatTypeKind" + case DoubleTypeKind: + return "DoubleTypeKind" + case X86_FP80TypeKind: + return "X86_FP80TypeKind" + case FP128TypeKind: + return "FP128TypeKind" + case PPC_FP128TypeKind: + return "PPC_FP128TypeKind" + case LabelTypeKind: + return "LabelTypeKind" + case IntegerTypeKind: + return "IntegerTypeKind" + case FunctionTypeKind: + return "FunctionTypeKind" + case StructTypeKind: + return "StructTypeKind" + case ArrayTypeKind: + return "ArrayTypeKind" + case PointerTypeKind: + return "PointerTypeKind" + case VectorTypeKind: + return "VectorTypeKind" + case MetadataTypeKind: + return "MetadataTypeKind" + } + panic("unreachable") +} + +func (t Type) String() string { + ts := typeStringer{s: make(map[Type]string)} + return ts.typeString(t) +} + +type typeStringer struct { + s map[Type]string +} + +func (ts *typeStringer) typeString(t Type) string { + if s, ok := ts.s[t]; ok { + return s + } + + k := t.TypeKind() + s := k.String() + s = s[:len(s)-len("Kind")] + + switch k { + case ArrayTypeKind: + s += fmt.Sprintf("(%v[%v])", ts.typeString(t.ElementType()), t.ArrayLength()) + case PointerTypeKind: + s += fmt.Sprintf("(%v)", ts.typeString(t.ElementType())) + case FunctionTypeKind: + params := t.ParamTypes() + s += "(" + if len(params) > 0 { + s += fmt.Sprintf("%v", ts.typeString(params[0])) + for i := 1; i < len(params); i++ { + s += fmt.Sprintf(", %v", ts.typeString(params[i])) + } + } + s += fmt.Sprintf("):%v", ts.typeString(t.ReturnType())) + case StructTypeKind: + if name := t.StructName(); name != "" { + ts.s[t] = "%" + name + s = fmt.Sprintf("%%%s: %s", name, s) + } + etypes := t.StructElementTypes() + s += "(" + if n := len(etypes); n > 0 { + s += ts.typeString(etypes[0]) + for i := 1; i < n; i++ { + s += fmt.Sprintf(", %v", ts.typeString(etypes[i])) + } + } + s += ")" + case IntegerTypeKind: + s += fmt.Sprintf("(%d bits)", t.IntTypeWidth()) + } + + ts.s[t] = s + return s +} diff --git a/bindings/go/llvm/string_test.go b/bindings/go/llvm/string_test.go new file mode 100644 index 0000000..3008f3e --- /dev/null +++ b/bindings/go/llvm/string_test.go @@ -0,0 +1,28 @@ +//===- string_test.go - test Stringer implementation for Type -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file tests the Stringer interface for the Type type. +// +//===----------------------------------------------------------------------===// + +package llvm + +import ( + "testing" +) + +func TestStringRecursiveType(t *testing.T) { + ctx := NewContext() + defer ctx.Dispose() + s := ctx.StructCreateNamed("recursive") + s.StructSetBody([]Type{s, s}, false) + if str := s.String(); str != "%recursive: StructType(%recursive, %recursive)" { + t.Errorf("incorrect string result %q", str) + } +} diff --git a/bindings/go/llvm/support.go b/bindings/go/llvm/support.go new file mode 100644 index 0000000..6f20086 --- /dev/null +++ b/bindings/go/llvm/support.go @@ -0,0 +1,54 @@ +//===- support.go - Bindings for support ----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the support component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Support.h" +#include "SupportBindings.h" +#include +*/ +import "C" + +import ( + "errors" + "unsafe" +) + +// Loads a dynamic library such that it may be used as an LLVM plugin. +// See llvm::sys::DynamicLibrary::LoadLibraryPermanently. +func LoadLibraryPermanently(lib string) error { + var errstr *C.char + libstr := C.CString(lib) + defer C.free(unsafe.Pointer(libstr)) + C.LLVMLoadLibraryPermanently2(libstr, &errstr) + if errstr != nil { + err := errors.New(C.GoString(errstr)) + C.free(unsafe.Pointer(errstr)) + return err + } + return nil +} + +// Parse the given arguments using the LLVM command line parser. +// See llvm::cl::ParseCommandLineOptions. +func ParseCommandLineOptions(args []string, overview string) { + argstrs := make([]*C.char, len(args)) + for i, arg := range args { + argstrs[i] = C.CString(arg) + defer C.free(unsafe.Pointer(argstrs[i])) + } + overviewstr := C.CString(overview) + defer C.free(unsafe.Pointer(overviewstr)) + C.LLVMParseCommandLineOptions(C.int(len(args)), &argstrs[0], overviewstr) +} diff --git a/bindings/go/llvm/target.go b/bindings/go/llvm/target.go new file mode 100644 index 0000000..bd1d0f3 --- /dev/null +++ b/bindings/go/llvm/target.go @@ -0,0 +1,300 @@ +//===- target.go - Bindings for target ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the target component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Target.h" +#include "llvm-c/TargetMachine.h" +#include +*/ +import "C" +import "unsafe" +import "errors" + +type ( + TargetData struct { + C C.LLVMTargetDataRef + } + Target struct { + C C.LLVMTargetRef + } + TargetMachine struct { + C C.LLVMTargetMachineRef + } + ByteOrdering C.enum_LLVMByteOrdering + RelocMode C.LLVMRelocMode + CodeGenOptLevel C.LLVMCodeGenOptLevel + CodeGenFileType C.LLVMCodeGenFileType + CodeModel C.LLVMCodeModel +) + +const ( + BigEndian ByteOrdering = C.LLVMBigEndian + LittleEndian ByteOrdering = C.LLVMLittleEndian +) + +const ( + RelocDefault RelocMode = C.LLVMRelocDefault + RelocStatic RelocMode = C.LLVMRelocStatic + RelocPIC RelocMode = C.LLVMRelocPIC + RelocDynamicNoPic RelocMode = C.LLVMRelocDynamicNoPic +) + +const ( + CodeGenLevelNone CodeGenOptLevel = C.LLVMCodeGenLevelNone + CodeGenLevelLess CodeGenOptLevel = C.LLVMCodeGenLevelLess + CodeGenLevelDefault CodeGenOptLevel = C.LLVMCodeGenLevelDefault + CodeGenLevelAggressive CodeGenOptLevel = C.LLVMCodeGenLevelAggressive +) + +const ( + CodeModelDefault CodeModel = C.LLVMCodeModelDefault + CodeModelJITDefault CodeModel = C.LLVMCodeModelJITDefault + CodeModelSmall CodeModel = C.LLVMCodeModelSmall + CodeModelKernel CodeModel = C.LLVMCodeModelKernel + CodeModelMedium CodeModel = C.LLVMCodeModelMedium + CodeModelLarge CodeModel = C.LLVMCodeModelLarge +) + +const ( + AssemblyFile CodeGenFileType = C.LLVMAssemblyFile + ObjectFile CodeGenFileType = C.LLVMObjectFile +) + +// InitializeAllTargetInfos - The main program should call this function if it +// wants access to all available targets that LLVM is configured to support. +func InitializeAllTargetInfos() { C.LLVMInitializeAllTargetInfos() } + +// InitializeAllTargets - The main program should call this function if it wants +// to link in all available targets that LLVM is configured to support. +func InitializeAllTargets() { C.LLVMInitializeAllTargets() } + +func InitializeAllTargetMCs() { C.LLVMInitializeAllTargetMCs() } + +func InitializeAllAsmParsers() { C.LLVMInitializeAllAsmParsers() } + +func InitializeAllAsmPrinters() { C.LLVMInitializeAllAsmPrinters() } + +var initializeNativeTargetError = errors.New("Failed to initialize native target") + +// InitializeNativeTarget - The main program should call this function to +// initialize the native target corresponding to the host. This is useful +// for JIT applications to ensure that the target gets linked in correctly. +func InitializeNativeTarget() error { + fail := C.LLVMInitializeNativeTarget() + if fail != 0 { + return initializeNativeTargetError + } + return nil +} + +func InitializeNativeAsmPrinter() error { + fail := C.LLVMInitializeNativeAsmPrinter() + if fail != 0 { + return initializeNativeTargetError + } + return nil +} + +//------------------------------------------------------------------------- +// llvm.TargetData +//------------------------------------------------------------------------- + +// Creates target data from a target layout string. +// See the constructor llvm::TargetData::TargetData. +func NewTargetData(rep string) (td TargetData) { + crep := C.CString(rep) + defer C.free(unsafe.Pointer(crep)) + td.C = C.LLVMCreateTargetData(crep) + return +} + +// Adds target data information to a pass manager. This does not take ownership +// of the target data. +// See the method llvm::PassManagerBase::add. +func (pm PassManager) Add(td TargetData) { + C.LLVMAddTargetData(td.C, pm.C) +} + +// Converts target data to a target layout string. The string must be disposed +// with LLVMDisposeMessage. +// See the constructor llvm::TargetData::TargetData. +func (td TargetData) String() (s string) { + cmsg := C.LLVMCopyStringRepOfTargetData(td.C) + s = C.GoString(cmsg) + C.LLVMDisposeMessage(cmsg) + return +} + +// Returns the byte order of a target, either BigEndian or LittleEndian. +// See the method llvm::TargetData::isLittleEndian. +func (td TargetData) ByteOrder() ByteOrdering { return ByteOrdering(C.LLVMByteOrder(td.C)) } + +// Returns the pointer size in bytes for a target. +// See the method llvm::TargetData::getPointerSize. +func (td TargetData) PointerSize() int { return int(C.LLVMPointerSize(td.C)) } + +// Returns the integer type that is the same size as a pointer on a target. +// See the method llvm::TargetData::getIntPtrType. +func (td TargetData) IntPtrType() (t Type) { t.C = C.LLVMIntPtrType(td.C); return } + +// Computes the size of a type in bytes for a target. +// See the method llvm::TargetData::getTypeSizeInBits. +func (td TargetData) TypeSizeInBits(t Type) uint64 { + return uint64(C.LLVMSizeOfTypeInBits(td.C, t.C)) +} + +// Computes the storage size of a type in bytes for a target. +// See the method llvm::TargetData::getTypeStoreSize. +func (td TargetData) TypeStoreSize(t Type) uint64 { + return uint64(C.LLVMStoreSizeOfType(td.C, t.C)) +} + +// Computes the ABI size of a type in bytes for a target. +// See the method llvm::TargetData::getTypeAllocSize. +func (td TargetData) TypeAllocSize(t Type) uint64 { + return uint64(C.LLVMABISizeOfType(td.C, t.C)) +} + +// Computes the ABI alignment of a type in bytes for a target. +// See the method llvm::TargetData::getABITypeAlignment. +func (td TargetData) ABITypeAlignment(t Type) int { + return int(C.LLVMABIAlignmentOfType(td.C, t.C)) +} + +// Computes the call frame alignment of a type in bytes for a target. +// See the method llvm::TargetData::getCallFrameTypeAlignment. +func (td TargetData) CallFrameTypeAlignment(t Type) int { + return int(C.LLVMCallFrameAlignmentOfType(td.C, t.C)) +} + +// Computes the preferred alignment of a type in bytes for a target. +// See the method llvm::TargetData::getPrefTypeAlignment. +func (td TargetData) PrefTypeAlignment(t Type) int { + return int(C.LLVMPreferredAlignmentOfType(td.C, t.C)) +} + +// Computes the preferred alignment of a global variable in bytes for a target. +// See the method llvm::TargetData::getPreferredAlignment. +func (td TargetData) PreferredAlignment(g Value) int { + return int(C.LLVMPreferredAlignmentOfGlobal(td.C, g.C)) +} + +// Computes the structure element that contains the byte offset for a target. +// See the method llvm::StructLayout::getElementContainingOffset. +func (td TargetData) ElementContainingOffset(t Type, offset uint64) int { + return int(C.LLVMElementAtOffset(td.C, t.C, C.ulonglong(offset))) +} + +// Computes the byte offset of the indexed struct element for a target. +// See the method llvm::StructLayout::getElementOffset. +func (td TargetData) ElementOffset(t Type, element int) uint64 { + return uint64(C.LLVMOffsetOfElement(td.C, t.C, C.unsigned(element))) +} + +// Deallocates a TargetData. +// See the destructor llvm::TargetData::~TargetData. +func (td TargetData) Dispose() { C.LLVMDisposeTargetData(td.C) } + +//------------------------------------------------------------------------- +// llvm.Target +//------------------------------------------------------------------------- + +func FirstTarget() Target { + return Target{C.LLVMGetFirstTarget()} +} + +func (t Target) NextTarget() Target { + return Target{C.LLVMGetNextTarget(t.C)} +} + +func GetTargetFromTriple(triple string) (t Target, err error) { + var errstr *C.char + ctriple := C.CString(triple) + defer C.free(unsafe.Pointer(ctriple)) + fail := C.LLVMGetTargetFromTriple(ctriple, &t.C, &errstr) + if fail != 0 { + err = errors.New(C.GoString(errstr)) + C.free(unsafe.Pointer(errstr)) + } + return +} + +func (t Target) Name() string { + return C.GoString(C.LLVMGetTargetName(t.C)) +} + +func (t Target) Description() string { + return C.GoString(C.LLVMGetTargetDescription(t.C)) +} + +//------------------------------------------------------------------------- +// llvm.TargetMachine +//------------------------------------------------------------------------- + +// CreateTargetMachine creates a new TargetMachine. +func (t Target) CreateTargetMachine(Triple string, CPU string, Features string, + Level CodeGenOptLevel, Reloc RelocMode, + CodeModel CodeModel) (tm TargetMachine) { + cTriple := C.CString(Triple) + defer C.free(unsafe.Pointer(cTriple)) + cCPU := C.CString(CPU) + defer C.free(unsafe.Pointer(cCPU)) + cFeatures := C.CString(Features) + defer C.free(unsafe.Pointer(cFeatures)) + tm.C = C.LLVMCreateTargetMachine(t.C, cTriple, cCPU, cFeatures, + C.LLVMCodeGenOptLevel(Level), + C.LLVMRelocMode(Reloc), + C.LLVMCodeModel(CodeModel)) + return +} + +// Triple returns the triple describing the machine (arch-vendor-os). +func (tm TargetMachine) Triple() string { + cstr := C.LLVMGetTargetMachineTriple(tm.C) + return C.GoString(cstr) +} + +// TargetData returns the TargetData for the machine. +func (tm TargetMachine) TargetData() TargetData { + return TargetData{C.LLVMGetTargetMachineData(tm.C)} +} + +func (tm TargetMachine) EmitToMemoryBuffer(m Module, ft CodeGenFileType) (MemoryBuffer, error) { + var errstr *C.char + var mb MemoryBuffer + fail := C.LLVMTargetMachineEmitToMemoryBuffer(tm.C, m.C, C.LLVMCodeGenFileType(ft), &errstr, &mb.C) + if fail != 0 { + err := errors.New(C.GoString(errstr)) + C.free(unsafe.Pointer(errstr)) + return MemoryBuffer{}, err + } + return mb, nil +} + +func (tm TargetMachine) AddAnalysisPasses(pm PassManager) { + C.LLVMAddAnalysisPasses(tm.C, pm.C) +} + +// Dispose releases resources related to the TargetMachine. +func (tm TargetMachine) Dispose() { + C.LLVMDisposeTargetMachine(tm.C) +} + +func DefaultTargetTriple() (triple string) { + cTriple := C.LLVMGetDefaultTargetTriple() + defer C.free(unsafe.Pointer(cTriple)) + triple = C.GoString(cTriple) + return +} diff --git a/bindings/go/llvm/transforms_instrumentation.go b/bindings/go/llvm/transforms_instrumentation.go new file mode 100644 index 0000000..9b191b2 --- /dev/null +++ b/bindings/go/llvm/transforms_instrumentation.go @@ -0,0 +1,43 @@ +//===- transforms_instrumentation.go - Bindings for instrumentation -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the instrumentation component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "InstrumentationBindings.h" +#include +*/ +import "C" +import "unsafe" + +func (pm PassManager) AddAddressSanitizerFunctionPass() { + C.LLVMAddAddressSanitizerFunctionPass(pm.C) +} + +func (pm PassManager) AddAddressSanitizerModulePass() { + C.LLVMAddAddressSanitizerModulePass(pm.C) +} + +func (pm PassManager) AddThreadSanitizerPass() { + C.LLVMAddThreadSanitizerPass(pm.C) +} + +func (pm PassManager) AddMemorySanitizerPass() { + C.LLVMAddMemorySanitizerPass(pm.C) +} + +func (pm PassManager) AddDataFlowSanitizerPass(abilist string) { + cabilist := C.CString(abilist) + defer C.free(unsafe.Pointer(cabilist)) + C.LLVMAddDataFlowSanitizerPass(pm.C, cabilist) +} diff --git a/bindings/go/llvm/transforms_ipo.go b/bindings/go/llvm/transforms_ipo.go new file mode 100644 index 0000000..12d972b --- /dev/null +++ b/bindings/go/llvm/transforms_ipo.go @@ -0,0 +1,42 @@ +//===- transforms_ipo.go - Bindings for ipo -------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the ipo component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Transforms/IPO.h" +*/ +import "C" + +// helpers +func boolToUnsigned(b bool) C.unsigned { + if b { + return 1 + } + return 0 +} + +func (pm PassManager) AddArgumentPromotionPass() { C.LLVMAddArgumentPromotionPass(pm.C) } +func (pm PassManager) AddConstantMergePass() { C.LLVMAddConstantMergePass(pm.C) } +func (pm PassManager) AddDeadArgEliminationPass() { C.LLVMAddDeadArgEliminationPass(pm.C) } +func (pm PassManager) AddFunctionAttrsPass() { C.LLVMAddFunctionAttrsPass(pm.C) } +func (pm PassManager) AddFunctionInliningPass() { C.LLVMAddFunctionInliningPass(pm.C) } +func (pm PassManager) AddGlobalDCEPass() { C.LLVMAddGlobalDCEPass(pm.C) } +func (pm PassManager) AddGlobalOptimizerPass() { C.LLVMAddGlobalOptimizerPass(pm.C) } +func (pm PassManager) AddIPConstantPropagationPass() { C.LLVMAddIPConstantPropagationPass(pm.C) } +func (pm PassManager) AddPruneEHPass() { C.LLVMAddPruneEHPass(pm.C) } +func (pm PassManager) AddIPSCCPPass() { C.LLVMAddIPSCCPPass(pm.C) } +func (pm PassManager) AddInternalizePass(allButMain bool) { + C.LLVMAddInternalizePass(pm.C, boolToUnsigned(allButMain)) +} +func (pm PassManager) AddStripDeadPrototypesPass() { C.LLVMAddStripDeadPrototypesPass(pm.C) } diff --git a/bindings/go/llvm/transforms_pmbuilder.go b/bindings/go/llvm/transforms_pmbuilder.go new file mode 100644 index 0000000..3d79d6e --- /dev/null +++ b/bindings/go/llvm/transforms_pmbuilder.go @@ -0,0 +1,48 @@ +//===- transforms_pmbuilder.go - Bindings for PassManagerBuilder ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the PassManagerBuilder class. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Transforms/PassManagerBuilder.h" +*/ +import "C" + +type PassManagerBuilder struct { + C C.LLVMPassManagerBuilderRef +} + +func NewPassManagerBuilder() (pmb PassManagerBuilder) { + pmb.C = C.LLVMPassManagerBuilderCreate() + return +} + +func (pmb PassManagerBuilder) SetOptLevel(level int) { + C.LLVMPassManagerBuilderSetOptLevel(pmb.C, C.uint(level)) +} + +func (pmb PassManagerBuilder) SetSizeLevel(level int) { + C.LLVMPassManagerBuilderSetSizeLevel(pmb.C, C.uint(level)) +} + +func (pmb PassManagerBuilder) Populate(pm PassManager) { + C.LLVMPassManagerBuilderPopulateModulePassManager(pmb.C, pm.C) +} + +func (pmb PassManagerBuilder) PopulateFunc(pm PassManager) { + C.LLVMPassManagerBuilderPopulateFunctionPassManager(pmb.C, pm.C) +} + +func (pmb PassManagerBuilder) Dispose() { + C.LLVMPassManagerBuilderDispose(pmb.C) +} diff --git a/bindings/go/llvm/transforms_scalar.go b/bindings/go/llvm/transforms_scalar.go new file mode 100644 index 0000000..6492a85 --- /dev/null +++ b/bindings/go/llvm/transforms_scalar.go @@ -0,0 +1,45 @@ +//===- transforms_scalar.go - Bindings for scalaropts ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines bindings for the scalaropts component. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm-c/Transforms/Scalar.h" +*/ +import "C" + +func (pm PassManager) AddAggressiveDCEPass() { C.LLVMAddAggressiveDCEPass(pm.C) } +func (pm PassManager) AddCFGSimplificationPass() { C.LLVMAddCFGSimplificationPass(pm.C) } +func (pm PassManager) AddDeadStoreEliminationPass() { C.LLVMAddDeadStoreEliminationPass(pm.C) } +func (pm PassManager) AddGVNPass() { C.LLVMAddGVNPass(pm.C) } +func (pm PassManager) AddIndVarSimplifyPass() { C.LLVMAddIndVarSimplifyPass(pm.C) } +func (pm PassManager) AddInstructionCombiningPass() { C.LLVMAddInstructionCombiningPass(pm.C) } +func (pm PassManager) AddJumpThreadingPass() { C.LLVMAddJumpThreadingPass(pm.C) } +func (pm PassManager) AddLICMPass() { C.LLVMAddLICMPass(pm.C) } +func (pm PassManager) AddLoopDeletionPass() { C.LLVMAddLoopDeletionPass(pm.C) } +func (pm PassManager) AddLoopRotatePass() { C.LLVMAddLoopRotatePass(pm.C) } +func (pm PassManager) AddLoopUnrollPass() { C.LLVMAddLoopUnrollPass(pm.C) } +func (pm PassManager) AddLoopUnswitchPass() { C.LLVMAddLoopUnswitchPass(pm.C) } +func (pm PassManager) AddMemCpyOptPass() { C.LLVMAddMemCpyOptPass(pm.C) } +func (pm PassManager) AddPromoteMemoryToRegisterPass() { C.LLVMAddPromoteMemoryToRegisterPass(pm.C) } +func (pm PassManager) AddReassociatePass() { C.LLVMAddReassociatePass(pm.C) } +func (pm PassManager) AddSCCPPass() { C.LLVMAddSCCPPass(pm.C) } +func (pm PassManager) AddScalarReplAggregatesPass() { C.LLVMAddScalarReplAggregatesPass(pm.C) } +func (pm PassManager) AddScalarReplAggregatesPassWithThreshold(threshold int) { + C.LLVMAddScalarReplAggregatesPassWithThreshold(pm.C, C.int(threshold)) +} +func (pm PassManager) AddSimplifyLibCallsPass() { C.LLVMAddSimplifyLibCallsPass(pm.C) } +func (pm PassManager) AddTailCallEliminationPass() { C.LLVMAddTailCallEliminationPass(pm.C) } +func (pm PassManager) AddConstantPropagationPass() { C.LLVMAddConstantPropagationPass(pm.C) } +func (pm PassManager) AddDemoteMemoryToRegisterPass() { C.LLVMAddDemoteMemoryToRegisterPass(pm.C) } +func (pm PassManager) AddVerifierPass() { C.LLVMAddVerifierPass(pm.C) } diff --git a/bindings/go/llvm/version.go b/bindings/go/llvm/version.go new file mode 100644 index 0000000..d0623be --- /dev/null +++ b/bindings/go/llvm/version.go @@ -0,0 +1,21 @@ +//===- version.go - LLVM version info -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LLVM version information. +// +//===----------------------------------------------------------------------===// + +package llvm + +/* +#include "llvm/Config/llvm-config.h" +*/ +import "C" + +const Version = C.LLVM_VERSION_STRING diff --git a/bindings/ocaml/CMakeLists.txt b/bindings/ocaml/CMakeLists.txt new file mode 100644 index 0000000..2058368 --- /dev/null +++ b/bindings/ocaml/CMakeLists.txt @@ -0,0 +1,11 @@ +add_subdirectory(llvm) +add_subdirectory(all_backends) +add_subdirectory(analysis) +add_subdirectory(backends) +add_subdirectory(bitreader) +add_subdirectory(bitwriter) +add_subdirectory(irreader) +add_subdirectory(linker) +add_subdirectory(target) +add_subdirectory(transforms) +add_subdirectory(executionengine) diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile index b0e1f09..2005367 100644 --- a/bindings/ocaml/Makefile +++ b/bindings/ocaml/Makefile @@ -1,10 +1,10 @@ ##===- bindings/ocaml/Makefile -----------------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../.. diff --git a/bindings/ocaml/Makefile.ocaml b/bindings/ocaml/Makefile.ocaml index 1b964ee..1f65a7b 100644 --- a/bindings/ocaml/Makefile.ocaml +++ b/bindings/ocaml/Makefile.ocaml @@ -1,27 +1,30 @@ ##===- bindings/ocaml/Makefile.ocaml -----------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## -# +# # An OCaml library is a unique project type in the context of LLVM, so rules are # here rather than in Makefile.rules. -# +# # Reference materials on installing OCaml libraries: -# +# # https://fedoraproject.org/wiki/Packaging/OCaml # http://pkg-ocaml-maint.alioth.debian.org/ocaml_packaging_policy.txt -# +# ##===----------------------------------------------------------------------===## include $(LEVEL)/Makefile.config +# We have our own rules for building static libraries. +NO_BUILD_ARCHIVE = 1 + # CFLAGS needs to be set before Makefile.rules is included. -CXX.Flags += -I"$(shell $(OCAMLC) -where)" -C.Flags += -I"$(shell $(OCAMLC) -where)" +CXX.Flags += -I"$(shell $(OCAMLFIND) c -where)" +C.Flags += -I"$(shell $(OCAMLFIND) c -where)" ifeq ($(ENABLE_SHARED),1) LINK_COMPONENTS := all @@ -29,6 +32,12 @@ endif include $(LEVEL)/Makefile.common +# Used in out-of-tree builds of OCaml bindings only. +ifdef SYSTEM_LLVM_CONFIG +LLVM_CONFIG = $(SYSTEM_LLVM_CONFIG) +LLVMLibsOptions += $(shell $(LLVM_CONFIG) --ldflags) +endif + # Intentionally ignore PROJ_prefix here. We want the ocaml stdlib. However, the # user can override this with OCAML_LIBDIR or configure --with-ocaml-libdir=. PROJ_libocamldir := $(DESTDIR)$(OCAML_LIBDIR) @@ -50,64 +59,61 @@ endif # from toplevels. ifneq ($(ObjectsO),) ifeq ($(ENABLE_SHARED),1) -OCAMLSTUBS := 1 +OCAMLSTUBS := 1 +OCAMLSTUBFLAGS := $(patsubst %,-cclib %, $(LLVMLibsOptions) -l$(LIBRARYNAME)) endif endif +# Avoid the need for LD_LIBRARY_PATH +ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) +ifneq ($(HOST_OS),Darwin) +OCAMLRPATH := $(RPATH) -Wl,'$$ORIGIN/../../lib' +endif +endif + +# See http://caml.inria.fr/mantis/view.php?id=6642 +OCAMLORIGIN := -ccopt -L'$$CAMLORIGIN/..' \ + -ccopt $(RPATH) -ccopt -Wl,'$$CAMLORIGIN/..' + # Tools -OCAMLCFLAGS += -I $(ObjDir) -I $(OcamlDir) +OCAMLCFLAGS += -I $(OcamlDir) $(addprefix -package ,$(FindlibPackages)) + ifndef IS_CLEANING_TARGET ifneq ($(ObjectsO),) OCAMLAFLAGS += $(patsubst %,-cclib %, \ $(filter-out -L$(LibDir),-l$(LIBRARYNAME) \ $(shell $(LLVM_CONFIG) --ldflags)) \ - $(UsedLibs)) + $(UsedLibs) $(ExtraLibs)) else OCAMLAFLAGS += $(patsubst %,-cclib %, \ $(filter-out -L$(LibDir),$(shell $(LLVM_CONFIG) --ldflags)) \ - $(UsedLibs)) + $(UsedLibs) $(ExtraLibs)) endif endif - -# -g was introduced in 3.10.0. -#ifneq ($(ENABLE_OPTIMIZED),1) -# OCAMLDEBUGFLAG := -g -#endif - -Compile.CMI := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) -Compile.CMO := $(strip $(OCAMLC) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) -Compile.CMX := $(strip $(OCAMLOPT) -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) -ifdef OCAMLSTUBS -# Avoid the need for LD_LIBRARY_PATH -ifneq ($(HOST_OS), $(filter $(HOST_OS), Cygwin MingW)) -ifneq ($(HOST_OS),Darwin) -OCAMLRPATH := $(RPATH) -Wl,'$(SharedLibDir)' -endif -endif +ifneq ($(DEBUG_SYMBOLS),1) + OCAMLDEBUGFLAG := -g endif -ifdef OCAMLSTUBS -Archive.CMA := $(strip $(OCAMLC) -a -dllib -l$(LIBRARYNAME) $(OCAMLDEBUGFLAG) \ - -o) -else -Archive.CMA := $(strip $(OCAMLC) -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ - -o) -endif +Compile.CMI := $(strip $(OCAMLFIND) c -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMO := $(strip $(OCAMLFIND) c -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) +Compile.CMX := $(strip $(OCAMLFIND) opt -c $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG) -o) ifdef OCAMLSTUBS -Archive.CMXA := $(strip $(OCAMLOPT) -a $(patsubst %,-cclib %, \ - $(LLVMLibsOptions) -l$(LIBRARYNAME) \ - -L$(SharedLibDir) $(OCAMLRPATH)) \ - $(OCAMLDEBUGFLAG) -o) +# -dllib is engaged with ocamlc builds, $(OCAMLSTUBFLAGS) in ocamlc -custom builds. +Archive.CMA := $(strip $(OCAMLFIND) c -a -dllib -l$(LIBRARYNAME) $(OCAMLSTUBFLAGS) \ + $(OCAMLDEBUGFLAG) $(OCAMLORIGIN) -o) else -Archive.CMXA := $(strip $(OCAMLOPT) -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) -o) +Archive.CMA := $(strip $(OCAMLFIND) c -a -custom $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ + $(OCAMLORIGIN) -o) endif -ifdef OCAMLOPT -Archive.EXE := $(strip $(OCAMLOPT) -cc $(CXX) $(OCAMLCFLAGS) $(UsedOcamlLibs:%=%.cmxa) $(OCAMLDEBUGFLAG) -o) +ifdef OCAMLSTUBS +Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLSTUBFLAGS) $(OCAMLDEBUGFLAG) \ + $(OCAMLORIGIN) -o) else -Archive.EXE := $(strip $(OCAMLC) -cc $(CXX) $(OCAMLCFLAGS) $(OCAMLDEBUGFLAG:%=%.cma) -o) +Archive.CMXA := $(strip $(OCAMLFIND) opt -a $(OCAMLAFLAGS) $(OCAMLDEBUGFLAG) \ + $(OCAMLORIGIN) -o) endif # Source files @@ -191,7 +197,7 @@ $(ObjectsCMI): $(UsedOcamlInterfaces:%=$(OcamlDir)/%.cmi) ifdef LIBRARYNAME $(ObjDir)/$(LIBRARYNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ $(OcamlDir)/.dir $(ObjDir)/.dir - $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + $(Verb) $(OCAMLFIND) dep $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ -include $(ObjDir)/$(LIBRARYNAME).ocamldep endif @@ -199,7 +205,7 @@ endif ifdef TOOLNAME $(ObjDir)/$(TOOLNAME).ocamldep: $(OcamlSources) $(OcamlHeaders) \ $(OcamlDir)/.dir $(ObjDir)/.dir - $(Verb) $(OCAMLDEP) $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ + $(Verb) $(OCAMLFIND) dep $(OCAMLCFLAGS) $(OcamlSources) $(OcamlHeaders) > $@ -include $(ObjDir)/$(TOOLNAME).ocamldep endif @@ -225,7 +231,7 @@ install-a:: $(LibraryA) $(Echo) "Installing $(BuildMode) $(DestA)" $(Verb) $(MKDIR) $(PROJ_libocamldir) $(Verb) $(INSTALL) $(LibraryA) $(DestA) - $(Verb) + $(Verb) uninstall-a:: $(Echo) "Uninstalling $(DestA)" @@ -243,8 +249,8 @@ uninstall-local:: uninstall-shared $(SharedLib): $(ObjectsO) $(OcamlDir)/.dir $(Echo) "Building $(BuildMode) $(notdir $@)" - $(Verb) $(Link) $(SharedLinkOptions) $(OCAMLRPATH) $(LLVMLibsOptions) \ - -o $@ $(ObjectsO) + $(Verb) $(Link) $(SharedLinkOptions) $(OCAMLRPATH) -o $@ $(ObjectsO) \ + $(LLVMLibsOptions) clean-shared:: -$(Verb) $(RM) -f $(SharedLib) @@ -261,8 +267,9 @@ uninstall-shared:: endif -##===- Deposit dependent libraries adjacent to Ocaml libs -----------------===## +##===- Deposit dependent libraries adjacent to OCaml libs -----------------===## +ifndef SYSTEM_LLVM_CONFIG all-local:: build-deplibs clean-local:: clean-deplibs install-local:: install-deplibs @@ -287,7 +294,7 @@ install-deplibs: uninstall-deplibs: $(Verb) $(RM) -f $(DestLibs) - +endif ##===- Build ocaml interfaces (.mli's -> .cmi's) --------------------------===## @@ -368,8 +375,8 @@ endif ##===- Build optimized ocaml archive (.ml's -> .cmx's -> .cmxa, .a) -------===## # The ocamlopt compiler is supported on a set of targets disjoint from LLVM's. -# If unavailable, 'configure' will not define OCAMLOPT in Makefile.config. -ifdef OCAMLOPT +# If unavailable, 'configure' will set HAVE_OCAMLOPT to 0 in Makefile.config. +ifeq ($(HAVE_OCAMLOPT),1) $(OcamlDir)/%.cmx: $(ObjDir)/%.cmx $(Verb) $(CP) -f $< $@ @@ -419,31 +426,11 @@ uninstall-cmxa:: endif endif -##===- Build executables --------------------------------------------------===## - -ifdef TOOLNAME -all-local:: $(OutputEXE) -clean-local:: clean-exe - -$(OutputEXE): $(ToolEXE) $(OcamlDir)/.dir - $(Verb) $(CP) -f $< $@ - -ifndef OCAMLOPT -$(ToolEXE): $(ObjectsCMO) $(OcamlDir)/.dir - $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" - $(Verb) $(Archive.EXE) $@ $(ObjectsCMO) -else -$(ToolEXE): $(ObjectsCMX) $(OcamlDir)/.dir - $(Echo) "Archiving $(notdir $@) for $(BuildMode) build" - $(Verb) $(Archive.EXE) $@ $(ObjectsCMX) -endif -endif - ##===- Generate documentation ---------------------------------------------===## $(ObjDir)/$(LIBRARYNAME).odoc: $(ObjectsCMI) $(Echo) "Documenting $(notdir $@)" - $(Verb) $(OCAMLDOC) -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) + $(Verb) $(OCAMLFIND) doc -I $(ObjDir) -I $(OcamlDir) -dump $@ $(OcamlHeaders) ocamldoc: $(ObjDir)/$(LIBRARYNAME).odoc @@ -454,15 +441,17 @@ printcamlvars:: $(Echo) "LLVM_CONFIG : " '$(LLVM_CONFIG)' $(Echo) "OCAMLCFLAGS : " '$(OCAMLCFLAGS)' $(Echo) "OCAMLAFLAGS : " '$(OCAMLAFLAGS)' - $(Echo) "OCAMLC : " '$(OCAMLC)' - $(Echo) "OCAMLOPT : " '$(OCAMLOPT)' - $(Echo) "OCAMLDEP : " '$(OCAMLDEP)' + $(Echo) "OCAMLRPATH : " '$(OCAMLRPATH)' + $(Echo) "OCAMLSTUBS : " '$(OCAMLSTUBS)' + $(Echo) "OCAMLSTUBFLAGS : " '$(OCAMLSTUBFLAGS)' + $(Echo) "OCAMLFIND : " '$(OCAMLFIND)' $(Echo) "Compile.CMI : " '$(Compile.CMI)' $(Echo) "Compile.CMO : " '$(Compile.CMO)' $(Echo) "Archive.CMA : " '$(Archive.CMA)' $(Echo) "Compile.CMX : " '$(Compile.CMX)' $(Echo) "Archive.CMXA : " '$(Archive.CMXA)' $(Echo) "CAML_LIBDIR : " '$(CAML_LIBDIR)' + $(Echo) "LibraryA : " '$(LibraryA)' $(Echo) "LibraryCMA : " '$(LibraryCMA)' $(Echo) "LibraryCMXA : " '$(LibraryCMXA)' $(Echo) "SharedLib : " '$(SharedLib)' @@ -482,6 +471,7 @@ printcamlvars:: $(Echo) "DestSharedLib: " '$(DestSharedLib)' $(Echo) "UsedLibs : " '$(UsedLibs)' $(Echo) "UsedLibNames : " '$(UsedLibNames)' + $(Echo) "ExtraLibs : " '$(ExtraLibs)' .PHONY: printcamlvars build-cmis \ clean-a clean-cmis clean-cma clean-cmxa \ diff --git a/bindings/ocaml/all_backends/CMakeLists.txt b/bindings/ocaml/all_backends/CMakeLists.txt new file mode 100644 index 0000000..716a49c --- /dev/null +++ b/bindings/ocaml/all_backends/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_all_backends + OCAML llvm_all_backends + OCAMLDEP llvm + C all_backends_ocaml + LLVM ${LLVM_TARGETS_TO_BUILD}) diff --git a/bindings/ocaml/all_backends/Makefile b/bindings/ocaml/all_backends/Makefile index a5ff290..f7c8cdb 100644 --- a/bindings/ocaml/all_backends/Makefile +++ b/bindings/ocaml/all_backends/Makefile @@ -1,4 +1,4 @@ -##===- bindings/ocaml/all_backends/Makefile ----------------------*- Makefile -*-===## +##===- bindings/ocaml/all_backends/Makefile ----------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## # -# This is the makefile for the Objective Caml Llvm_backends interface. +# This is the makefile for the Objective Caml Llvm_all_backends interface. # ##===----------------------------------------------------------------------===## diff --git a/bindings/ocaml/analysis/CMakeLists.txt b/bindings/ocaml/analysis/CMakeLists.txt new file mode 100644 index 0000000..f8ca84d --- /dev/null +++ b/bindings/ocaml/analysis/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_analysis + OCAML llvm_analysis + OCAMLDEP llvm + C analysis_ocaml + LLVM analysis) diff --git a/bindings/ocaml/analysis/Makefile b/bindings/ocaml/analysis/Makefile index cbfcb24..daff061 100644 --- a/bindings/ocaml/analysis/Makefile +++ b/bindings/ocaml/analysis/Makefile @@ -1,14 +1,14 @@ ##===- bindings/ocaml/analysis/Makefile --------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## -# +# # This is the makefile for the Objective Caml Llvm_analysis interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. diff --git a/bindings/ocaml/analysis/analysis_ocaml.c b/bindings/ocaml/analysis/analysis_ocaml.c index 91be2d3..44e3197 100644 --- a/bindings/ocaml/analysis/analysis_ocaml.c +++ b/bindings/ocaml/analysis/analysis_ocaml.c @@ -20,15 +20,14 @@ #include "caml/mlvalues.h" #include "caml/memory.h" - /* Llvm.llmodule -> string option */ CAMLprim value llvm_verify_module(LLVMModuleRef M) { CAMLparam0(); CAMLlocal2(String, Option); - + char *Message; int Result = LLVMVerifyModule(M, LLVMReturnStatusAction, &Message); - + if (0 == Result) { Option = Val_int(0); } else { @@ -36,9 +35,9 @@ CAMLprim value llvm_verify_module(LLVMModuleRef M) { String = copy_string(Message); Store_field(Option, 0, String); } - + LLVMDisposeMessage(Message); - + CAMLreturn(Option); } diff --git a/bindings/ocaml/analysis/llvm_analysis.ml b/bindings/ocaml/analysis/llvm_analysis.ml index 21088ab..8c11a63 100644 --- a/bindings/ocaml/analysis/llvm_analysis.ml +++ b/bindings/ocaml/analysis/llvm_analysis.ml @@ -1,4 +1,4 @@ -(*===-- llvm_analysis.ml - LLVM OCaml Interface -----------------*- C++ -*-===* +(*===-- llvm_analysis.ml - LLVM OCaml Interface ---------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * diff --git a/bindings/ocaml/analysis/llvm_analysis.mli b/bindings/ocaml/analysis/llvm_analysis.mli index 1a0af02..03197cd 100644 --- a/bindings/ocaml/analysis/llvm_analysis.mli +++ b/bindings/ocaml/analysis/llvm_analysis.mli @@ -1,4 +1,4 @@ -(*===-- llvm_analysis.mli - LLVM OCaml Interface ----------------*- C++ -*-===* +(*===-- llvm_analysis.mli - LLVM OCaml Interface --------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * diff --git a/bindings/ocaml/backends/CMakeLists.txt b/bindings/ocaml/backends/CMakeLists.txt new file mode 100644 index 0000000..a980638 --- /dev/null +++ b/bindings/ocaml/backends/CMakeLists.txt @@ -0,0 +1,27 @@ +foreach(TARGET ${LLVM_TARGETS_TO_BUILD}) + set(OCAML_LLVM_TARGET ${TARGET}) + + foreach( ext ml mli ) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/llvm_backend.${ext}.in" + "${CMAKE_CURRENT_BINARY_DIR}/llvm_${TARGET}.${ext}") + endforeach() + + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/backend_ocaml.c" + "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_ocaml.c") + + add_ocaml_library(llvm_${TARGET} + OCAML llvm_${TARGET} + C ${TARGET}_ocaml + CFLAGS -DTARGET=${TARGET} + LLVM ${TARGET} + NOCOPY) + + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/META.llvm_backend.in" + "${LLVM_LIBRARY_DIR}/ocaml/META.llvm_${TARGET}") + + install(FILES "${LLVM_LIBRARY_DIR}/ocaml/META.llvm_${TARGET}" + DESTINATION lib/ocaml) +endforeach() diff --git a/bindings/ocaml/backends/META.llvm_backend.in b/bindings/ocaml/backends/META.llvm_backend.in index 0d4a6d6..6c1e8c4 100644 --- a/bindings/ocaml/backends/META.llvm_backend.in +++ b/bindings/ocaml/backends/META.llvm_backend.in @@ -5,4 +5,3 @@ requires = "llvm" archive(byte) = "llvm_@TARGET@.cma" archive(native) = "llvm_@TARGET@.cmxa" directory = "." -linkopts = "-ccopt -lstdc++" \ No newline at end of file diff --git a/bindings/ocaml/backends/backend_ocaml.c b/bindings/ocaml/backends/backend_ocaml.c index 2d4ba85..3e1a438 100644 --- a/bindings/ocaml/backends/backend_ocaml.c +++ b/bindings/ocaml/backends/backend_ocaml.c @@ -19,10 +19,11 @@ #include "caml/alloc.h" #include "caml/memory.h" -// TODO: Figure out how to call these only for targets which support them. -// LLVMInitialize ## target ## AsmPrinter(); -// LLVMInitialize ## target ## AsmParser(); -// LLVMInitialize ## target ## Disassembler(); +/* TODO: Figure out how to call these only for targets which support them. + * LLVMInitialize ## target ## AsmPrinter(); + * LLVMInitialize ## target ## AsmParser(); + * LLVMInitialize ## target ## Disassembler(); + */ #define INITIALIZER1(target) \ CAMLprim value llvm_initialize_ ## target(value Unit) { \ diff --git a/bindings/ocaml/bitreader/CMakeLists.txt b/bindings/ocaml/bitreader/CMakeLists.txt new file mode 100644 index 0000000..8d16103 --- /dev/null +++ b/bindings/ocaml/bitreader/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_bitreader + OCAML llvm_bitreader + OCAMLDEP llvm + C bitreader_ocaml + LLVM bitreader) diff --git a/bindings/ocaml/bitreader/Makefile b/bindings/ocaml/bitreader/Makefile index a1c7de8..dad4e1d 100644 --- a/bindings/ocaml/bitreader/Makefile +++ b/bindings/ocaml/bitreader/Makefile @@ -1,14 +1,14 @@ ##===- bindings/ocaml/bitreader/Makefile -------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## -# +# # This is the makefile for the Objective Caml Llvm_bitreader interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. diff --git a/bindings/ocaml/bitreader/bitreader_ocaml.c b/bindings/ocaml/bitreader/bitreader_ocaml.c index 0264e73..15ebd5f 100644 --- a/bindings/ocaml/bitreader/bitreader_ocaml.c +++ b/bindings/ocaml/bitreader/bitreader_ocaml.c @@ -16,58 +16,28 @@ #include "caml/alloc.h" #include "caml/fail.h" #include "caml/memory.h" +#include "caml/callback.h" - -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_bitreader_error_exn; - -CAMLprim value llvm_register_bitreader_exns(value Error) { - llvm_bitreader_error_exn = Field(Error, 0); - register_global_root(&llvm_bitreader_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - - -/*===-- Modules -----------------------------------------------------------===*/ +void llvm_raise(value Prototype, char *Message); /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ -CAMLprim value llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { - CAMLparam0(); - CAMLlocal2(Variant, MessageVal); - char *Message; - +CAMLprim LLVMModuleRef llvm_get_module(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { LLVMModuleRef M; + char *Message; + if (LLVMGetBitcodeModuleInContext(C, MemBuf, &M, &Message)) - llvm_raise(llvm_bitreader_error_exn, Message); - - CAMLreturn((value) M); + llvm_raise(*caml_named_value("Llvm_bitreader.Error"), Message); + + return M; } /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ -CAMLprim value llvm_parse_bitcode(LLVMContextRef C, - LLVMMemoryBufferRef MemBuf) { - CAMLparam0(); - CAMLlocal2(Variant, MessageVal); +CAMLprim LLVMModuleRef llvm_parse_bitcode(LLVMContextRef C, LLVMMemoryBufferRef MemBuf) { LLVMModuleRef M; char *Message; - + if (LLVMParseBitcodeInContext(C, MemBuf, &M, &Message)) - llvm_raise(llvm_bitreader_error_exn, Message); - - CAMLreturn((value) M); + llvm_raise(*caml_named_value("Llvm_bitreader.Error"), Message); + + return M; } diff --git a/bindings/ocaml/bitreader/llvm_bitreader.ml b/bindings/ocaml/bitreader/llvm_bitreader.ml index 865208c..b26efdd 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.ml +++ b/bindings/ocaml/bitreader/llvm_bitreader.ml @@ -1,4 +1,4 @@ -(*===-- llvm_bitreader.ml - LLVM OCaml Interface ----------------*- C++ -*-===* +(*===-- llvm_bitreader.ml - LLVM OCaml Interface --------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -7,14 +7,13 @@ * *===----------------------------------------------------------------------===*) - exception Error of string -external register_exns : exn -> unit = "llvm_register_bitreader_exns" -let _ = register_exns (Error "") - -external get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule - = "llvm_get_module" +let () = Callback.register_exception "Llvm_bitreader.Error" (Error "") -external parse_bitcode : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule - = "llvm_parse_bitcode" +external get_module + : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_get_module" +external parse_bitcode + : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule + = "llvm_parse_bitcode" diff --git a/bindings/ocaml/bitreader/llvm_bitreader.mli b/bindings/ocaml/bitreader/llvm_bitreader.mli index ff377b9..4351343 100644 --- a/bindings/ocaml/bitreader/llvm_bitreader.mli +++ b/bindings/ocaml/bitreader/llvm_bitreader.mli @@ -1,4 +1,4 @@ -(*===-- llvm_bitreader.mli - LLVM OCaml Interface ---------------*- C++ -*-===* +(*===-- llvm_bitreader.mli - LLVM OCaml Interface -------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -20,7 +20,6 @@ exception Error of string encountered. See the function [llvm::getBitcodeModule]. *) val get_module : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule - (** [parse_bitcode context mb] parses the bitcode for a new module [m] from the memory buffer [mb] in the context [context]. Returns [m] if successful, or raises [Error msg] otherwise, where [msg] is a description of the error diff --git a/bindings/ocaml/bitwriter/CMakeLists.txt b/bindings/ocaml/bitwriter/CMakeLists.txt new file mode 100644 index 0000000..5a14498 --- /dev/null +++ b/bindings/ocaml/bitwriter/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_bitwriter + OCAML llvm_bitwriter + OCAMLDEP llvm + C bitwriter_ocaml + LLVM bitwriter) diff --git a/bindings/ocaml/bitwriter/Makefile b/bindings/ocaml/bitwriter/Makefile index cec0a59..9f0b2c8 100644 --- a/bindings/ocaml/bitwriter/Makefile +++ b/bindings/ocaml/bitwriter/Makefile @@ -1,14 +1,14 @@ ##===- bindings/ocaml/bitwriter/Makefile -------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## -# +# # This is the makefile for the Objective Caml Llvm_bitwriter interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. diff --git a/bindings/ocaml/bitwriter/bitwriter_ocaml.c b/bindings/ocaml/bitwriter/bitwriter_ocaml.c index a47f700..04fd619 100644 --- a/bindings/ocaml/bitwriter/bitwriter_ocaml.c +++ b/bindings/ocaml/bitwriter/bitwriter_ocaml.c @@ -21,25 +21,28 @@ #include "caml/mlvalues.h" #include "caml/memory.h" -/*===-- Modules -----------------------------------------------------------===*/ - /* Llvm.llmodule -> string -> bool */ -CAMLprim value llvm_write_bitcode_file(value M, value Path) { - int res = LLVMWriteBitcodeToFile((LLVMModuleRef) M, String_val(Path)); - return Val_bool(res == 0); +CAMLprim value llvm_write_bitcode_file(LLVMModuleRef M, value Path) { + int Result = LLVMWriteBitcodeToFile(M, String_val(Path)); + return Val_bool(Result == 0); } /* ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool */ -CAMLprim value llvm_write_bitcode_to_fd(value U, value M, value FD) { +CAMLprim value llvm_write_bitcode_to_fd(value U, LLVMModuleRef M, value FD) { int Unbuffered; - int res; + int Result; if (U == Val_int(0)) { Unbuffered = 0; } else { - Unbuffered = Bool_val(Field(U,0)); + Unbuffered = Bool_val(Field(U, 0)); } - res = LLVMWriteBitcodeToFD((LLVMModuleRef) M, Int_val(FD), 0, Unbuffered); - return Val_bool(res == 0); + Result = LLVMWriteBitcodeToFD(M, Int_val(FD), 0, Unbuffered); + return Val_bool(Result == 0); +} + +/* Llvm.llmodule -> Llvm.llmemorybuffer */ +CAMLprim LLVMMemoryBufferRef llvm_write_bitcode_to_memory_buffer(LLVMModuleRef M) { + return LLVMWriteBitcodeToMemoryBuffer(M); } diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.ml b/bindings/ocaml/bitwriter/llvm_bitwriter.ml index fac8553..fca6efa 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.ml +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.ml @@ -1,4 +1,4 @@ -(*===-- llvm_bitwriter.ml - LLVM OCaml Interface ----------------*- C++ -*-===* +(*===-- llvm_bitwriter.ml - LLVM OCaml Interface --------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -12,14 +12,17 @@ * *===----------------------------------------------------------------------===*) +external write_bitcode_file + : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" -(* Writes the bitcode for module the given path. Returns true if successful. *) -external write_bitcode_file : Llvm.llmodule -> string -> bool - = "llvm_write_bitcode_file" +external write_bitcode_to_fd + : ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" -external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule - -> Unix.file_descr -> bool - = "llvm_write_bitcode_to_fd" +external write_bitcode_to_memory_buffer + : Llvm.llmodule -> Llvm.llmemorybuffer + = "llvm_write_bitcode_to_memory_buffer" let output_bitcode ?unbuffered channel m = write_bitcode_to_fd ?unbuffered m (Unix.descr_of_out_channel channel) diff --git a/bindings/ocaml/bitwriter/llvm_bitwriter.mli b/bindings/ocaml/bitwriter/llvm_bitwriter.mli index bb3e3b8..3d0f780 100644 --- a/bindings/ocaml/bitwriter/llvm_bitwriter.mli +++ b/bindings/ocaml/bitwriter/llvm_bitwriter.mli @@ -1,4 +1,4 @@ -(*===-- llvm_bitwriter.mli - LLVM OCaml Interface ---------------*- C++ -*-===* +(*===-- llvm_bitwriter.mli - LLVM OCaml Interface -------------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -14,15 +14,22 @@ (** [write_bitcode_file m path] writes the bitcode for module [m] to the file at [path]. Returns [true] if successful, [false] otherwise. *) -external write_bitcode_file : Llvm.llmodule -> string -> bool - = "llvm_write_bitcode_file" +external write_bitcode_file + : Llvm.llmodule -> string -> bool + = "llvm_write_bitcode_file" (** [write_bitcode_to_fd ~unbuffered fd m] writes the bitcode for module [m] to the channel [c]. If [unbuffered] is [true], after every write the fd will be flushed. Returns [true] if successful, [false] otherwise. *) -external write_bitcode_to_fd : ?unbuffered:bool -> Llvm.llmodule - -> Unix.file_descr -> bool - = "llvm_write_bitcode_to_fd" +external write_bitcode_to_fd + : ?unbuffered:bool -> Llvm.llmodule -> Unix.file_descr -> bool + = "llvm_write_bitcode_to_fd" + +(** [write_bitcode_to_memory_buffer m] returns a memory buffer containing + the bitcode for module [m]. *) +external write_bitcode_to_memory_buffer + : Llvm.llmodule -> Llvm.llmemorybuffer + = "llvm_write_bitcode_to_memory_buffer" (** [output_bitcode ~unbuffered c m] writes the bitcode for module [m] to the channel [c]. If [unbuffered] is [true], after every write the fd diff --git a/bindings/ocaml/executionengine/CMakeLists.txt b/bindings/ocaml/executionengine/CMakeLists.txt new file mode 100644 index 0000000..ae9af08 --- /dev/null +++ b/bindings/ocaml/executionengine/CMakeLists.txt @@ -0,0 +1,6 @@ +add_ocaml_library(llvm_executionengine + OCAML llvm_executionengine + OCAMLDEP llvm llvm_target + C executionengine_ocaml + LLVM executionengine mcjit native + PKG ctypes) diff --git a/bindings/ocaml/executionengine/Makefile b/bindings/ocaml/executionengine/Makefile index 5fa3f22..8b5d28f 100644 --- a/bindings/ocaml/executionengine/Makefile +++ b/bindings/ocaml/executionengine/Makefile @@ -1,19 +1,20 @@ -##===- bindings/ocaml/executionengine/Makefile --------------*- Makefile -*-===## -# +##===- bindings/ocaml/executionengine/Makefile -------------*- Makefile -*-===## +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## -# +# # This is the makefile for the Objective Caml Llvm_executionengine interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. LIBRARYNAME := llvm_executionengine -UsedComponents := executionengine jit interpreter native +UsedComponents := executionengine mcjit native UsedOcamlInterfaces := llvm llvm_target +FindlibPackages := ctypes include ../Makefile.ocaml diff --git a/bindings/ocaml/executionengine/executionengine_ocaml.c b/bindings/ocaml/executionengine/executionengine_ocaml.c index 4b44a91..b799250 100644 --- a/bindings/ocaml/executionengine/executionengine_ocaml.c +++ b/bindings/ocaml/executionengine/executionengine_ocaml.c @@ -15,189 +15,48 @@ |* *| \*===----------------------------------------------------------------------===*/ +#include +#include #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" #include "caml/alloc.h" #include "caml/custom.h" #include "caml/fail.h" #include "caml/memory.h" -#include -#include +#include "caml/callback.h" -/* Force the LLVM interpreter and JIT to be linked in. */ -void llvm_initialize(void) { - LLVMLinkInInterpreter(); - LLVMLinkInJIT(); -} +void llvm_raise(value Prototype, char *Message); /* unit -> bool */ -CAMLprim value llvm_initialize_native_target(value Unit) { - return Val_bool(LLVMInitializeNativeTarget()); -} - -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_ee_error_exn; - -CAMLprim value llvm_register_ee_exns(value Error) { - llvm_ee_error_exn = Field(Error, 0); - register_global_root(&llvm_ee_error_exn); - return Val_unit; -} +CAMLprim value llvm_ee_initialize(value Unit) { + LLVMLinkInMCJIT(); -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif + return Val_bool(!LLVMInitializeNativeTarget() && + !LLVMInitializeNativeAsmParser() && + !LLVMInitializeNativeAsmPrinter()); } - -/*--... Operations on generic values .......................................--*/ - -#define Genericvalue_val(v) (*(LLVMGenericValueRef *)(Data_custom_val(v))) - -static void llvm_finalize_generic_value(value GenVal) { - LLVMDisposeGenericValue(Genericvalue_val(GenVal)); -} - -static struct custom_operations generic_value_ops = { - (char *) "LLVMGenericValue", - llvm_finalize_generic_value, - custom_compare_default, - custom_hash_default, - custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif -}; - -static value alloc_generic_value(LLVMGenericValueRef Ref) { - value Val = alloc_custom(&generic_value_ops, sizeof(LLVMGenericValueRef), 0, 1); - Genericvalue_val(Val) = Ref; - return Val; -} - -/* Llvm.lltype -> float -> t */ -CAMLprim value llvm_genericvalue_of_float(LLVMTypeRef Ty, value N) { - CAMLparam1(N); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfFloat(Ty, Double_val(N)))); -} - -/* 'a -> t */ -CAMLprim value llvm_genericvalue_of_pointer(value V) { - CAMLparam1(V); - CAMLreturn(alloc_generic_value(LLVMCreateGenericValueOfPointer(Op_val(V)))); -} - -/* Llvm.lltype -> int -> t */ -CAMLprim value llvm_genericvalue_of_int(LLVMTypeRef Ty, value Int) { - return alloc_generic_value(LLVMCreateGenericValueOfInt(Ty, Int_val(Int), 1)); -} - -/* Llvm.lltype -> int32 -> t */ -CAMLprim value llvm_genericvalue_of_int32(LLVMTypeRef Ty, value Int32) { - CAMLparam1(Int32); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfInt(Ty, Int32_val(Int32), 1))); -} - -/* Llvm.lltype -> nativeint -> t */ -CAMLprim value llvm_genericvalue_of_nativeint(LLVMTypeRef Ty, value NatInt) { - CAMLparam1(NatInt); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfInt(Ty, Nativeint_val(NatInt), 1))); -} - -/* Llvm.lltype -> int64 -> t */ -CAMLprim value llvm_genericvalue_of_int64(LLVMTypeRef Ty, value Int64) { - CAMLparam1(Int64); - CAMLreturn(alloc_generic_value( - LLVMCreateGenericValueOfInt(Ty, Int64_val(Int64), 1))); -} - -/* Llvm.lltype -> t -> float */ -CAMLprim value llvm_genericvalue_as_float(LLVMTypeRef Ty, value GenVal) { - CAMLparam1(GenVal); - CAMLreturn(copy_double( - LLVMGenericValueToFloat(Ty, Genericvalue_val(GenVal)))); -} - -/* t -> 'a */ -CAMLprim value llvm_genericvalue_as_pointer(value GenVal) { - return Val_op(LLVMGenericValueToPointer(Genericvalue_val(GenVal))); -} - -/* t -> int */ -CAMLprim value llvm_genericvalue_as_int(value GenVal) { - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) - && "Generic value too wide to treat as an int!"); - return Val_int(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1)); -} - -/* t -> int32 */ -CAMLprim value llvm_genericvalue_as_int32(value GenVal) { - CAMLparam1(GenVal); - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 32 - && "Generic value too wide to treat as an int32!"); - CAMLreturn(copy_int32(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); -} - -/* t -> int64 */ -CAMLprim value llvm_genericvalue_as_int64(value GenVal) { - CAMLparam1(GenVal); - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 64 - && "Generic value too wide to treat as an int64!"); - CAMLreturn(copy_int64(LLVMGenericValueToInt(Genericvalue_val(GenVal), 1))); -} - -/* t -> nativeint */ -CAMLprim value llvm_genericvalue_as_nativeint(value GenVal) { - CAMLparam1(GenVal); - assert(LLVMGenericValueIntWidth(Genericvalue_val(GenVal)) <= 8 * sizeof(value) - && "Generic value too wide to treat as a nativeint!"); - CAMLreturn(copy_nativeint(LLVMGenericValueToInt(Genericvalue_val(GenVal),1))); -} - - -/*--... Operations on execution engines ....................................--*/ - -/* llmodule -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef llvm_ee_create(LLVMModuleRef M) { - LLVMExecutionEngineRef Interp; - char *Error; - if (LLVMCreateExecutionEngineForModule(&Interp, M, &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return Interp; -} - -/* llmodule -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef -llvm_ee_create_interpreter(LLVMModuleRef M) { - LLVMExecutionEngineRef Interp; +/* llmodule -> llcompileroption -> ExecutionEngine.t */ +CAMLprim LLVMExecutionEngineRef llvm_ee_create(value OptRecordOpt, LLVMModuleRef M) { + value OptRecord; + LLVMExecutionEngineRef MCJIT; char *Error; - if (LLVMCreateInterpreterForModule(&Interp, M, &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return Interp; -} + struct LLVMMCJITCompilerOptions Options; + + LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options)); + if (OptRecordOpt != Val_int(0)) { + OptRecord = Field(OptRecordOpt, 0); + Options.OptLevel = Int_val(Field(OptRecord, 0)); + Options.CodeModel = Int_val(Field(OptRecord, 1)); + Options.NoFramePointerElim = Int_val(Field(OptRecord, 2)); + Options.EnableFastISel = Int_val(Field(OptRecord, 3)); + Options.MCJMM = NULL; + } -/* llmodule -> int -> ExecutionEngine.t */ -CAMLprim LLVMExecutionEngineRef -llvm_ee_create_jit(LLVMModuleRef M, value OptLevel) { - LLVMExecutionEngineRef JIT; - char *Error; - if (LLVMCreateJITCompilerForModule(&JIT, M, Int_val(OptLevel), &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return JIT; + if (LLVMCreateMCJITCompilerForModule(&MCJIT, M, &Options, + sizeof(Options), &Error)) + llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error); + return MCJIT; } /* ExecutionEngine.t -> unit */ @@ -213,43 +72,12 @@ CAMLprim value llvm_ee_add_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { } /* llmodule -> ExecutionEngine.t -> llmodule */ -CAMLprim LLVMModuleRef llvm_ee_remove_module(LLVMModuleRef M, - LLVMExecutionEngineRef EE) { +CAMLprim value llvm_ee_remove_module(LLVMModuleRef M, LLVMExecutionEngineRef EE) { LLVMModuleRef RemovedModule; char *Error; if (LLVMRemoveModule(EE, M, &RemovedModule, &Error)) - llvm_raise(llvm_ee_error_exn, Error); - return RemovedModule; -} - -/* string -> ExecutionEngine.t -> llvalue option */ -CAMLprim value llvm_ee_find_function(value Name, LLVMExecutionEngineRef EE) { - CAMLparam1(Name); - CAMLlocal1(Option); - LLVMValueRef Found; - if (LLVMFindFunction(EE, String_val(Name), &Found)) - CAMLreturn(Val_unit); - Option = alloc(1, 0); - Field(Option, 0) = Val_op(Found); - CAMLreturn(Option); -} - -/* llvalue -> GenericValue.t array -> ExecutionEngine.t -> GenericValue.t */ -CAMLprim value llvm_ee_run_function(LLVMValueRef F, value Args, - LLVMExecutionEngineRef EE) { - unsigned NumArgs; - LLVMGenericValueRef Result, *GVArgs; - unsigned I; - - NumArgs = Wosize_val(Args); - GVArgs = (LLVMGenericValueRef*) malloc(NumArgs * sizeof(LLVMGenericValueRef)); - for (I = 0; I != NumArgs; ++I) - GVArgs[I] = Genericvalue_val(Field(Args, I)); - - Result = LLVMRunFunction(EE, F, NumArgs, GVArgs); - - free(GVArgs); - return alloc_generic_value(Result); + llvm_raise(*caml_named_value("Llvm_executionengine.Error"), Error); + return Val_unit; } /* ExecutionEngine.t -> unit */ @@ -264,78 +92,35 @@ CAMLprim value llvm_ee_run_static_dtors(LLVMExecutionEngineRef EE) { return Val_unit; } -/* llvalue -> string array -> (string * string) array -> ExecutionEngine.t -> - int */ -CAMLprim value llvm_ee_run_function_as_main(LLVMValueRef F, - value Args, value Env, - LLVMExecutionEngineRef EE) { - CAMLparam2(Args, Env); - int I, NumArgs, NumEnv, EnvSize, Result; - const char **CArgs, **CEnv; - char *CEnvBuf, *Pos; - - NumArgs = Wosize_val(Args); - NumEnv = Wosize_val(Env); - - /* Build the environment. */ - CArgs = (const char **) malloc(NumArgs * sizeof(char*)); - for (I = 0; I != NumArgs; ++I) - CArgs[I] = String_val(Field(Args, I)); - - /* Compute the size of the environment string buffer. */ - for (I = 0, EnvSize = 0; I != NumEnv; ++I) { - EnvSize += strlen(String_val(Field(Field(Env, I), 0))) + 1; - EnvSize += strlen(String_val(Field(Field(Env, I), 1))) + 1; - } - - /* Build the environment. */ - CEnv = (const char **) malloc((NumEnv + 1) * sizeof(char*)); - CEnvBuf = (char*) malloc(EnvSize); - Pos = CEnvBuf; - for (I = 0; I != NumEnv; ++I) { - char *Name = String_val(Field(Field(Env, I), 0)), - *Value = String_val(Field(Field(Env, I), 1)); - int NameLen = strlen(Name), - ValueLen = strlen(Value); - - CEnv[I] = Pos; - memcpy(Pos, Name, NameLen); - Pos += NameLen; - *Pos++ = '='; - memcpy(Pos, Value, ValueLen); - Pos += ValueLen; - *Pos++ = '\0'; - } - CEnv[NumEnv] = NULL; - - Result = LLVMRunFunctionAsMain(EE, F, NumArgs, CArgs, CEnv); - - free(CArgs); - free(CEnv); - free(CEnvBuf); - - CAMLreturn(Val_int(Result)); -} - -/* llvalue -> ExecutionEngine.t -> unit */ -CAMLprim value llvm_ee_free_machine_code(LLVMValueRef F, - LLVMExecutionEngineRef EE) { - LLVMFreeMachineCodeForFunction(EE, F); - return Val_unit; -} - extern value llvm_alloc_data_layout(LLVMTargetDataRef TargetData); /* ExecutionEngine.t -> Llvm_target.DataLayout.t */ CAMLprim value llvm_ee_get_data_layout(LLVMExecutionEngineRef EE) { value DataLayout; LLVMTargetDataRef OrigDataLayout; - OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); - char* TargetDataCStr; + + OrigDataLayout = LLVMGetExecutionEngineTargetData(EE); TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); LLVMDisposeMessage(TargetDataCStr); return DataLayout; } + +/* Llvm.llvalue -> int64 -> llexecutionengine -> unit */ +CAMLprim value llvm_ee_add_global_mapping(LLVMValueRef Global, value Ptr, + LLVMExecutionEngineRef EE) { + LLVMAddGlobalMapping(EE, Global, (void*) (Int64_val(Ptr))); + return Val_unit; +} + +CAMLprim value llvm_ee_get_global_value_address(value Name, + LLVMExecutionEngineRef EE) { + return caml_copy_int64((int64_t) LLVMGetGlobalValueAddress(EE, String_val(Name))); +} + +CAMLprim value llvm_ee_get_function_address(value Name, + LLVMExecutionEngineRef EE) { + return caml_copy_int64((int64_t) LLVMGetFunctionAddress(EE, String_val(Name))); +} diff --git a/bindings/ocaml/executionengine/llvm_executionengine.ml b/bindings/ocaml/executionengine/llvm_executionengine.ml index a738df7..34031be 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.ml +++ b/bindings/ocaml/executionengine/llvm_executionengine.ml @@ -1,4 +1,4 @@ -(*===-- llvm_executionengine.ml - LLVM OCaml Interface ----------*- C++ -*-===* +(*===-- llvm_executionengine.ml - LLVM OCaml Interface --------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -7,105 +7,66 @@ * *===----------------------------------------------------------------------===*) - exception Error of string -external register_exns: exn -> unit - = "llvm_register_ee_exns" +let () = Callback.register_exception "Llvm_executionengine.Error" (Error "") + +external initialize : unit -> bool + = "llvm_ee_initialize" + +type llexecutionengine + +type llcompileroptions = { + opt_level: int; + code_model: Llvm_target.CodeModel.t; + no_framepointer_elim: bool; + enable_fast_isel: bool; +} +let default_compiler_options = { + opt_level = 0; + code_model = Llvm_target.CodeModel.JITDefault; + no_framepointer_elim = false; + enable_fast_isel = false } -module GenericValue = struct - type t - - external of_float: Llvm.lltype -> float -> t - = "llvm_genericvalue_of_float" - external of_pointer: 'a -> t - = "llvm_genericvalue_of_pointer" - external of_int32: Llvm.lltype -> int32 -> t - = "llvm_genericvalue_of_int32" - external of_int: Llvm.lltype -> int -> t - = "llvm_genericvalue_of_int" - external of_nativeint: Llvm.lltype -> nativeint -> t - = "llvm_genericvalue_of_nativeint" - external of_int64: Llvm.lltype -> int64 -> t - = "llvm_genericvalue_of_int64" - - external as_float: Llvm.lltype -> t -> float - = "llvm_genericvalue_as_float" - external as_pointer: t -> 'a - = "llvm_genericvalue_as_pointer" - external as_int32: t -> int32 - = "llvm_genericvalue_as_int32" - external as_int: t -> int - = "llvm_genericvalue_as_int" - external as_nativeint: t -> nativeint - = "llvm_genericvalue_as_nativeint" - external as_int64: t -> int64 - = "llvm_genericvalue_as_int64" -end +external create : ?options:llcompileroptions -> Llvm.llmodule -> llexecutionengine + = "llvm_ee_create" +external dispose : llexecutionengine -> unit + = "llvm_ee_dispose" +external add_module : Llvm.llmodule -> llexecutionengine -> unit + = "llvm_ee_add_module" +external remove_module : Llvm.llmodule -> llexecutionengine -> unit + = "llvm_ee_remove_module" +external run_static_ctors : llexecutionengine -> unit + = "llvm_ee_run_static_ctors" +external run_static_dtors : llexecutionengine -> unit + = "llvm_ee_run_static_dtors" +external data_layout : llexecutionengine -> Llvm_target.DataLayout.t + = "llvm_ee_get_data_layout" +external add_global_mapping_ : Llvm.llvalue -> int64 -> llexecutionengine -> unit + = "llvm_ee_add_global_mapping" +external get_global_value_address_ : string -> llexecutionengine -> int64 + = "llvm_ee_get_global_value_address" +external get_function_address_ : string -> llexecutionengine -> int64 + = "llvm_ee_get_function_address" +let add_global_mapping llval ptr ee = + add_global_mapping_ llval (Ctypes.raw_address_of_ptr (Ctypes.to_voidp ptr)) ee -module ExecutionEngine = struct - type t - - (* FIXME: Ocaml is not running this setup code unless we use 'val' in the - interface, which causes the emission of a stub for each function; - using 'external' in the module allows direct calls into - ocaml_executionengine.c. This is hardly fatal, but it is unnecessary - overhead on top of the two stubs that are already invoked for each - call into LLVM. *) - let _ = register_exns (Error "") - - external create: Llvm.llmodule -> t - = "llvm_ee_create" - external create_interpreter: Llvm.llmodule -> t - = "llvm_ee_create_interpreter" - external create_jit: Llvm.llmodule -> int -> t - = "llvm_ee_create_jit" - external dispose: t -> unit - = "llvm_ee_dispose" - external add_module: Llvm.llmodule -> t -> unit - = "llvm_ee_add_module" - external remove_module: Llvm.llmodule -> t -> Llvm.llmodule - = "llvm_ee_remove_module" - external find_function: string -> t -> Llvm.llvalue option - = "llvm_ee_find_function" - external run_function: Llvm.llvalue -> GenericValue.t array -> t -> - GenericValue.t - = "llvm_ee_run_function" - external run_static_ctors: t -> unit - = "llvm_ee_run_static_ctors" - external run_static_dtors: t -> unit - = "llvm_ee_run_static_dtors" - external run_function_as_main: Llvm.llvalue -> string array -> - (string * string) array -> t -> int - = "llvm_ee_run_function_as_main" - external free_machine_code: Llvm.llvalue -> t -> unit - = "llvm_ee_free_machine_code" +let get_global_value_address name typ ee = + let vptr = get_global_value_address_ name ee in + if Int64.to_int vptr <> 0 then + let open Ctypes in !@ (coerce (ptr void) (ptr typ) (ptr_of_raw_address vptr)) + else + raise (Error ("Value " ^ name ^ " not found")) - external data_layout : t -> Llvm_target.DataLayout.t - = "llvm_ee_get_data_layout" - - (* The following are not bound. Patches are welcome. - - add_global_mapping: llvalue -> llgenericvalue -> t -> unit - clear_all_global_mappings: t -> unit - update_global_mapping: llvalue -> llgenericvalue -> t -> unit - get_pointer_to_global_if_available: llvalue -> t -> llgenericvalue - get_pointer_to_global: llvalue -> t -> llgenericvalue - get_pointer_to_function: llvalue -> t -> llgenericvalue - get_pointer_to_function_or_stub: llvalue -> t -> llgenericvalue - get_global_value_at_address: llgenericvalue -> t -> llvalue option - store_value_to_memory: llgenericvalue -> llgenericvalue -> lltype -> unit - initialize_memory: llvalue -> llgenericvalue -> t -> unit - recompile_and_relink_function: llvalue -> t -> llgenericvalue - get_or_emit_global_variable: llvalue -> t -> llgenericvalue - disable_lazy_compilation: t -> unit - lazy_compilation_enabled: t -> bool - install_lazy_function_creator: (string -> llgenericvalue) -> t -> unit - - *) -end +let get_function_address name typ ee = + let fptr = get_function_address_ name ee in + if Int64.to_int fptr <> 0 then + let open Ctypes in coerce (ptr void) typ (ptr_of_raw_address fptr) + else + raise (Error ("Function " ^ name ^ " not found")) -external initialize_native_target : unit -> bool - = "llvm_initialize_native_target" +(* The following are not bound. Patches are welcome. +target_machine : llexecutionengine -> Llvm_target.TargetMachine.t + *) diff --git a/bindings/ocaml/executionengine/llvm_executionengine.mli b/bindings/ocaml/executionengine/llvm_executionengine.mli index 74a6062..bc076be 100644 --- a/bindings/ocaml/executionengine/llvm_executionengine.mli +++ b/bindings/ocaml/executionengine/llvm_executionengine.mli @@ -1,4 +1,4 @@ -(*===-- llvm_executionengine.mli - LLVM OCaml Interface ---------*- C++ -*-===* +(*===-- llvm_executionengine.mli - LLVM OCaml Interface -------*- OCaml -*-===* * * The LLVM Compiler Infrastructure * @@ -10,147 +10,84 @@ (** JIT Interpreter. This interface provides an OCaml API for LLVM execution engine (JIT/ - interpreter), the classes in the ExecutionEngine library. *) + interpreter), the classes in the [ExecutionEngine] library. *) exception Error of string -module GenericValue: sig - (** [GenericValue.t] is a boxed union type used to portably pass arguments to - and receive values from the execution engine. It supports only a limited - selection of types; for more complex argument types, it is necessary to - generate a stub function by hand or to pass parameters by reference. - See the struct [llvm::GenericValue]. *) - type t - - (** [of_float fpty n] boxes the float [n] in a float-valued generic value - according to the floating point type [fpty]. See the fields - [llvm::GenericValue::DoubleVal] and [llvm::GenericValue::FloatVal]. *) - val of_float : Llvm.lltype -> float -> t - - (** [of_pointer v] boxes the pointer value [v] in a generic value. See the - field [llvm::GenericValue::PointerVal]. *) - val of_pointer : 'a -> t - - (** [of_int32 n w] boxes the int32 [i] in a generic value with the bitwidth - [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int32 : Llvm.lltype -> int32 -> t - - (** [of_int n w] boxes the int [i] in a generic value with the bitwidth - [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int : Llvm.lltype -> int -> t - - (** [of_natint n w] boxes the native int [i] in a generic value with the - bitwidth [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_nativeint : Llvm.lltype -> nativeint -> t - - (** [of_int64 n w] boxes the int64 [i] in a generic value with the bitwidth - [w]. See the field [llvm::GenericValue::IntVal]. *) - val of_int64 : Llvm.lltype -> int64 -> t - - (** [as_float fpty gv] unboxes the floating point-valued generic value [gv] of - floating point type [fpty]. See the fields [llvm::GenericValue::DoubleVal] - and [llvm::GenericValue::FloatVal]. *) - val as_float : Llvm.lltype -> t -> float - - (** [as_pointer gv] unboxes the pointer-valued generic value [gv]. See the - field [llvm::GenericValue::PointerVal]. *) - val as_pointer : t -> 'a - - (** [as_int32 gv] unboxes the integer-valued generic value [gv] as an [int32]. - Is invalid if [gv] has a bitwidth greater than 32 bits. See the field - [llvm::GenericValue::IntVal]. *) - val as_int32 : t -> int32 - - (** [as_int gv] unboxes the integer-valued generic value [gv] as an [int]. - Is invalid if [gv] has a bitwidth greater than the host bit width (but the - most significant bit may be lost). See the field - [llvm::GenericValue::IntVal]. *) - val as_int : t -> int - - (** [as_natint gv] unboxes the integer-valued generic value [gv] as a - [nativeint]. Is invalid if [gv] has a bitwidth greater than - [nativeint]. See the field [llvm::GenericValue::IntVal]. *) - val as_nativeint : t -> nativeint - - (** [as_int64 gv] returns the integer-valued generic value [gv] as an [int64]. - Is invalid if [gv] has a bitwidth greater than [int64]. See the field - [llvm::GenericValue::IntVal]. *) - val as_int64 : t -> int64 -end - - -module ExecutionEngine: sig - (** An execution engine is either a JIT compiler or an interpreter, capable of - directly loading an LLVM module and executing its functions without first - invoking a static compiler and generating a native executable. *) - type t - - (** [create m] creates a new execution engine, taking ownership of the - module [m] if successful. Creates a JIT if possible, else falls back to an - interpreter. Raises [Error msg] if an error occurrs. The execution engine - is not garbage collected and must be destroyed with [dispose ee]. - See the function [llvm::EngineBuilder::create]. *) - val create : Llvm.llmodule -> t - - (** [create_interpreter m] creates a new interpreter, taking ownership of the - module [m] if successful. Raises [Error msg] if an error occurrs. The - execution engine is not garbage collected and must be destroyed with - [dispose ee]. - See the function [llvm::EngineBuilder::create]. *) - val create_interpreter : Llvm.llmodule -> t - - (** [create_jit m optlevel] creates a new JIT (just-in-time compiler), taking - ownership of the module [m] if successful with the desired optimization - level [optlevel]. Raises [Error msg] if an error occurrs. The execution - engine is not garbage collected and must be destroyed with [dispose ee]. - See the function [llvm::EngineBuilder::create]. *) - val create_jit : Llvm.llmodule -> int -> t - - (** [dispose ee] releases the memory used by the execution engine and must be - invoked to avoid memory leaks. *) - val dispose : t -> unit - - (** [add_module m ee] adds the module [m] to the execution engine [ee]. *) - val add_module : Llvm.llmodule -> t -> unit - - (** [remove_module m ee] removes the module [m] from the execution engine - [ee], disposing of [m] and the module referenced by [mp]. Raises - [Error msg] if an error occurs. *) - val remove_module : Llvm.llmodule -> t -> Llvm.llmodule - - (** [find_function n ee] finds the function named [n] defined in any of the - modules owned by the execution engine [ee]. Returns [None] if the function - is not found and [Some f] otherwise. *) - val find_function : string -> t -> Llvm.llvalue option - - (** [run_function f args ee] synchronously executes the function [f] with the - arguments [args], which must be compatible with the parameter types. *) - val run_function : Llvm.llvalue -> GenericValue.t array -> t -> - GenericValue.t - - (** [run_static_ctors ee] executes the static constructors of each module in - the execution engine [ee]. *) - val run_static_ctors : t -> unit - - (** [run_static_dtors ee] executes the static destructors of each module in - the execution engine [ee]. *) - val run_static_dtors : t -> unit - - (** [run_function_as_main f args env ee] executes the function [f] as a main - function, passing it [argv] and [argc] according to the string array - [args], and [envp] as specified by the array [env]. Returns the integer - return value of the function. *) - val run_function_as_main : Llvm.llvalue -> string array -> - (string * string) array -> t -> int - - (** [free_machine_code f ee] releases the memory in the execution engine [ee] - used to store the machine code for the function [f]. *) - val free_machine_code : Llvm.llvalue -> t -> unit - - (** [data_layout ee] is the data layout of the execution engine [ee]. *) - val data_layout : t -> Llvm_target.DataLayout.t -end - -(** [initialize_native_target ()] initializes the native target corresponding - to the host. Returns [true] if initialization is {b not} done. *) -val initialize_native_target : unit -> bool +(** [initialize ()] initializes the backend corresponding to the host. + Returns [true] if initialization is successful; [false] indicates + that there is no such backend or it is unable to emit object code + via MCJIT. *) +val initialize : unit -> bool + +(** An execution engine is either a JIT compiler or an interpreter, capable of + directly loading an LLVM module and executing its functions without first + invoking a static compiler and generating a native executable. *) +type llexecutionengine + +(** MCJIT compiler options. See [llvm::TargetOptions]. *) +type llcompileroptions = { + opt_level: int; + code_model: Llvm_target.CodeModel.t; + no_framepointer_elim: bool; + enable_fast_isel: bool; +} + +(** Default MCJIT compiler options: + [{ opt_level = 0; code_model = CodeModel.JIT_default; + no_framepointer_elim = false; enable_fast_isel = false }] *) +val default_compiler_options : llcompileroptions + +(** [create m optlevel] creates a new MCJIT just-in-time compiler, taking + ownership of the module [m] if successful with the desired optimization + level [optlevel]. Raises [Error msg] if an error occurrs. The execution + engine is not garbage collected and must be destroyed with [dispose ee]. + + Run {!initialize} before using this function. + + See the function [llvm::EngineBuilder::create]. *) +val create : ?options:llcompileroptions -> Llvm.llmodule -> llexecutionengine + +(** [dispose ee] releases the memory used by the execution engine and must be + invoked to avoid memory leaks. *) +val dispose : llexecutionengine -> unit + +(** [add_module m ee] adds the module [m] to the execution engine [ee]. *) +val add_module : Llvm.llmodule -> llexecutionengine -> unit + +(** [remove_module m ee] removes the module [m] from the execution engine + [ee]. Raises [Error msg] if an error occurs. *) +val remove_module : Llvm.llmodule -> llexecutionengine -> unit + +(** [run_static_ctors ee] executes the static constructors of each module in + the execution engine [ee]. *) +val run_static_ctors : llexecutionengine -> unit + +(** [run_static_dtors ee] executes the static destructors of each module in + the execution engine [ee]. *) +val run_static_dtors : llexecutionengine -> unit + +(** [data_layout ee] is the data layout of the execution engine [ee]. *) +val data_layout : llexecutionengine -> Llvm_target.DataLayout.t + +(** [add_global_mapping gv ptr ee] tells the execution engine [ee] that + the global [gv] is at the specified location [ptr], which must outlive + [gv] and [ee]. + All uses of [gv] in the compiled code will refer to [ptr]. *) +val add_global_mapping : Llvm.llvalue -> 'a Ctypes.ptr -> llexecutionengine -> unit + +(** [get_global_value_address id typ ee] returns a pointer to the + identifier [id] as type [typ], which will be a pointer type for a + value, and which will be live as long as [id] and [ee] + are. Caution: this function finalizes, i.e. forces code + generation, all loaded modules. Further modifications to the + modules will not have any effect. *) +val get_global_value_address : string -> 'a Ctypes.typ -> llexecutionengine -> 'a + +(** [get_function_address fn typ ee] returns a pointer to the function + [fn] as type [typ], which will be a pointer type for a function + (e.g. [(int -> int) typ]), and which will be live as long as [fn] + and [ee] are. Caution: this function finalizes, i.e. forces code + generation, all loaded modules. Further modifications to the + modules will not have any effect. *) +val get_function_address : string -> 'a Ctypes.typ -> llexecutionengine -> 'a diff --git a/bindings/ocaml/irreader/CMakeLists.txt b/bindings/ocaml/irreader/CMakeLists.txt new file mode 100644 index 0000000..87d269b --- /dev/null +++ b/bindings/ocaml/irreader/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_irreader + OCAML llvm_irreader + OCAMLDEP llvm + C irreader_ocaml + LLVM irreader) diff --git a/bindings/ocaml/irreader/irreader_ocaml.c b/bindings/ocaml/irreader/irreader_ocaml.c index 30c10c7..ce593db 100644 --- a/bindings/ocaml/irreader/irreader_ocaml.c +++ b/bindings/ocaml/irreader/irreader_ocaml.c @@ -16,33 +16,9 @@ #include "caml/alloc.h" #include "caml/fail.h" #include "caml/memory.h" +#include "caml/callback.h" -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_irreader_error_exn; - -CAMLprim value llvm_register_irreader_exns(value Error) { - llvm_irreader_error_exn = Field(Error, 0); - register_global_root(&llvm_irreader_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - - -/*===-- Modules -----------------------------------------------------------===*/ +void llvm_raise(value Prototype, char *Message); /* Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule */ CAMLprim value llvm_parse_ir(LLVMContextRef C, @@ -53,7 +29,7 @@ CAMLprim value llvm_parse_ir(LLVMContextRef C, char *Message; if (LLVMParseIRInContext(C, MemBuf, &M, &Message)) - llvm_raise(llvm_irreader_error_exn, Message); + llvm_raise(*caml_named_value("Llvm_irreader.Error"), Message); CAMLreturn((value) M); } diff --git a/bindings/ocaml/irreader/llvm_irreader.ml b/bindings/ocaml/irreader/llvm_irreader.ml index 455b1fa..f757d62 100644 --- a/bindings/ocaml/irreader/llvm_irreader.ml +++ b/bindings/ocaml/irreader/llvm_irreader.ml @@ -10,8 +10,7 @@ exception Error of string -external register_exns : exn -> unit = "llvm_register_irreader_exns" -let _ = register_exns (Error "") +let _ = Callback.register_exception "Llvm_irreader.Error" (Error "") external parse_ir : Llvm.llcontext -> Llvm.llmemorybuffer -> Llvm.llmodule = "llvm_parse_ir" diff --git a/bindings/ocaml/linker/CMakeLists.txt b/bindings/ocaml/linker/CMakeLists.txt new file mode 100644 index 0000000..b6bc8ac --- /dev/null +++ b/bindings/ocaml/linker/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_linker + OCAML llvm_linker + OCAMLDEP llvm + C linker_ocaml + LLVM linker) diff --git a/bindings/ocaml/linker/linker_ocaml.c b/bindings/ocaml/linker/linker_ocaml.c index 2491e3b..3b8512a 100644 --- a/bindings/ocaml/linker/linker_ocaml.c +++ b/bindings/ocaml/linker/linker_ocaml.c @@ -1,4 +1,4 @@ -/*===-- linker_ocaml.c - LLVM Ocaml Glue ------------------------*- C++ -*-===*\ +/*===-- linker_ocaml.c - LLVM OCaml Glue ------------------------*- C++ -*-===*\ |* *| |* The LLVM Compiler Infrastructure *| |* *| @@ -19,36 +19,16 @@ #include "caml/alloc.h" #include "caml/memory.h" #include "caml/fail.h" +#include "caml/callback.h" -static value llvm_linker_error_exn; +void llvm_raise(value Prototype, char *Message); -CAMLprim value llvm_register_linker_exns(value Error) { - llvm_linker_error_exn = Field(Error, 0); - register_global_root(&llvm_linker_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - -/* llmodule -> llmodule -> Mode.t -> unit - raises Error msg on error */ -CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src, value Mode) { +/* llmodule -> llmodule -> unit */ +CAMLprim value llvm_link_modules(LLVMModuleRef Dst, LLVMModuleRef Src) { char* Message; - if (LLVMLinkModules(Dst, Src, Int_val(Mode), &Message)) - llvm_raise(llvm_linker_error_exn, Message); + if (LLVMLinkModules(Dst, Src, 0, &Message)) + llvm_raise(*caml_named_value("Llvm_linker.Error"), Message); return Val_unit; } diff --git a/bindings/ocaml/linker/llvm_linker.ml b/bindings/ocaml/linker/llvm_linker.ml index 2b73e2e..3044abd 100644 --- a/bindings/ocaml/linker/llvm_linker.ml +++ b/bindings/ocaml/linker/llvm_linker.ml @@ -9,14 +9,7 @@ exception Error of string -external register_exns : exn -> unit = "llvm_register_linker_exns" -let _ = register_exns (Error "") +let () = Callback.register_exception "Llvm_linker.Error" (Error "") -module Mode = struct - type t = - | DestroySource - | PreserveSource -end - -external link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit - = "llvm_link_modules" \ No newline at end of file +external link_modules : Llvm.llmodule -> Llvm.llmodule -> unit + = "llvm_link_modules" diff --git a/bindings/ocaml/linker/llvm_linker.mli b/bindings/ocaml/linker/llvm_linker.mli index 4def7a8..06c3b92 100644 --- a/bindings/ocaml/linker/llvm_linker.mli +++ b/bindings/ocaml/linker/llvm_linker.mli @@ -14,13 +14,6 @@ exception Error of string -(** Linking mode. *) -module Mode : sig - type t = - | DestroySource - | PreserveSource -end - (** [link_modules dst src mode] links [src] into [dst], raising [Error] if the linking fails. *) -val link_modules : Llvm.llmodule -> Llvm.llmodule -> Mode.t -> unit \ No newline at end of file +val link_modules : Llvm.llmodule -> Llvm.llmodule -> unit \ No newline at end of file diff --git a/bindings/ocaml/llvm/CMakeLists.txt b/bindings/ocaml/llvm/CMakeLists.txt new file mode 100644 index 0000000..4956fa4 --- /dev/null +++ b/bindings/ocaml/llvm/CMakeLists.txt @@ -0,0 +1,11 @@ +add_ocaml_library(llvm + OCAML llvm + C llvm_ocaml + LLVM core support) + +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/META.llvm.in" + "${LLVM_LIBRARY_DIR}/ocaml/META.llvm") + +install(FILES "${LLVM_LIBRARY_DIR}/ocaml/META.llvm" + DESTINATION lib/ocaml) diff --git a/bindings/ocaml/llvm/META.llvm.in b/bindings/ocaml/llvm/META.llvm.in index edb84e0..92896e3 100644 --- a/bindings/ocaml/llvm/META.llvm.in +++ b/bindings/ocaml/llvm/META.llvm.in @@ -4,7 +4,6 @@ description = "LLVM OCaml bindings" archive(byte) = "llvm.cma" archive(native) = "llvm.cmxa" directory = "." -linkopts = "-ccopt -lstdc++" package "analysis" ( requires = "llvm" @@ -31,7 +30,7 @@ package "bitwriter" ( ) package "executionengine" ( - requires = "llvm,llvm.target" + requires = "llvm,llvm.target,ctypes.foreign" version = "@PACKAGE_VERSION@" description = "JIT and Interpreter for LLVM" archive(byte) = "llvm_executionengine.cma" @@ -62,6 +61,14 @@ package "scalar_opts" ( archive(native) = "llvm_scalar_opts.cmxa" ) +package "transform_utils" ( + requires = "llvm" + version = "@PACKAGE_VERSION@" + description = "Transform utilities for LLVM" + archive(byte) = "llvm_transform_utils.cma" + archive(native) = "llvm_transform_utils.cmxa" +) + package "vectorize" ( requires = "llvm" version = "@PACKAGE_VERSION@" diff --git a/bindings/ocaml/llvm/Makefile b/bindings/ocaml/llvm/Makefile index 850f564..c0785a1 100644 --- a/bindings/ocaml/llvm/Makefile +++ b/bindings/ocaml/llvm/Makefile @@ -1,20 +1,21 @@ ##===- bindings/ocaml/llvm/Makefile ------------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## -# +# # This is the makefile for the Objective Caml Llvm interface. -# +# ##===----------------------------------------------------------------------===## LEVEL := ../../.. LIBRARYNAME := llvm UsedComponents := core UsedOcamlLibs := llvm +ExtraLibs := -lstdc++ include ../Makefile.ocaml diff --git a/bindings/ocaml/llvm/llvm.ml b/bindings/ocaml/llvm/llvm.ml index 39875a5..042edcb 100644 --- a/bindings/ocaml/llvm/llvm.ml +++ b/bindings/ocaml/llvm/llvm.ml @@ -1,4 +1,4 @@ -(*===-- llvm/llvm.ml - LLVM Ocaml Interface --------------------------------===* +(*===-- llvm/llvm.ml - LLVM OCaml Interface -------------------------------===* * * The LLVM Compiler Infrastructure * @@ -66,6 +66,13 @@ module Visibility = struct | Protected end +module DLLStorageClass = struct + type t = + | Default + | DLLImport + | DLLExport +end + module CallConv = struct let c = 0 let fast = 8 @@ -278,8 +285,7 @@ end exception IoError of string -external register_exns : exn -> unit = "llvm_register_core_exns" -let _ = register_exns (IoError "") +let () = Callback.register_exception "Llvm.IoError" (IoError "") external install_fatal_error_handler : (string -> unit) -> unit = "llvm_install_fatal_error_handler" @@ -287,6 +293,8 @@ external reset_fatal_error_handler : unit -> unit = "llvm_reset_fatal_error_handler" external enable_pretty_stacktrace : unit -> unit = "llvm_enable_pretty_stacktrace" +external parse_command_line_options : ?overview:string -> string array -> unit + = "llvm_parse_command_line_options" type ('a, 'b) llpos = | At_end of 'a @@ -428,6 +436,7 @@ let fold_right_uses f v init = (*--... Operations on users ................................................--*) external operand : llvalue -> int -> llvalue = "llvm_operand" +external operand_use : llvalue -> int -> lluse = "llvm_operand_use" external set_operand : llvalue -> int -> llvalue -> unit = "llvm_set_operand" external num_operands : llvalue -> int = "llvm_num_operands" @@ -450,6 +459,7 @@ external clear_metadata : llvalue -> llmdkind -> unit = "llvm_clear_metadata" (*--... Operations on metadata .......,.....................................--*) external mdstring : llcontext -> string -> llvalue = "llvm_mdstring" external mdnode : llcontext -> llvalue array -> llvalue = "llvm_mdnode" +external mdnull : llcontext -> llvalue = "llvm_mdnull" external get_mdstring : llvalue -> string option = "llvm_get_mdstring" external get_named_metadata : llmodule -> string -> llvalue array = "llvm_get_namedmd" @@ -465,6 +475,8 @@ external int64_of_const : llvalue -> Int64.t option external const_int_of_string : lltype -> string -> int -> llvalue = "llvm_const_int_of_string" external const_float : lltype -> float -> llvalue = "llvm_const_float" +external float_of_const : llvalue -> float option + = "llvm_float_of_const" external const_float_of_string : lltype -> string -> llvalue = "llvm_const_float_of_string" @@ -479,6 +491,8 @@ external const_named_struct : lltype -> llvalue array -> llvalue external const_packed_struct : llcontext -> llvalue array -> llvalue = "llvm_const_packed_struct" external const_vector : llvalue array -> llvalue = "llvm_const_vector" +external string_of_const : llvalue -> string option = "llvm_string_of_const" +external const_element : llvalue -> int -> llvalue = "llvm_const_element" (*--... Constant expressions ...............................................--*) external align_of : lltype -> llvalue = "LLVMAlignOf" @@ -569,6 +583,8 @@ external section : llvalue -> string = "llvm_section" external set_section : string -> llvalue -> unit = "llvm_set_section" external visibility : llvalue -> Visibility.t = "llvm_visibility" external set_visibility : Visibility.t -> llvalue -> unit = "llvm_set_visibility" +external dll_storage_class : llvalue -> DLLStorageClass.t = "llvm_dll_storage_class" +external set_dll_storage_class : DLLStorageClass.t -> llvalue -> unit = "llvm_set_dll_storage_class" external alignment : llvalue -> int = "llvm_alignment" external set_alignment : int -> llvalue -> unit = "llvm_set_alignment" external is_global_constant : llvalue -> bool = "llvm_is_global_constant" @@ -952,6 +968,8 @@ external instr_pred : llvalue -> (llbasicblock, llvalue) llrev_pos external instr_opcode : llvalue -> Opcode.t = "llvm_instr_get_opcode" external icmp_predicate : llvalue -> Icmp.t option = "llvm_instr_icmp_predicate" +external fcmp_predicate : llvalue -> Fcmp.t option = "llvm_instr_fcmp_predicate" +external instr_clone : llvalue -> llvalue = "llvm_instr_clone" let rec iter_instrs_range f i e = if i = e then () else @@ -1019,6 +1037,63 @@ external set_tail_call : bool -> llvalue -> unit = "llvm_set_tail_call" external is_volatile : llvalue -> bool = "llvm_is_volatile" external set_volatile : bool -> llvalue -> unit = "llvm_set_volatile" +(*--... Operations on terminators ..........................................--*) + +let is_terminator llv = + let open ValueKind in + let open Opcode in + match classify_value llv with + | Instruction (Br | IndirectBr | Invoke | Resume | Ret | Switch | Unreachable) + -> true + | _ -> false + +external successor : llvalue -> int -> llbasicblock = "llvm_successor" +external set_successor : llvalue -> int -> llbasicblock -> unit + = "llvm_set_successor" +external num_successors : llvalue -> int = "llvm_num_successors" + +let successors llv = + if not (is_terminator llv) then + raise (Invalid_argument "Llvm.successors can only be used on terminators") + else + Array.init (num_successors llv) (successor llv) + +let iter_successors f llv = + if not (is_terminator llv) then + raise (Invalid_argument "Llvm.iter_successors can only be used on terminators") + else + for i = 0 to num_successors llv - 1 do + f (successor llv i) + done + +let fold_successors f llv z = + if not (is_terminator llv) then + raise (Invalid_argument "Llvm.fold_successors can only be used on terminators") + else + let n = num_successors llv in + let rec aux i acc = + if i >= n then acc + else begin + let llb = successor llv i in + aux (i+1) (f llb acc) + end + in aux 0 z + + +(*--... Operations on branches .............................................--*) +external condition : llvalue -> llvalue = "llvm_condition" +external set_condition : llvalue -> llvalue -> unit + = "llvm_set_condition" +external is_conditional : llvalue -> bool = "llvm_is_conditional" + +let get_branch llv = + if classify_value llv <> ValueKind.Instruction Opcode.Br then + None + else if is_conditional llv then + Some (`Conditional (condition llv, successor llv 0, successor llv 1)) + else + Some (`Unconditional (successor llv 0)) + (*--... Operations on phi nodes ............................................--*) external add_incoming : (llvalue * llbasicblock) -> llvalue -> unit = "llvm_add_incoming" diff --git a/bindings/ocaml/llvm/llvm.mli b/bindings/ocaml/llvm/llvm.mli index f5f5b53..8fdddd1 100644 --- a/bindings/ocaml/llvm/llvm.mli +++ b/bindings/ocaml/llvm/llvm.mli @@ -105,6 +105,15 @@ module Visibility : sig | Protected end +(** The DLL storage class of a global value, accessed with {!dll_storage_class} and + {!set_dll_storage_class}. See [llvm::GlobalValue::DLLStorageClassTypes]. *) +module DLLStorageClass : sig + type t = + | Default + | DLLImport + | DLLExport +end + (** The following calling convention values may be accessed with {!function_call_conv} and {!set_function_call_conv}. Calling conventions are open-ended. *) @@ -157,16 +166,16 @@ end See the [llvm::ICmpInst::Predicate] enumeration. *) module Icmp : sig type t = - | Eq (* Equal *) - | Ne (* Not equal *) - | Ugt (* Unsigned greater than *) - | Uge (* Unsigned greater or equal *) - | Ult (* Unsigned less than *) - | Ule (* Unsigned less or equal *) - | Sgt (* Signed greater than *) - | Sge (* Signed greater or equal *) - | Slt (* Signed less than *) - | Sle (* Signed less or equal *) + | Eq (** Equal *) + | Ne (** Not equal *) + | Ugt (** Unsigned greater than *) + | Uge (** Unsigned greater or equal *) + | Ult (** Unsigned less than *) + | Ule (** Unsigned less or equal *) + | Sgt (** Signed greater than *) + | Sge (** Signed greater or equal *) + | Slt (** Signed less than *) + | Sle (** Signed less or equal *) end (** The predicate for a floating-point comparison ([fcmp]) instruction. @@ -175,38 +184,38 @@ end See the [llvm::FCmpInst::Predicate] enumeration. *) module Fcmp : sig type t = - | False (* Always false *) - | Oeq (* Ordered and equal *) - | Ogt (* Ordered and greater than *) - | Oge (* Ordered and greater or equal *) - | Olt (* Ordered and less than *) - | Ole (* Ordered and less or equal *) - | One (* Ordered and not equal *) - | Ord (* Ordered (no operand is NaN) *) - | Uno (* Unordered (one operand at least is NaN) *) - | Ueq (* Unordered and equal *) - | Ugt (* Unordered and greater than *) - | Uge (* Unordered and greater or equal *) - | Ult (* Unordered and less than *) - | Ule (* Unordered and less or equal *) - | Une (* Unordered and not equal *) - | True (* Always true *) + | False (** Always false *) + | Oeq (** Ordered and equal *) + | Ogt (** Ordered and greater than *) + | Oge (** Ordered and greater or equal *) + | Olt (** Ordered and less than *) + | Ole (** Ordered and less or equal *) + | One (** Ordered and not equal *) + | Ord (** Ordered (no operand is NaN) *) + | Uno (** Unordered (one operand at least is NaN) *) + | Ueq (** Unordered and equal *) + | Ugt (** Unordered and greater than *) + | Uge (** Unordered and greater or equal *) + | Ult (** Unordered and less than *) + | Ule (** Unordered and less or equal *) + | Une (** Unordered and not equal *) + | True (** Always true *) end (** The opcodes for LLVM instructions and constant expressions. *) module Opcode : sig type t = - | Invalid (* not an instruction *) - (* Terminator Instructions *) - | Ret + | Invalid (** Not an instruction *) + + | Ret (** Terminator Instructions *) | Br | Switch | IndirectBr | Invoke | Invalid2 | Unreachable - (* Standard Binary Operators *) - | Add + + | Add (** Standard Binary Operators *) | FAdd | Sub | FSub @@ -218,20 +227,20 @@ module Opcode : sig | URem | SRem | FRem - (* Logical Operators *) - | Shl + + | Shl (** Logical Operators *) | LShr | AShr | And | Or | Xor - (* Memory Operators *) - | Alloca + + | Alloca (** Memory Operators *) | Load | Store | GetElementPtr - (* Cast Operators *) - | Trunc + + | Trunc (** Cast Operators *) | ZExt | SExt | FPToUI @@ -243,8 +252,8 @@ module Opcode : sig | PtrToInt | IntToPtr | BitCast - (* Other Operators *) - | ICmp + + | ICmp (** Other Operators *) | FCmp | PHI | Call @@ -291,7 +300,7 @@ module AtomicOrdering : sig | NotAtomic | Unordered | Monotonic - | Invalid (* removed due to API changes *) + | Invalid (** removed due to API changes *) | Acquire | Release | AcqiureRelease @@ -381,6 +390,14 @@ val install_fatal_error_handler : (string -> unit) -> unit (** [reset_fatal_error_handler ()] resets LLVM's fatal error handler. *) val reset_fatal_error_handler : unit -> unit +(** [parse_command_line_options ?overview args] parses [args] using + the LLVM command line parser. Note that the only stable thing about this + function is its signature; you cannot rely on any particular set of command + line arguments being interpreted the same way across LLVM versions. + + See the function [llvm::cl::ParseCommandLineOptions()]. *) +val parse_command_line_options : ?overview:string -> string array -> unit + (** {6 Contexts} *) (** [create_context ()] creates a context for storing the "global" state in @@ -651,7 +668,7 @@ val x86_mmx_type : llcontext -> lltype val type_by_name : llmodule -> string -> lltype option -(* {6 Values} *) +(** {6 Values} *) (** [type_of v] returns the type of the value [v]. See the method [llvm::Value::getType]. *) @@ -682,7 +699,7 @@ val string_of_llvalue : llvalue -> string val replace_all_uses_with : llvalue -> llvalue -> unit -(* {6 Uses} *) +(** {6 Uses} *) (** [use_begin v] returns the first position in the use list for the value [v]. [use_begin] and [use_succ] can e used to iterate over the use list in order. @@ -714,12 +731,17 @@ val fold_left_uses : ('a -> lluse -> 'a) -> 'a -> llvalue -> 'a val fold_right_uses : (lluse -> 'a -> 'a) -> llvalue -> 'a -> 'a -(* {6 Users} *) +(** {6 Users} *) (** [operand v i] returns the operand at index [i] for the value [v]. See the method [llvm::User::getOperand]. *) val operand : llvalue -> int -> llvalue +(** [operand_use v i] returns the use of the operand at index [i] for the value [v]. See the + method [llvm::User::getOperandUse]. *) +val operand_use : llvalue -> int -> lluse + + (** [set_operand v i o] sets the operand of the value [v] at the index [i] to the value [o]. See the method [llvm::User::setOperand]. *) @@ -797,6 +819,9 @@ val mdstring : llcontext -> string -> llvalue See the method [llvm::MDNode::get]. *) val mdnode : llcontext -> llvalue array -> llvalue +(** [mdnull c ] returns a null MDNode in context [c]. *) +val mdnull : llcontext -> llvalue + (** [get_mdstring v] returns the MDString. See the method [llvm::MDString::getString] *) val get_mdstring : llvalue -> string option @@ -837,15 +862,19 @@ val const_int_of_string : lltype -> string -> int -> llvalue value [n]. See the method [llvm::ConstantFP::get]. *) val const_float : lltype -> float -> llvalue +(** [float_of_const c] returns the float value of the [c] constant float. + None is returned if this is not an float constant. + See the method [llvm::ConstantFP::getDoubleValue].*) +val float_of_const : llvalue -> float option + (** [const_float_of_string ty s] returns the floating point constant of type [ty] and value [n]. See the method [llvm::ConstantFP::get]. *) val const_float_of_string : lltype -> string -> llvalue - (** {7 Operations on composite constants} *) (** [const_string c s] returns the constant [i8] array with the values of the - characters in the string [s] in the context [c]. The array is not + characters in the string [s] in the context [c]. The array is not null-terminated (but see {!const_stringz}). This value can in turn be used as the initializer for a global variable. See the method [llvm::ConstantArray::get]. *) @@ -887,6 +916,14 @@ val const_packed_struct : llcontext -> llvalue array -> llvalue values [elts]. See the method [llvm::ConstantVector::get]. *) val const_vector : llvalue array -> llvalue +(** [string_of_const c] returns [Some str] if [c] is a string constant, + or [None] if this is not a string constant. *) +val string_of_const : llvalue -> string option + +(** [const_element c] returns a constant for a specified index's element. + See the method ConstantDataSequential::getElementAsConstant. *) +val const_element : llvalue -> int -> llvalue + (** {7 Constant expressions} *) @@ -1234,6 +1271,14 @@ val visibility : llvalue -> Visibility.t [v]. See the method [llvm::GlobalValue::setVisibility]. *) val set_visibility : Visibility.t -> llvalue -> unit +(** [dll_storage_class g] returns the DLL storage class of the global value [g]. + See the method [llvm::GlobalValue::getDLLStorageClass]. *) +val dll_storage_class : llvalue -> DLLStorageClass.t + +(** [set_dll_storage_class v g] sets the DLL storage class of the global value [g] to + [v]. See the method [llvm::GlobalValue::setDLLStorageClass]. *) +val set_dll_storage_class : DLLStorageClass.t -> llvalue -> unit + (** [alignment g] returns the required alignment of the global value [g]. See the method [llvm::GlobalValue::getAlignment]. *) val alignment : llvalue -> int @@ -1687,6 +1732,15 @@ val instr_opcode : llvalue -> Opcode.t instruction [i]. *) val icmp_predicate : llvalue -> Icmp.t option +(** [fcmp_predicate i] returns the [fcmp.t] corresponding to an [fcmp] + instruction [i]. *) +val fcmp_predicate : llvalue -> Fcmp.t option + +(** [inst_clone i] returns a copy of instruction [i], + The instruction has no parent, and no name. + See the method [llvm::Instruction::clone]. *) +val instr_clone : llvalue -> llvalue + (** {7 Operations on call sites} *) @@ -1741,6 +1795,52 @@ val is_volatile : llvalue -> bool [llvm::StoreInst::setVolatile]. *) val set_volatile : bool -> llvalue -> unit +(** {7 Operations on terminators} *) + +(** [is_terminator v] returns true if the instruction [v] is a terminator. *) +val is_terminator : llvalue -> bool + +(** [successor v i] returns the successor at index [i] for the value [v]. + See the method [llvm::TerminatorInst::getSuccessor]. *) +val successor : llvalue -> int -> llbasicblock + +(** [set_successor v i o] sets the successor of the value [v] at the index [i] to + the value [o]. + See the method [llvm::TerminatorInst::setSuccessor]. *) +val set_successor : llvalue -> int -> llbasicblock -> unit + +(** [num_successors v] returns the number of successors for the value [v]. + See the method [llvm::TerminatorInst::getNumSuccessors]. *) +val num_successors : llvalue -> int + +(** [successors v] returns the successors of [v]. *) +val successors : llvalue -> llbasicblock array + +(** [iter_successors f v] applies function f to each successor [v] in order. Tail recursive. *) +val iter_successors : (llbasicblock -> unit) -> llvalue -> unit + +(** [fold_successors f v init] is [f (... (f init vN) ...) v1] where [v1,...,vN] are the successors of [v]. Tail recursive. *) +val fold_successors : (llbasicblock -> 'a -> 'a) -> llvalue -> 'a -> 'a + +(** {7 Operations on branches} *) + +(** [is_conditional v] returns true if the branch instruction [v] is conditional. + See the method [llvm::BranchInst::isConditional]. *) +val is_conditional : llvalue -> bool + +(** [condition v] return the condition of the branch instruction [v]. + See the method [llvm::BranchInst::getCondition]. *) +val condition : llvalue -> llvalue + +(** [set_condition v c] sets the condition of the branch instruction [v] to the value [c]. + See the method [llvm::BranchInst::setCondition]. *) +val set_condition : llvalue -> llvalue -> unit + +(** [get_branch c] returns a description of the branch instruction [c]. *) +val get_branch : llvalue -> + [ `Conditional of llvalue * llbasicblock * llbasicblock + | `Unconditional of llbasicblock ] + option (** {7 Operations on phi nodes} *) @@ -2402,7 +2502,7 @@ module MemoryBuffer : sig path [p]. If the file could not be read, then [IoError msg] is raised. *) val of_file : string -> llmemorybuffer - + (** [of_stdin ()] is the memory buffer containing the contents of standard input. If standard input is empty, then [IoError msg] is raised. *) val of_stdin : unit -> llmemorybuffer @@ -2413,7 +2513,7 @@ module MemoryBuffer : sig (** [as_string mb] is the string containing the contents of memory buffer [mb]. *) val as_string : llmemorybuffer -> string - + (** Disposes of a memory buffer. *) val dispose : llmemorybuffer -> unit end @@ -2425,13 +2525,13 @@ module PassManager : sig (** *) type 'a t type any = [ `Module | `Function ] - + (** [PassManager.create ()] constructs a new whole-module pass pipeline. This type of pipeline is suitable for link-time optimization and whole-module transformations. See the constructor of [llvm::PassManager]. *) val create : unit -> [ `Module ] t - + (** [PassManager.create_function m] constructs a new function-by-function pass pipeline over the module [m]. It does not take ownership of [m]. This type of pipeline is suitable for code generation and JIT compilation @@ -2450,19 +2550,19 @@ module PassManager : sig the module, [false] otherwise. See the [llvm::FunctionPassManager::doInitialization] method. *) val initialize : [ `Function ] t -> bool - + (** [run_function f fpm] executes all of the function passes scheduled in the function pass manager [fpm] over the function [f]. Returns [true] if any of the passes modified [f], [false] otherwise. See the [llvm::FunctionPassManager::run] method. *) val run_function : llvalue -> [ `Function ] t -> bool - + (** [finalize fpm] finalizes all of the function passes scheduled in in the function pass manager [fpm]. Returns [true] if any of the passes modified the module, [false] otherwise. See the [llvm::FunctionPassManager::doFinalization] method. *) val finalize : [ `Function ] t -> bool - + (** Frees the memory of a pass pipeline. For function pipelines, does not free the module. See the destructor of [llvm::BasePassManager]. *) diff --git a/bindings/ocaml/llvm/llvm_ocaml.c b/bindings/ocaml/llvm/llvm_ocaml.c index d5ebdcd..1fa4d0f 100644 --- a/bindings/ocaml/llvm/llvm_ocaml.c +++ b/bindings/ocaml/llvm/llvm_ocaml.c @@ -15,46 +15,33 @@ |* *| \*===----------------------------------------------------------------------===*/ +#include +#include +#include #include "llvm-c/Core.h" #include "caml/alloc.h" #include "caml/custom.h" #include "caml/memory.h" #include "caml/fail.h" #include "caml/callback.h" -#include -#include -#include - - -/* Can't use the recommended caml_named_value mechanism for backwards - compatibility reasons. This is largely equivalent. */ -static value llvm_ioerror_exn; -CAMLprim value llvm_register_core_exns(value IoError) { - llvm_ioerror_exn = Field(IoError, 0); - register_global_root(&llvm_ioerror_exn); +value llvm_string_of_message(char* Message) { + value String = caml_copy_string(Message); + LLVMDisposeMessage(Message); - return Val_unit; + return String; } -static void llvm_raise(value Prototype, char *Message) { +void llvm_raise(value Prototype, char *Message) { CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif + caml_raise_with_arg(Prototype, llvm_string_of_message(Message)); + CAMLnoreturn; } static value llvm_fatal_error_handler; static void llvm_fatal_error_trampoline(const char *Reason) { - callback(llvm_fatal_error_handler, copy_string(Reason)); + callback(llvm_fatal_error_handler, caml_copy_string(Reason)); } CAMLprim value llvm_install_fatal_error_handler(value Handler) { @@ -75,6 +62,17 @@ CAMLprim value llvm_enable_pretty_stacktrace(value Unit) { return Val_unit; } +CAMLprim value llvm_parse_command_line_options(value Overview, value Args) { + char *COverview; + if (Overview == Val_int(0)) { + COverview = NULL; + } else { + COverview = String_val(Field(Overview, 0)); + } + LLVMParseCommandLineOptions(Wosize_val(Args), (const char* const*) Op_val(Args), COverview); + return Val_unit; +} + static value alloc_variant(int tag, void *Value) { value Iter = alloc_small(1, tag); Field(Iter, 0) = Val_op(Value); @@ -157,7 +155,7 @@ CAMLprim value llvm_dispose_module(LLVMModuleRef M) { /* llmodule -> string */ CAMLprim value llvm_target_triple(LLVMModuleRef M) { - return copy_string(LLVMGetTarget(M)); + return caml_copy_string(LLVMGetTarget(M)); } /* string -> llmodule -> unit */ @@ -168,7 +166,7 @@ CAMLprim value llvm_set_target_triple(value Trip, LLVMModuleRef M) { /* llmodule -> string */ CAMLprim value llvm_data_layout(LLVMModuleRef M) { - return copy_string(LLVMGetDataLayout(M)); + return caml_copy_string(LLVMGetDataLayout(M)); } /* string -> llmodule -> unit */ @@ -186,22 +184,24 @@ CAMLprim value llvm_dump_module(LLVMModuleRef M) { /* string -> llmodule -> unit */ CAMLprim value llvm_print_module(value Filename, LLVMModuleRef M) { char* Message; - if(LLVMPrintModuleToFile(M, String_val(Filename), &Message)) { - llvm_raise(llvm_ioerror_exn, Message); - } + + if(LLVMPrintModuleToFile(M, String_val(Filename), &Message)) + llvm_raise(*caml_named_value("Llvm.IoError"), Message); return Val_unit; } /* llmodule -> string */ CAMLprim value llvm_string_of_llmodule(LLVMModuleRef M) { + CAMLparam0(); + CAMLlocal1(ModuleStr); char* ModuleCStr; - ModuleCStr = LLVMPrintModuleToString(M); - value ModuleStr = caml_copy_string(ModuleCStr); + ModuleCStr = LLVMPrintModuleToString(M); + ModuleStr = caml_copy_string(ModuleCStr); LLVMDisposeMessage(ModuleCStr); - return ModuleStr; + CAMLreturn(ModuleStr); } /* llmodule -> string -> unit */ @@ -234,13 +234,15 @@ CAMLprim value llvm_dump_type(LLVMTypeRef Val) { /* lltype -> string */ CAMLprim value llvm_string_of_lltype(LLVMTypeRef M) { + CAMLparam0(); + CAMLlocal1(TypeStr); char* TypeCStr; - TypeCStr = LLVMPrintTypeToString(M); - value TypeStr = caml_copy_string(TypeCStr); + TypeCStr = LLVMPrintTypeToString(M); + TypeStr = caml_copy_string(TypeCStr); LLVMDisposeMessage(TypeCStr); - return TypeStr; + CAMLreturn(TypeStr); } /*--... Operations on integer types ........................................--*/ @@ -537,7 +539,7 @@ CAMLprim value llvm_classify_value(LLVMValueRef Val) { /* llvalue -> string */ CAMLprim value llvm_value_name(LLVMValueRef Val) { - return copy_string(LLVMGetValueName(Val)); + return caml_copy_string(LLVMGetValueName(Val)); } /* string -> llvalue -> unit */ @@ -554,13 +556,15 @@ CAMLprim value llvm_dump_value(LLVMValueRef Val) { /* llvalue -> string */ CAMLprim value llvm_string_of_llvalue(LLVMValueRef M) { + CAMLparam0(); + CAMLlocal1(ValueStr); char* ValueCStr; - ValueCStr = LLVMPrintValueToString(M); - value ValueStr = caml_copy_string(ValueCStr); + ValueCStr = LLVMPrintValueToString(M); + ValueStr = caml_copy_string(ValueCStr); LLVMDisposeMessage(ValueCStr); - return ValueStr; + CAMLreturn(ValueStr); } /* llvalue -> llvalue -> unit */ @@ -577,6 +581,11 @@ CAMLprim LLVMValueRef llvm_operand(LLVMValueRef V, value I) { return LLVMGetOperand(V, Int_val(I)); } +/* llvalue -> int -> lluse */ +CAMLprim LLVMUseRef llvm_operand_use(LLVMValueRef V, value I) { + return LLVMGetOperandUse(V, Int_val(I)); +} + /* llvalue -> int -> llvalue -> unit */ CAMLprim value llvm_set_operand(LLVMValueRef U, value I, LLVMValueRef V) { LLVMSetOperand(U, Int_val(I), V); @@ -657,6 +666,11 @@ CAMLprim LLVMValueRef llvm_mdnode(LLVMContextRef C, value ElementVals) { Wosize_val(ElementVals)); } +/* llcontext -> llvalue */ +CAMLprim LLVMValueRef llvm_mdnull(LLVMContextRef C) { + return NULL; +} + /* llvalue -> string option */ CAMLprim value llvm_get_mdstring(LLVMValueRef V) { CAMLparam0(); @@ -695,7 +709,7 @@ CAMLprim value llvm_append_namedmd(LLVMModuleRef M, value Name, LLVMValueRef Val /* lltype -> int -> llvalue */ CAMLprim LLVMValueRef llvm_const_int(LLVMTypeRef IntTy, value N) { - return LLVMConstInt(IntTy, (long long) Int_val(N), 1); + return LLVMConstInt(IntTy, (long long) Long_val(N), 1); } /* lltype -> Int64.t -> bool -> llvalue */ @@ -729,6 +743,28 @@ CAMLprim LLVMValueRef llvm_const_float(LLVMTypeRef RealTy, value N) { return LLVMConstReal(RealTy, Double_val(N)); } + +/* llvalue -> float */ +CAMLprim value llvm_float_of_const(LLVMValueRef Const) +{ + CAMLparam0(); + CAMLlocal1(Option); + LLVMBool LosesInfo; + double Result; + + if (LLVMIsAConstantFP(Const)) { + Result = LLVMConstRealGetDouble(Const, &LosesInfo); + if (LosesInfo) + CAMLreturn(Val_int(0)); + + Option = alloc(1, 0); + Field(Option, 0) = caml_copy_double(Result); + CAMLreturn(Option); + } + + CAMLreturn(Val_int(0)); +} + /* lltype -> string -> llvalue */ CAMLprim LLVMValueRef llvm_const_float_of_string(LLVMTypeRef RealTy, value S) { return LLVMConstRealOfStringAndSize(RealTy, String_val(S), @@ -782,6 +818,31 @@ CAMLprim LLVMValueRef llvm_const_vector(value ElementVals) { Wosize_val(ElementVals)); } +/* llvalue -> string option */ +CAMLprim value llvm_string_of_const(LLVMValueRef Const) { + const char *S; + size_t Len; + CAMLparam0(); + CAMLlocal2(Option, Str); + + if(LLVMIsAConstantDataSequential(Const) && LLVMIsConstantString(Const)) { + S = LLVMGetAsString(Const, &Len); + Str = caml_alloc_string(Len); + memcpy(String_val(Str), S, Len); + + Option = alloc(1, 0); + Field(Option, 0) = Str; + CAMLreturn(Option); + } else { + CAMLreturn(Val_int(0)); + } +} + +/* llvalue -> int -> llvalue */ +CAMLprim LLVMValueRef llvm_const_element(LLVMValueRef Const, value N) { + return LLVMGetElementAsConstant(Const, Int_val(N)); +} + /*--... Constant expressions ...............................................--*/ /* Icmp.t -> llvalue -> llvalue -> llvalue */ @@ -881,7 +942,7 @@ CAMLprim value llvm_set_linkage(value Linkage, LLVMValueRef Global) { /* llvalue -> string */ CAMLprim value llvm_section(LLVMValueRef Global) { - return copy_string(LLVMGetSection(Global)); + return caml_copy_string(LLVMGetSection(Global)); } /* string -> llvalue -> unit */ @@ -901,6 +962,17 @@ CAMLprim value llvm_set_visibility(value Viz, LLVMValueRef Global) { return Val_unit; } +/* llvalue -> DLLStorageClass.t */ +CAMLprim value llvm_dll_storage_class(LLVMValueRef Global) { + return Val_int(LLVMGetDLLStorageClass(Global)); +} + +/* DLLStorageClass.t -> llvalue -> unit */ +CAMLprim value llvm_set_dll_storage_class(value Viz, LLVMValueRef Global) { + LLVMSetDLLStorageClass(Global, Int_val(Viz)); + return Val_unit; +} + /* llvalue -> int */ CAMLprim value llvm_alignment(LLVMValueRef Global) { return Val_int(LLVMGetAlignment(Global)); @@ -1151,10 +1223,10 @@ CAMLprim value llvm_gc(LLVMValueRef Fn) { const char *GC; CAMLparam0(); CAMLlocal2(Name, Option); - + if ((GC = LLVMGetGC(Fn))) { - Name = copy_string(GC); - + Name = caml_copy_string(GC); + Option = alloc(1, 0); Field(Option, 0) = Name; CAMLreturn(Option); @@ -1328,6 +1400,25 @@ CAMLprim value llvm_instr_icmp_predicate(LLVMValueRef Val) { CAMLreturn(Val_int(0)); } +/* llvalue -> FCmp.t option */ +CAMLprim value llvm_instr_fcmp_predicate(LLVMValueRef Val) { + CAMLparam0(); + int x = LLVMGetFCmpPredicate(Val); + if (x) { + value Option = alloc(1, 0); + Field(Option, 0) = Val_int(x - LLVMRealPredicateFalse); + CAMLreturn(Option); + } + CAMLreturn(Val_int(0)); +} + +/* llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_instr_clone(LLVMValueRef Inst) { + if (!LLVMIsAInstruction(Inst)) + failwith("Not an instruction"); + return LLVMInstructionClone(Inst); +} + /*--... Operations on call sites ...........................................--*/ @@ -1386,6 +1477,43 @@ CAMLprim value llvm_set_volatile(value IsVolatile, return Val_unit; } + +/*--.. Operations on terminators ...........................................--*/ + +/* llvalue -> int -> llbasicblock */ +CAMLprim LLVMBasicBlockRef llvm_successor(LLVMValueRef V, value I) { + return LLVMGetSuccessor(V, Int_val(I)); +} + +/* llvalue -> int -> llvalue -> unit */ +CAMLprim value llvm_set_successor(LLVMValueRef U, value I, LLVMBasicBlockRef B) { + LLVMSetSuccessor(U, Int_val(I), B); + return Val_unit; +} + +/* llvalue -> int */ +CAMLprim value llvm_num_successors(LLVMValueRef V) { + return Val_int(LLVMGetNumSuccessors(V)); +} + +/*--.. Operations on branch ................................................--*/ + +/* llvalue -> llvalue */ +CAMLprim LLVMValueRef llvm_condition(LLVMValueRef V) { + return LLVMGetCondition(V); +} + +/* llvalue -> llvalue -> unit */ +CAMLprim value llvm_set_condition(LLVMValueRef B, LLVMValueRef C) { + LLVMSetCondition(B, C); + return Val_unit; +} + +/* llvalue -> bool */ +CAMLprim value llvm_is_conditional(LLVMValueRef V) { + return Val_bool(LLVMIsConditional(V)); +} + /*--... Operations on phi nodes ............................................--*/ /* (llvalue * llbasicblock) -> llvalue -> unit */ @@ -1402,20 +1530,20 @@ CAMLprim value llvm_incoming(LLVMValueRef PhiNode) { unsigned I; CAMLparam0(); CAMLlocal3(Hd, Tl, Tmp); - + /* Build a tuple list of them. */ Tl = Val_int(0); for (I = LLVMCountIncoming(PhiNode); I != 0; ) { Hd = alloc(2, 0); Store_field(Hd, 0, (value) LLVMGetIncomingValue(PhiNode, --I)); Store_field(Hd, 1, (value) LLVMGetIncomingBlock(PhiNode, I)); - + Tmp = alloc(2, 0); Store_field(Tmp, 0, Hd); Store_field(Tmp, 1, Tl); Tl = Tmp; } - + CAMLreturn(Tl); } @@ -1434,15 +1562,13 @@ static void llvm_finalize_builder(value B) { } static struct custom_operations builder_ops = { - (char *) "LLVMIRBuilder", + (char *) "Llvm.llbuilder", llvm_finalize_builder, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; static value alloc_builder(LLVMBuilderRef B) { @@ -1472,7 +1598,7 @@ CAMLprim value llvm_position_builder(value Pos, value B) { CAMLprim LLVMBasicBlockRef llvm_insertion_block(value B) { LLVMBasicBlockRef InsertBlock = LLVMGetInsertBlock(Builder_val(B)); if (!InsertBlock) - raise_not_found(); + caml_raise_not_found(); return InsertBlock; } @@ -2048,9 +2174,9 @@ CAMLprim LLVMValueRef llvm_build_fcmp(value Pred, CAMLprim LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) { value Hd, Tl; LLVMValueRef FirstValue, PhiNode; - + assert(Incoming != Val_int(0) && "Empty list passed to Llvm.build_phi!"); - + Hd = Field(Incoming, 0); FirstValue = (LLVMValueRef) Field(Hd, 0); PhiNode = LLVMBuildPhi(Builder_val(B), LLVMTypeOf(FirstValue), @@ -2061,7 +2187,7 @@ CAMLprim LLVMValueRef llvm_build_phi(value Incoming, value Name, value B) { LLVMAddIncoming(PhiNode, (LLVMValueRef*) &Field(Hd, 0), (LLVMBasicBlockRef*) &Field(Hd, 1), 1); } - + return PhiNode; } @@ -2097,7 +2223,7 @@ CAMLprim LLVMValueRef llvm_build_insertelement(LLVMValueRef Vec, LLVMValueRef Element, LLVMValueRef Idx, value Name, value B) { - return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx, + return LLVMBuildInsertElement(Builder_val(B), Vec, Element, Idx, String_val(Name)); } @@ -2149,11 +2275,11 @@ CAMLprim value llvm_memorybuffer_of_file(value Path) { CAMLparam1(Path); char *Message; LLVMMemoryBufferRef MemBuf; - + if (LLVMCreateMemoryBufferWithContentsOfFile(String_val(Path), &MemBuf, &Message)) - llvm_raise(llvm_ioerror_exn, Message); - + llvm_raise(*caml_named_value("Llvm.IoError"), Message); + CAMLreturn((value) MemBuf); } @@ -2162,22 +2288,23 @@ CAMLprim value llvm_memorybuffer_of_file(value Path) { CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_stdin(value Unit) { char *Message; LLVMMemoryBufferRef MemBuf; - + if (LLVMCreateMemoryBufferWithSTDIN(&MemBuf, &Message)) - llvm_raise(llvm_ioerror_exn, Message); - + llvm_raise(*caml_named_value("Llvm.IoError"), Message); + return MemBuf; } /* ?name:string -> string -> llmemorybuffer */ CAMLprim LLVMMemoryBufferRef llvm_memorybuffer_of_string(value Name, value String) { + LLVMMemoryBufferRef MemBuf; const char *NameCStr; + if(Name == Val_int(0)) NameCStr = ""; else NameCStr = String_val(Field(Name, 0)); - LLVMMemoryBufferRef MemBuf; MemBuf = LLVMCreateMemoryBufferWithMemoryRangeCopy( String_val(String), caml_string_length(String), NameCStr); diff --git a/bindings/ocaml/target/CMakeLists.txt b/bindings/ocaml/target/CMakeLists.txt new file mode 100644 index 0000000..adee0fc --- /dev/null +++ b/bindings/ocaml/target/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_target + OCAML llvm_target + OCAMLDEP llvm + C target_ocaml + LLVM target) diff --git a/bindings/ocaml/target/llvm_target.ml b/bindings/ocaml/target/llvm_target.ml index 974bd49..bd7388e 100644 --- a/bindings/ocaml/target/llvm_target.ml +++ b/bindings/ocaml/target/llvm_target.ml @@ -47,8 +47,7 @@ end exception Error of string -external register_exns : exn -> unit = "llvm_register_target_exns" -let _ = register_exns (Error "") +let () = Callback.register_exception "Llvm_target.Error" (Error "") module DataLayout = struct type t @@ -127,6 +126,8 @@ module TargetMachine = struct = "llvm_targetmachine_features" external data_layout : t -> DataLayout.t = "llvm_targetmachine_data_layout" + external add_analysis_passes : [< Llvm.PassManager.any ] Llvm.PassManager.t -> t -> unit + = "llvm_targetmachine_add_analysis_passes" external set_verbose_asm : bool -> t -> unit = "llvm_targetmachine_set_verbose_asm" external emit_to_file : Llvm.llmodule -> CodeGenFileType.t -> string -> diff --git a/bindings/ocaml/target/llvm_target.mli b/bindings/ocaml/target/llvm_target.mli index 4f5e717..676bc61 100644 --- a/bindings/ocaml/target/llvm_target.mli +++ b/bindings/ocaml/target/llvm_target.mli @@ -67,7 +67,7 @@ module DataLayout : sig See the method [llvm::DataLayout::getStringRepresentation]. *) val as_string : t -> string - (** [add_to_pass_manager dl pm] adds the target data [dl] to + (** [add_to_pass_manager pm dl] adds the data layout [dl] to the pass manager [pm]. See the method [llvm::PassManagerBase::add]. *) val add_to_pass_manager : [ @@ -207,6 +207,10 @@ module TargetMachine : sig (** Returns the data layout of this target machine. *) val data_layout : t -> DataLayout.t + (** Adds the target-specific analysis passes to the pass manager. + See [llvm::TargetMachine::addAnalysisPasses]. *) + val add_analysis_passes : [< Llvm.PassManager.any ] Llvm.PassManager.t -> t -> unit + (** Sets the assembly verbosity of this target machine. See [llvm::TargetMachine::setAsmVerbosity]. *) val set_verbose_asm : bool -> t -> unit diff --git a/bindings/ocaml/target/target_ocaml.c b/bindings/ocaml/target/target_ocaml.c index 74e8185..8f77cb4 100644 --- a/bindings/ocaml/target/target_ocaml.c +++ b/bindings/ocaml/target/target_ocaml.c @@ -21,37 +21,10 @@ #include "caml/fail.h" #include "caml/memory.h" #include "caml/custom.h" +#include "caml/callback.h" -/*===---- Exceptions ------------------------------------------------------===*/ - -static value llvm_target_error_exn; - -CAMLprim value llvm_register_target_exns(value Error) { - llvm_target_error_exn = Field(Error, 0); - register_global_root(&llvm_target_error_exn); - return Val_unit; -} - -static void llvm_raise(value Prototype, char *Message) { - CAMLparam1(Prototype); - CAMLlocal1(CamlMessage); - - CamlMessage = copy_string(Message); - LLVMDisposeMessage(Message); - - raise_with_arg(Prototype, CamlMessage); - abort(); /* NOTREACHED */ -#ifdef CAMLnoreturn - CAMLnoreturn; /* Silences warnings, but is missing in some versions. */ -#endif -} - -static value llvm_string_of_message(char* Message) { - value String = caml_copy_string(Message); - LLVMDisposeMessage(Message); - - return String; -} +void llvm_raise(value Prototype, char *Message); +value llvm_string_of_message(char* Message); /*===---- Data Layout -----------------------------------------------------===*/ @@ -62,15 +35,13 @@ static void llvm_finalize_data_layout(value DataLayout) { } static struct custom_operations llvm_data_layout_ops = { - (char *) "LLVMDataLayout", + (char *) "Llvm_target.DataLayout.t", llvm_finalize_data_layout, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; value llvm_alloc_data_layout(LLVMTargetDataRef DataLayout) { @@ -219,7 +190,7 @@ CAMLprim LLVMTargetRef llvm_target_by_triple(value Triple) { char *Error; if(LLVMGetTargetFromTriple(String_val(Triple), &T, &Error)) - llvm_raise(llvm_target_error_exn, Error); + llvm_raise(*caml_named_value("Llvm_target.Error"), Error); return T; } @@ -258,15 +229,13 @@ static void llvm_finalize_target_machine(value Machine) { } static struct custom_operations llvm_target_machine_ops = { - (char *) "LLVMTargetMachine", + (char *) "Llvm_target.TargetMachine.t", llvm_finalize_target_machine, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; static value llvm_alloc_targetmachine(LLVMTargetMachineRef Machine) { @@ -337,6 +306,7 @@ CAMLprim value llvm_targetmachine_features(value Machine) { CAMLprim value llvm_targetmachine_data_layout(value Machine) { CAMLparam1(Machine); CAMLlocal1(DataLayout); + char *TargetDataCStr; /* LLVMGetTargetMachineData returns a pointer owned by the TargetMachine, so it is impossible to wrap it with llvm_alloc_target_data, which assumes @@ -344,7 +314,6 @@ CAMLprim value llvm_targetmachine_data_layout(value Machine) { LLVMTargetDataRef OrigDataLayout; OrigDataLayout = LLVMGetTargetMachineData(TargetMachine_val(Machine)); - char* TargetDataCStr; TargetDataCStr = LLVMCopyStringRepOfTargetData(OrigDataLayout); DataLayout = llvm_alloc_data_layout(LLVMCreateTargetData(TargetDataCStr)); LLVMDisposeMessage(TargetDataCStr); @@ -361,12 +330,12 @@ CAMLprim value llvm_targetmachine_set_verbose_asm(value Verb, value Machine) { /* Llvm.llmodule -> CodeGenFileType.t -> string -> TargetMachine.t -> unit */ CAMLprim value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, value FileType, value FileName, value Machine) { - char* ErrorMessage; + char *ErrorMessage; if(LLVMTargetMachineEmitToFile(TargetMachine_val(Machine), Module, String_val(FileName), Int_val(FileType), &ErrorMessage)) { - llvm_raise(llvm_target_error_exn, ErrorMessage); + llvm_raise(*caml_named_value("Llvm_target.Error"), ErrorMessage); } return Val_unit; @@ -377,14 +346,21 @@ CAMLprim value llvm_targetmachine_emit_to_file(LLVMModuleRef Module, CAMLprim LLVMMemoryBufferRef llvm_targetmachine_emit_to_memory_buffer( LLVMModuleRef Module, value FileType, value Machine) { - char* ErrorMessage; + char *ErrorMessage; LLVMMemoryBufferRef Buffer; if(LLVMTargetMachineEmitToMemoryBuffer(TargetMachine_val(Machine), Module, Int_val(FileType), &ErrorMessage, &Buffer)) { - llvm_raise(llvm_target_error_exn, ErrorMessage); + llvm_raise(*caml_named_value("Llvm_target.Error"), ErrorMessage); } return Buffer; } + +/* TargetMachine.t -> Llvm.PassManager.t -> unit */ +CAMLprim value llvm_targetmachine_add_analysis_passes(LLVMPassManagerRef PM, + value Machine) { + LLVMAddAnalysisPasses(TargetMachine_val(Machine), PM); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/CMakeLists.txt b/bindings/ocaml/transforms/CMakeLists.txt new file mode 100644 index 0000000..beb8694 --- /dev/null +++ b/bindings/ocaml/transforms/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(ipo) +add_subdirectory(passmgr_builder) +add_subdirectory(scalar_opts) +add_subdirectory(utils) +add_subdirectory(vectorize) diff --git a/bindings/ocaml/transforms/Makefile b/bindings/ocaml/transforms/Makefile index 92c8396..15bffb4 100644 --- a/bindings/ocaml/transforms/Makefile +++ b/bindings/ocaml/transforms/Makefile @@ -8,7 +8,7 @@ ##===----------------------------------------------------------------------===## LEVEL := ../../.. -DIRS = scalar ipo vectorize passmgr_builder +DIRS = ipo passmgr_builder scalar_opts utils vectorize ocamldoc: $(Verb) for i in $(DIRS) ; do \ diff --git a/bindings/ocaml/transforms/ipo/CMakeLists.txt b/bindings/ocaml/transforms/ipo/CMakeLists.txt new file mode 100644 index 0000000..4b8784f --- /dev/null +++ b/bindings/ocaml/transforms/ipo/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_ipo + OCAML llvm_ipo + OCAMLDEP llvm + C ipo_ocaml + LLVM ipo) diff --git a/bindings/ocaml/transforms/ipo/Makefile b/bindings/ocaml/transforms/ipo/Makefile index ed67a7c..f54bc4e 100644 --- a/bindings/ocaml/transforms/ipo/Makefile +++ b/bindings/ocaml/transforms/ipo/Makefile @@ -1,4 +1,4 @@ -##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===## +##===- bindings/ocaml/transforms/ipo/Makefile --------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## # -# This is the makefile for the Objective Caml Llvm_scalar_opts interface. +# This is the makefile for the Objective Caml Llvm_ipo interface. # ##===----------------------------------------------------------------------===## diff --git a/bindings/ocaml/transforms/ipo/ipo_ocaml.c b/bindings/ocaml/transforms/ipo/ipo_ocaml.c index 4ad8afb..9d8fb1e 100644 --- a/bindings/ocaml/transforms/ipo/ipo_ocaml.c +++ b/bindings/ocaml/transforms/ipo/ipo_ocaml.c @@ -56,12 +56,6 @@ CAMLprim value llvm_add_always_inliner(LLVMPassManagerRef PM) { } /* [`Module] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_always_inliner_pass(LLVMPassManagerRef PM) { - LLVMAddAlwaysInlinerPass(PM); - return Val_unit; -} - -/* [`Module] Llvm.PassManager.t -> unit */ CAMLprim value llvm_add_global_dce(LLVMPassManagerRef PM) { LLVMAddGlobalDCEPass(PM); return Val_unit; @@ -74,7 +68,7 @@ CAMLprim value llvm_add_global_optimizer(LLVMPassManagerRef PM) { } /* [`Module] Llvm.PassManager.t -> unit */ -CAMLprim value llvm_add_ipc_propagation(LLVMPassManagerRef PM) { +CAMLprim value llvm_add_ip_constant_propagation(LLVMPassManagerRef PM) { LLVMAddIPConstantPropagationPass(PM); return Val_unit; } @@ -91,7 +85,7 @@ CAMLprim value llvm_add_ipsccp(LLVMPassManagerRef PM) { return Val_unit; } -/* [`Module] Llvm.PassManager.t -> bool -> unit */ +/* [`Module] Llvm.PassManager.t -> all_but_main:bool -> unit */ CAMLprim value llvm_add_internalize(LLVMPassManagerRef PM, value AllButMain) { LLVMAddInternalizePass(PM, Bool_val(AllButMain)); return Val_unit; diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.ml b/bindings/ocaml/transforms/ipo/llvm_ipo.ml index 93f564a..1af7d67 100644 --- a/bindings/ocaml/transforms/ipo/llvm_ipo.ml +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.ml @@ -7,31 +7,45 @@ * *===----------------------------------------------------------------------===*) -external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_argument_promotion" -external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_constant_merge" -external add_dead_arg_elimination : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination" -external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_attrs" -external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_inlining" -external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_always_inliner" -external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_dce" -external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_optimizer" -external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipc_propagation" -external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_prune_eh" -external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipsccp" -external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit = - "llvm_add_internalize" -external add_strip_dead_prototypes : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes" -external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_strip_symbols" +external add_argument_promotion + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_argument_promotion" +external add_constant_merge + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_constant_merge" +external add_dead_arg_elimination + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_dead_arg_elimination" +external add_function_attrs + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_attrs" +external add_function_inlining + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_inlining" +external add_always_inliner + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_always_inliner" +external add_global_dce + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_dce" +external add_global_optimizer + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_optimizer" +external add_ipc_propagation + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ip_constant_propagation" +external add_prune_eh + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_prune_eh" +external add_ipsccp + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ipsccp" +external add_internalize + : [ `Module ] Llvm.PassManager.t -> all_but_main:bool -> unit + = "llvm_add_internalize" +external add_strip_dead_prototypes + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_dead_prototypes" +external add_strip_symbols + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_symbols" diff --git a/bindings/ocaml/transforms/ipo/llvm_ipo.mli b/bindings/ocaml/transforms/ipo/llvm_ipo.mli index 1944c30..09a4860 100644 --- a/bindings/ocaml/transforms/ipo/llvm_ipo.mli +++ b/bindings/ocaml/transforms/ipo/llvm_ipo.mli @@ -12,58 +12,72 @@ This interface provides an OCaml API for LLVM interprocedural optimizations, the classes in the [LLVMIPO] library. *) -(** See llvm::createAddArgumentPromotionPass *) -external add_argument_promotion : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_argument_promotion" - -(** See llvm::createConstantMergePass function. *) -external add_constant_merge : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_constant_merge" - -(** See llvm::createDeadArgEliminationPass function. *) -external add_dead_arg_elimination : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_dead_arg_elimination" - -(** See llvm::createFunctionAttrsPass function. *) -external add_function_attrs : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_attrs" - -(** See llvm::createFunctionInliningPass function. *) -external add_function_inlining : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_function_inlining" - -(** See llvm::createAlwaysInlinerPass function. *) -external add_always_inliner : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_always_inliner" - -(** See llvm::createGlobalDCEPass function. *) -external add_global_dce : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_dce" - -(** See llvm::createGlobalOptimizerPass function. *) -external add_global_optimizer : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_global_optimizer" - -(** See llvm::createIPConstantPropagationPass function. *) -external add_ipc_propagation : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipc_propagation" - -(** See llvm::createPruneEHPass function. *) -external add_prune_eh : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_prune_eh" - -(** See llvm::createIPSCCPPass function. *) -external add_ipsccp : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_ipsccp" - -(** See llvm::createInternalizePass function. *) -external add_internalize : [ | `Module ] Llvm.PassManager.t -> bool -> unit = - "llvm_add_internalize" - -(** See llvm::createStripDeadPrototypesPass function. *) -external add_strip_dead_prototypes : - [ | `Module ] Llvm.PassManager.t -> unit = "llvm_add_strip_dead_prototypes" - -(** See llvm::createStripSymbolsPass function. *) -external add_strip_symbols : [ | `Module ] Llvm.PassManager.t -> unit = - "llvm_add_strip_symbols" +(** See the [llvm::createAddArgumentPromotionPass] function. *) +external add_argument_promotion + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_argument_promotion" + +(** See the [llvm::createConstantMergePass] function. *) +external add_constant_merge + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_constant_merge" + +(** See the [llvm::createDeadArgEliminationPass] function. *) +external add_dead_arg_elimination + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_dead_arg_elimination" + +(** See the [llvm::createFunctionAttrsPass] function. *) +external add_function_attrs + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_attrs" + +(** See the [llvm::createFunctionInliningPass] function. *) +external add_function_inlining + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_function_inlining" + +(** See the [llvm::createAlwaysInlinerPass] function. *) +external add_always_inliner + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_always_inliner" + +(** See the [llvm::createGlobalDCEPass] function. *) +external add_global_dce + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_dce" + +(** See the [llvm::createGlobalOptimizerPass] function. *) +external add_global_optimizer + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_global_optimizer" + +(** See the [llvm::createIPConstantPropagationPass] function. *) +external add_ipc_propagation + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ip_constant_propagation" + +(** See the [llvm::createPruneEHPass] function. *) +external add_prune_eh + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_prune_eh" + +(** See the [llvm::createIPSCCPPass] function. *) +external add_ipsccp + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_ipsccp" + +(** See the [llvm::createInternalizePass] function. *) +external add_internalize + : [ `Module ] Llvm.PassManager.t -> all_but_main:bool -> unit + = "llvm_add_internalize" + +(** See the [llvm::createStripDeadPrototypesPass] function. *) +external add_strip_dead_prototypes + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_dead_prototypes" + +(** See the [llvm::createStripSymbolsPass] function. *) +external add_strip_symbols + : [ `Module ] Llvm.PassManager.t -> unit + = "llvm_add_strip_symbols" diff --git a/bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt b/bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt new file mode 100644 index 0000000..b012863 --- /dev/null +++ b/bindings/ocaml/transforms/passmgr_builder/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_passmgr_builder + OCAML llvm_passmgr_builder + OCAMLDEP llvm + C passmgr_builder_ocaml + LLVM ipo) diff --git a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli index 66b0981..ce162b1 100644 --- a/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli +++ b/bindings/ocaml/transforms/passmgr_builder/llvm_passmgr_builder.mli @@ -14,41 +14,41 @@ type t -(** See [llvm::PassManagerBuilder]. *) +(** See the [llvm::PassManagerBuilder] function. *) external create : unit -> t = "llvm_pmbuilder_create" -(** See [llvm::PassManagerBuilder::OptLevel]. *) +(** See the [llvm::PassManagerBuilder::OptLevel] function. *) external set_opt_level : int -> t -> unit = "llvm_pmbuilder_set_opt_level" -(** See [llvm::PassManagerBuilder::SizeLevel]. *) +(** See the [llvm::PassManagerBuilder::SizeLevel] function. *) external set_size_level : int -> t -> unit = "llvm_pmbuilder_set_size_level" -(** See [llvm::PassManagerBuilder::DisableUnitAtATime]. *) +(** See the [llvm::PassManagerBuilder::DisableUnitAtATime] function. *) external set_disable_unit_at_a_time : bool -> t -> unit = "llvm_pmbuilder_set_disable_unit_at_a_time" -(** See [llvm::PassManagerBuilder::DisableUnrollLoops]. *) +(** See the [llvm::PassManagerBuilder::DisableUnrollLoops] function. *) external set_disable_unroll_loops : bool -> t -> unit = "llvm_pmbuilder_set_disable_unroll_loops" -(** See [llvm::PassManagerBuilder::Inliner]. *) +(** See the [llvm::PassManagerBuilder::Inliner] function. *) external use_inliner_with_threshold : int -> t -> unit = "llvm_pmbuilder_use_inliner_with_threshold" -(** See [llvm::PassManagerBuilder::populateFunctionPassManager]. *) +(** See the [llvm::PassManagerBuilder::populateFunctionPassManager] function. *) external populate_function_pass_manager : [ `Function ] Llvm.PassManager.t -> t -> unit = "llvm_pmbuilder_populate_function_pass_manager" -(** See [llvm::PassManagerBuilder::populateModulePassManager]. *) +(** See the [llvm::PassManagerBuilder::populateModulePassManager] function. *) external populate_module_pass_manager : [ `Module ] Llvm.PassManager.t -> t -> unit = "llvm_pmbuilder_populate_module_pass_manager" -(** See [llvm::PassManagerBuilder::populateLTOPassManager]. *) +(** See the [llvm::PassManagerBuilder::populateLTOPassManager] function. *) external populate_lto_pass_manager : [ `Module ] Llvm.PassManager.t -> internalize:bool -> run_inliner:bool -> t -> unit - = "llvm_pmbuilder_populate_lto_pass_manager" \ No newline at end of file + = "llvm_pmbuilder_populate_lto_pass_manager" diff --git a/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c index a707856..a43863c 100644 --- a/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c +++ b/bindings/ocaml/transforms/passmgr_builder/passmgr_builder_ocaml.c @@ -27,15 +27,13 @@ static void llvm_finalize_pmbuilder(value PMB) { } static struct custom_operations pmbuilder_ops = { - (char *) "LLVMPassManagerBuilder", + (char *) "Llvm_passmgr_builder.t", llvm_finalize_pmbuilder, custom_compare_default, custom_hash_default, custom_serialize_default, - custom_deserialize_default -#ifdef custom_compare_ext_default - , custom_compare_ext_default -#endif + custom_deserialize_default, + custom_compare_ext_default }; static value alloc_pmbuilder(LLVMPassManagerBuilderRef Ref) { diff --git a/bindings/ocaml/transforms/scalar/Makefile b/bindings/ocaml/transforms/scalar/Makefile deleted file mode 100644 index 6e250f6..0000000 --- a/bindings/ocaml/transforms/scalar/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -##===- bindings/ocaml/transforms/scalar/Makefile -----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -# -# This is the makefile for the Objective Caml Llvm_scalar_opts interface. -# -##===----------------------------------------------------------------------===## - -LEVEL := ../../../.. -LIBRARYNAME := llvm_scalar_opts -UsedComponents := scalaropts -UsedOcamlInterfaces := llvm - -include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml deleted file mode 100644 index 958939d..0000000 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.ml +++ /dev/null @@ -1,114 +0,0 @@ -(*===-- llvm_scalar_opts.ml - LLVM OCaml Interface -------------*- OCaml -*-===* - * - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - * - *===----------------------------------------------------------------------===*) - -external add_constant_propagation : [ unit - = "llvm_add_constant_propagation" -external add_sccp : [ unit - = "llvm_add_sccp" -external add_dead_store_elimination : [ unit - = "llvm_add_dead_store_elimination" -external add_aggressive_dce : [ unit - = "llvm_add_aggressive_dce" -external -add_scalar_repl_aggregation : [ unit - = "llvm_add_scalar_repl_aggregation" - -external -add_scalar_repl_aggregation_ssa : [ unit - = "llvm_add_scalar_repl_aggregation_ssa" - -external -add_scalar_repl_aggregation_with_threshold : int -> [ unit - = "llvm_add_scalar_repl_aggregation_with_threshold" -external add_ind_var_simplification : [ unit - = "llvm_add_ind_var_simplification" -external -add_instruction_combination : [ unit - = "llvm_add_instruction_combination" -external add_licm : [ unit - = "llvm_add_licm" -external add_loop_unswitch : [ unit - = "llvm_add_loop_unswitch" -external add_loop_unroll : [ unit - = "llvm_add_loop_unroll" -external add_loop_rotation : [ unit - = "llvm_add_loop_rotation" -external -add_memory_to_register_promotion : [ unit - = "llvm_add_memory_to_register_promotion" -external -add_memory_to_register_demotion : [ unit - = "llvm_add_memory_to_register_demotion" -external add_reassociation : [ unit - = "llvm_add_reassociation" -external add_jump_threading : [ unit - = "llvm_add_jump_threading" -external add_cfg_simplification : [ unit - = "llvm_add_cfg_simplification" -external -add_tail_call_elimination : [ unit - = "llvm_add_tail_call_elimination" -external add_gvn : [ unit - = "llvm_add_gvn" -external add_memcpy_opt : [ unit - = "llvm_add_memcpy_opt" -external add_loop_deletion : [ unit - = "llvm_add_loop_deletion" - -external add_loop_idiom : [ unit - = "llvm_add_loop_idiom" - -external -add_lib_call_simplification : [ unit - = "llvm_add_lib_call_simplification" - -external -add_verifier : [ unit - = "llvm_add_verifier" - -external -add_correlated_value_propagation : [ unit - = "llvm_add_correlated_value_propagation" - -external -add_early_cse : [ unit - = "llvm_add_early_cse" - -external -add_lower_expect_intrinsic : [ unit - = "llvm_add_lower_expect_intrinsic" - -external -add_type_based_alias_analysis : [ unit - = "llvm_add_type_based_alias_analysis" - -external -add_basic_alias_analysis : [ unit - = "llvm_add_basic_alias_analysis" - -external -add_partially_inline_lib_calls : [ unit - = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli deleted file mode 100644 index ab6fa4a..0000000 --- a/bindings/ocaml/transforms/scalar/llvm_scalar_opts.mli +++ /dev/null @@ -1,168 +0,0 @@ -(*===-- llvm_scalar_opts.mli - LLVM OCaml Interface ------------*- OCaml -*-===* - * - * The LLVM Compiler Infrastructure - * - * This file is distributed under the University of Illinois Open Source - * License. See LICENSE.TXT for details. - * - *===----------------------------------------------------------------------===*) - -(** Scalar Transforms. - - This interface provides an OCaml API for LLVM scalar transforms, the - classes in the [LLVMScalarOpts] library. *) - -(** See the [llvm::createConstantPropagationPass] function. *) -external add_constant_propagation : [ unit - = "llvm_add_constant_propagation" - -(** See the [llvm::createSCCPPass] function. *) -external add_sccp : [ unit - = "llvm_add_sccp" - -(** See [llvm::createDeadStoreEliminationPass] function. *) -external add_dead_store_elimination : [ unit - = "llvm_add_dead_store_elimination" - -(** See The [llvm::createAggressiveDCEPass] function. *) -external add_aggressive_dce : [ unit - = "llvm_add_aggressive_dce" - -(** See the [llvm::createScalarReplAggregatesPass] function. *) -external -add_scalar_repl_aggregation : [ unit - = "llvm_add_scalar_repl_aggregation" - -(** See the [llvm::createScalarReplAggregatesPassSSA] function. *) -external -add_scalar_repl_aggregation_ssa : [ unit - = "llvm_add_scalar_repl_aggregation_ssa" - -(** See the [llvm::createScalarReplAggregatesWithThreshold] function. *) -external -add_scalar_repl_aggregation_with_threshold : int -> [ unit - = "llvm_add_scalar_repl_aggregation_with_threshold" - -(** See the [llvm::createIndVarSimplifyPass] function. *) -external add_ind_var_simplification : [ unit - = "llvm_add_ind_var_simplification" - -(** See the [llvm::createInstructionCombiningPass] function. *) -external -add_instruction_combination : [ unit - = "llvm_add_instruction_combination" - -(** See the [llvm::createLICMPass] function. *) -external add_licm : [ unit - = "llvm_add_licm" - -(** See the [llvm::createLoopUnswitchPass] function. *) -external add_loop_unswitch : [ unit - = "llvm_add_loop_unswitch" - -(** See the [llvm::createLoopUnrollPass] function. *) -external add_loop_unroll : [ unit - = "llvm_add_loop_unroll" - -(** See the [llvm::createLoopRotatePass] function. *) -external add_loop_rotation : [ unit - = "llvm_add_loop_rotation" - -(** See the [llvm::createPromoteMemoryToRegisterPass] function. *) -external -add_memory_to_register_promotion : [ unit - = "llvm_add_memory_to_register_promotion" - -(** See the [llvm::createDemoteMemoryToRegisterPass] function. *) -external -add_memory_to_register_demotion : [ unit - = "llvm_add_memory_to_register_demotion" - -(** See the [llvm::createReassociatePass] function. *) -external add_reassociation : [ unit - = "llvm_add_reassociation" - -(** See the [llvm::createJumpThreadingPass] function. *) -external add_jump_threading : [ unit - = "llvm_add_jump_threading" - -(** See the [llvm::createCFGSimplificationPass] function. *) -external add_cfg_simplification : [ unit - = "llvm_add_cfg_simplification" - -(** See the [llvm::createTailCallEliminationPass] function. *) -external -add_tail_call_elimination : [ unit - = "llvm_add_tail_call_elimination" - -(** See the [llvm::createGVNPass] function. *) -external add_gvn : [ unit - = "llvm_add_gvn" - -(** See the [llvm::createMemCpyOptPass] function. *) -external add_memcpy_opt : [ unit - = "llvm_add_memcpy_opt" - -(** See the [llvm::createLoopDeletionPass] function. *) -external add_loop_deletion : [ unit - = "llvm_add_loop_deletion" - -external add_loop_idiom : [ unit - = "llvm_add_loop_idiom" - -(** See the [llvm::createSimplifyLibCallsPass] function. *) -external -add_lib_call_simplification : [ unit - = "llvm_add_lib_call_simplification" - -(** See the [llvm::createVerifierPass] function. *) -external -add_verifier : [ unit - = "llvm_add_verifier" - -(** See the [llvm::createCorrelatedValuePropagationPass] function. *) -external -add_correlated_value_propagation : [ unit - = "llvm_add_correlated_value_propagation" - -(** See the [llvm::createEarlyCSE] function. *) -external -add_early_cse : [ unit - = "llvm_add_early_cse" - -(** See the [llvm::createLowerExpectIntrinsicPass] function. *) -external -add_lower_expect_intrinsic : [ unit - = "llvm_add_lower_expect_intrinsic" - -(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *) -external -add_type_based_alias_analysis : [ unit - = "llvm_add_type_based_alias_analysis" - -(** See the [llvm::createBasicAliasAnalysisPass] function. *) -external -add_basic_alias_analysis : [ unit - = "llvm_add_basic_alias_analysis" - -(** See the [llvm::createPartiallyInlineLibCallsPass] function. *) -external -add_partially_inline_lib_calls : [ unit - = "llvm_add_partially_inline_lib_calls" diff --git a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c b/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c deleted file mode 100644 index 47e1790..0000000 --- a/bindings/ocaml/transforms/scalar/scalar_opts_ocaml.c +++ /dev/null @@ -1,213 +0,0 @@ -/*===-- scalar_opts_ocaml.c - LLVM OCaml Glue -------------------*- C++ -*-===*\ -|* *| -|* The LLVM Compiler Infrastructure *| -|* *| -|* This file is distributed under the University of Illinois Open Source *| -|* License. See LICENSE.TXT for details. *| -|* *| -|*===----------------------------------------------------------------------===*| -|* *| -|* This file glues LLVM's OCaml interface to its C interface. These functions *| -|* are by and large transparent wrappers to the corresponding C functions. *| -|* *| -|* Note that these functions intentionally take liberties with the CAMLparamX *| -|* macros, since most of the parameters are not GC heap objects. *| -|* *| -\*===----------------------------------------------------------------------===*/ - -#include "llvm-c/Transforms/Scalar.h" -#include "caml/mlvalues.h" -#include "caml/misc.h" - -/* [ unit */ -CAMLprim value llvm_add_constant_propagation(LLVMPassManagerRef PM) { - LLVMAddConstantPropagationPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_sccp(LLVMPassManagerRef PM) { - LLVMAddSCCPPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_dead_store_elimination(LLVMPassManagerRef PM) { - LLVMAddDeadStoreEliminationPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_aggressive_dce(LLVMPassManagerRef PM) { - LLVMAddAggressiveDCEPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_scalar_repl_aggregation(LLVMPassManagerRef PM) { - LLVMAddScalarReplAggregatesPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_scalar_repl_aggregation_ssa(LLVMPassManagerRef PM) { - LLVMAddScalarReplAggregatesPassSSA(PM); - return Val_unit; -} - -/* [ int -> unit */ -CAMLprim value llvm_add_scalar_repl_aggregation_with_threshold(value threshold, - LLVMPassManagerRef PM) { - LLVMAddScalarReplAggregatesPassWithThreshold(PM, Int_val(threshold)); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_ind_var_simplification(LLVMPassManagerRef PM) { - LLVMAddIndVarSimplifyPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_instruction_combination(LLVMPassManagerRef PM) { - LLVMAddInstructionCombiningPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) { - LLVMAddLICMPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) { - LLVMAddLoopUnswitchPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_loop_unroll(LLVMPassManagerRef PM) { - LLVMAddLoopUnrollPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_loop_rotation(LLVMPassManagerRef PM) { - LLVMAddLoopRotatePass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_memory_to_register_promotion(LLVMPassManagerRef PM) { - LLVMAddPromoteMemoryToRegisterPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_memory_to_register_demotion(LLVMPassManagerRef PM) { - LLVMAddDemoteMemoryToRegisterPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_reassociation(LLVMPassManagerRef PM) { - LLVMAddReassociatePass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_jump_threading(LLVMPassManagerRef PM) { - LLVMAddJumpThreadingPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_cfg_simplification(LLVMPassManagerRef PM) { - LLVMAddCFGSimplificationPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_tail_call_elimination(LLVMPassManagerRef PM) { - LLVMAddTailCallEliminationPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_merged_load_store_motion(LLVMPassManagerRef PM) { - LLVMAddMergedLoadStoreMotionPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { - LLVMAddGVNPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_memcpy_opt(LLVMPassManagerRef PM) { - LLVMAddMemCpyOptPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) { - LLVMAddLoopDeletionPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_loop_idiom(LLVMPassManagerRef PM) { - LLVMAddLoopIdiomPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_lib_call_simplification(LLVMPassManagerRef PM) { - LLVMAddSimplifyLibCallsPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_verifier(LLVMPassManagerRef PM) { - LLVMAddVerifierPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_correlated_value_propagation(LLVMPassManagerRef PM) { - LLVMAddCorrelatedValuePropagationPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_early_cse(LLVMPassManagerRef PM) { - LLVMAddEarlyCSEPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_lower_expect_intrinsic(LLVMPassManagerRef PM) { - LLVMAddLowerExpectIntrinsicPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) { - LLVMAddTypeBasedAliasAnalysisPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) { - LLVMAddBasicAliasAnalysisPass(PM); - return Val_unit; -} - -/* [ unit */ -CAMLprim value llvm_add_partially_inline_lib_calls(LLVMPassManagerRef PM) { - LLVMAddPartiallyInlineLibCallsPass(PM); - return Val_unit; -} diff --git a/bindings/ocaml/transforms/scalar_opts/CMakeLists.txt b/bindings/ocaml/transforms/scalar_opts/CMakeLists.txt new file mode 100644 index 0000000..98c7c68 --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_scalar_opts + OCAML llvm_scalar_opts + OCAMLDEP llvm + C scalar_opts_ocaml + LLVM scalaropts) diff --git a/bindings/ocaml/transforms/scalar_opts/Makefile b/bindings/ocaml/transforms/scalar_opts/Makefile new file mode 100644 index 0000000..63d86a6 --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/scalar_opts/Makefile ------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_scalar_opts interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_scalar_opts +UsedComponents := scalaropts +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.ml b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.ml new file mode 100644 index 0000000..b90d0ae --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.ml @@ -0,0 +1,120 @@ +(*===-- llvm_scalar_opts.ml - LLVM OCaml Interface ------------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +external add_aggressive_dce + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_aggressive_dce" +external add_alignment_from_assumptions + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_alignment_from_assumptions" +external add_cfg_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_cfg_simplification" +external add_dead_store_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_dead_store_elimination" +external add_scalarizer + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalarizer" +external add_merged_load_store_motion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_merged_load_store_motion" +external add_gvn + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_gvn" +external add_ind_var_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_ind_var_simplify" +external add_instruction_combination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_instruction_combining" +external add_jump_threading + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_jump_threading" +external add_licm + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_licm" +external add_loop_deletion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_deletion" +external add_loop_idiom + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_idiom" +external add_loop_rotation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_rotate" +external add_loop_reroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_reroll" +external add_loop_unroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unroll" +external add_loop_unswitch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unswitch" +external add_memcpy_opt + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_memcpy_opt" +external add_partially_inline_lib_calls + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_partially_inline_lib_calls" +external add_lower_switch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_switch" +external add_memory_to_register_promotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_promote_memory_to_register" +external add_reassociation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_reassociation" +external add_sccp + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_sccp" +external add_scalar_repl_aggregation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates" +external add_scalar_repl_aggregation_ssa + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_ssa" +external add_scalar_repl_aggregation_with_threshold + : int -> [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_with_threshold" +external add_lib_call_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_simplify_lib_calls" +external add_tail_call_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_tail_call_elimination" +external add_constant_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_constant_propagation" +external add_memory_to_register_demotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_demote_memory_to_register" +external add_verifier + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_verifier" +external add_correlated_value_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_correlated_value_propagation" +external add_early_cse + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_early_cse" +external add_lower_expect_intrinsic + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_expect_intrinsic" +external add_type_based_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_type_based_alias_analysis" +external add_scoped_no_alias_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scoped_no_alias_aa" +external add_basic_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_basic_alias_analysis" diff --git a/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli new file mode 100644 index 0000000..b4cefed --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/llvm_scalar_opts.mli @@ -0,0 +1,198 @@ +(*===-- llvm_scalar_opts.mli - LLVM OCaml Interface -----------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Scalar Transforms. + + This interface provides an OCaml API for LLVM scalar transforms, the + classes in the [LLVMScalarOpts] library. *) + +(** See the [llvm::createAggressiveDCEPass] function. *) +external add_aggressive_dce + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_aggressive_dce" + +(** See the [llvm::createAlignmentFromAssumptionsPass] function. *) +external add_alignment_from_assumptions + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_alignment_from_assumptions" + +(** See the [llvm::createCFGSimplificationPass] function. *) +external add_cfg_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_cfg_simplification" + +(** See [llvm::createDeadStoreEliminationPass] function. *) +external add_dead_store_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_dead_store_elimination" + +(** See [llvm::createScalarizerPass] function. *) +external add_scalarizer + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalarizer" + +(** See [llvm::createMergedLoadStoreMotionPass] function. *) +external add_merged_load_store_motion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_merged_load_store_motion" + +(** See the [llvm::createGVNPass] function. *) +external add_gvn + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_gvn" + +(** See the [llvm::createIndVarSimplifyPass] function. *) +external add_ind_var_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_ind_var_simplify" + +(** See the [llvm::createInstructionCombiningPass] function. *) +external add_instruction_combination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_instruction_combining" + +(** See the [llvm::createJumpThreadingPass] function. *) +external add_jump_threading + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_jump_threading" + +(** See the [llvm::createLICMPass] function. *) +external add_licm + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_licm" + +(** See the [llvm::createLoopDeletionPass] function. *) +external add_loop_deletion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_deletion" + +(** See the [llvm::createLoopIdiomPass] function. *) +external add_loop_idiom + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_idiom" + +(** See the [llvm::createLoopRotatePass] function. *) +external add_loop_rotation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_rotate" + +(** See the [llvm::createLoopRerollPass] function. *) +external add_loop_reroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_reroll" + +(** See the [llvm::createLoopUnrollPass] function. *) +external add_loop_unroll + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unroll" + +(** See the [llvm::createLoopUnswitchPass] function. *) +external add_loop_unswitch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_loop_unswitch" + +(** See the [llvm::createMemCpyOptPass] function. *) +external add_memcpy_opt + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_memcpy_opt" + +(** See the [llvm::createPartiallyInlineLibCallsPass] function. *) +external add_partially_inline_lib_calls + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_partially_inline_lib_calls" + +(** See the [llvm::createLowerSwitchPass] function. *) +external add_lower_switch + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_switch" + +(** See the [llvm::createPromoteMemoryToRegisterPass] function. *) +external add_memory_to_register_promotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_promote_memory_to_register" + +(** See the [llvm::createReassociatePass] function. *) +external add_reassociation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_reassociation" + +(** See the [llvm::createSCCPPass] function. *) +external add_sccp + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_sccp" + +(** See the [llvm::createScalarReplAggregatesPass] function. *) +external add_scalar_repl_aggregation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates" + +(** See the [llvm::createScalarReplAggregatesPassSSA] function. *) +external add_scalar_repl_aggregation_ssa + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_ssa" + +(** See the [llvm::createScalarReplAggregatesWithThreshold] function. *) +external add_scalar_repl_aggregation_with_threshold + : int -> [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scalar_repl_aggregates_with_threshold" + +(** See the [llvm::createSimplifyLibCallsPass] function. *) +external add_lib_call_simplification + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_simplify_lib_calls" + +(** See the [llvm::createTailCallEliminationPass] function. *) +external add_tail_call_elimination + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_tail_call_elimination" + +(** See the [llvm::createConstantPropagationPass] function. *) +external add_constant_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_constant_propagation" + +(** See the [llvm::createDemoteMemoryToRegisterPass] function. *) +external add_memory_to_register_demotion + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_demote_memory_to_register" + +(** See the [llvm::createVerifierPass] function. *) +external add_verifier + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_verifier" + +(** See the [llvm::createCorrelatedValuePropagationPass] function. *) +external add_correlated_value_propagation + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_correlated_value_propagation" + +(** See the [llvm::createEarlyCSE] function. *) +external add_early_cse + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_early_cse" + +(** See the [llvm::createLowerExpectIntrinsicPass] function. *) +external add_lower_expect_intrinsic + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_lower_expect_intrinsic" + +(** See the [llvm::createTypeBasedAliasAnalysisPass] function. *) +external add_type_based_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_type_based_alias_analysis" + +(** See the [llvm::createScopedNoAliasAAPass] function. *) +external add_scoped_no_alias_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_scoped_no_alias_aa" + +(** See the [llvm::createBasicAliasAnalysisPass] function. *) +external add_basic_alias_analysis + : [< Llvm.PassManager.any ] Llvm.PassManager.t -> unit + = "llvm_add_basic_alias_analysis" diff --git a/bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c b/bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c new file mode 100644 index 0000000..bae4e31 --- /dev/null +++ b/bindings/ocaml/transforms/scalar_opts/scalar_opts_ocaml.c @@ -0,0 +1,243 @@ +/*===-- scalar_opts_ocaml.c - LLVM OCaml Glue -------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Transforms/Scalar.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* [ unit */ +CAMLprim value llvm_add_aggressive_dce(LLVMPassManagerRef PM) { + LLVMAddAggressiveDCEPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_alignment_from_assumptions(LLVMPassManagerRef PM) { + LLVMAddAlignmentFromAssumptionsPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_cfg_simplification(LLVMPassManagerRef PM) { + LLVMAddCFGSimplificationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_dead_store_elimination(LLVMPassManagerRef PM) { + LLVMAddDeadStoreEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scalarizer(LLVMPassManagerRef PM) { + LLVMAddScalarizerPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_merged_load_store_motion(LLVMPassManagerRef PM) { + LLVMAddMergedLoadStoreMotionPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_gvn(LLVMPassManagerRef PM) { + LLVMAddGVNPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_ind_var_simplify(LLVMPassManagerRef PM) { + LLVMAddIndVarSimplifyPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_instruction_combining(LLVMPassManagerRef PM) { + LLVMAddInstructionCombiningPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_jump_threading(LLVMPassManagerRef PM) { + LLVMAddJumpThreadingPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_licm(LLVMPassManagerRef PM) { + LLVMAddLICMPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_deletion(LLVMPassManagerRef PM) { + LLVMAddLoopDeletionPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_idiom(LLVMPassManagerRef PM) { + LLVMAddLoopIdiomPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_rotate(LLVMPassManagerRef PM) { + LLVMAddLoopRotatePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_reroll(LLVMPassManagerRef PM) { + LLVMAddLoopRerollPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unroll(LLVMPassManagerRef PM) { + LLVMAddLoopUnrollPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_loop_unswitch(LLVMPassManagerRef PM) { + LLVMAddLoopUnswitchPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_memcpy_opt(LLVMPassManagerRef PM) { + LLVMAddMemCpyOptPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_partially_inline_lib_calls(LLVMPassManagerRef PM) { + LLVMAddPartiallyInlineLibCallsPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_lower_switch(LLVMPassManagerRef PM) { + LLVMAddLowerSwitchPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_promote_memory_to_register(LLVMPassManagerRef PM) { + LLVMAddPromoteMemoryToRegisterPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_reassociation(LLVMPassManagerRef PM) { + LLVMAddReassociatePass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_sccp(LLVMPassManagerRef PM) { + LLVMAddSCCPPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scalar_repl_aggregates(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scalar_repl_aggregates_ssa(LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPassSSA(PM); + return Val_unit; +} + +/* int -> [ unit */ +CAMLprim value llvm_add_scalar_repl_aggregates_with_threshold(value threshold, + LLVMPassManagerRef PM) { + LLVMAddScalarReplAggregatesPassWithThreshold(PM, Int_val(threshold)); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_simplify_lib_calls(LLVMPassManagerRef PM) { + LLVMAddSimplifyLibCallsPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_tail_call_elimination(LLVMPassManagerRef PM) { + LLVMAddTailCallEliminationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_constant_propagation(LLVMPassManagerRef PM) { + LLVMAddConstantPropagationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_demote_memory_to_register(LLVMPassManagerRef PM) { + LLVMAddDemoteMemoryToRegisterPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_verifier(LLVMPassManagerRef PM) { + LLVMAddVerifierPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_correlated_value_propagation(LLVMPassManagerRef PM) { + LLVMAddCorrelatedValuePropagationPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_early_cse(LLVMPassManagerRef PM) { + LLVMAddEarlyCSEPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_lower_expect_intrinsic(LLVMPassManagerRef PM) { + LLVMAddLowerExpectIntrinsicPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_type_based_alias_analysis(LLVMPassManagerRef PM) { + LLVMAddTypeBasedAliasAnalysisPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_scoped_no_alias_aa(LLVMPassManagerRef PM) { + LLVMAddScopedNoAliasAAPass(PM); + return Val_unit; +} + +/* [ unit */ +CAMLprim value llvm_add_basic_alias_analysis(LLVMPassManagerRef PM) { + LLVMAddBasicAliasAnalysisPass(PM); + return Val_unit; +} diff --git a/bindings/ocaml/transforms/utils/CMakeLists.txt b/bindings/ocaml/transforms/utils/CMakeLists.txt new file mode 100644 index 0000000..37f3eb7 --- /dev/null +++ b/bindings/ocaml/transforms/utils/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_transform_utils + OCAML llvm_transform_utils + OCAMLDEP llvm + C transform_utils_ocaml + LLVM transformutils) diff --git a/bindings/ocaml/transforms/utils/Makefile b/bindings/ocaml/transforms/utils/Makefile new file mode 100644 index 0000000..76a6f0b --- /dev/null +++ b/bindings/ocaml/transforms/utils/Makefile @@ -0,0 +1,19 @@ +##===- bindings/ocaml/transforms/utils/Makefile ------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +# +# This is the makefile for the Objective Caml Llvm_vectorize interface. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../../../.. +LIBRARYNAME := llvm_transform_utils +UsedComponents := transformutils +UsedOcamlInterfaces := llvm + +include ../../Makefile.ocaml diff --git a/bindings/ocaml/transforms/utils/llvm_transform_utils.ml b/bindings/ocaml/transforms/utils/llvm_transform_utils.ml new file mode 100644 index 0000000..135efe2 --- /dev/null +++ b/bindings/ocaml/transforms/utils/llvm_transform_utils.ml @@ -0,0 +1,10 @@ +(*===-- llvm_transform_utils.ml - LLVM OCaml Interface --------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +external clone_module : Llvm.llmodule -> Llvm.llmodule = "llvm_clone_module" diff --git a/bindings/ocaml/transforms/utils/llvm_transform_utils.mli b/bindings/ocaml/transforms/utils/llvm_transform_utils.mli new file mode 100644 index 0000000..1c2b07c --- /dev/null +++ b/bindings/ocaml/transforms/utils/llvm_transform_utils.mli @@ -0,0 +1,17 @@ +(*===-- llvm_transform_utils.mli - LLVM OCaml Interface -------*- OCaml -*-===* + * + * The LLVM Compiler Infrastructure + * + * This file is distributed under the University of Illinois Open Source + * License. See LICENSE.TXT for details. + * + *===----------------------------------------------------------------------===*) + +(** Transform Utilities. + + This interface provides an OCaml API for LLVM transform utilities, the + classes in the [LLVMTransformUtils] library. *) + +(** [clone_module m] returns an exact copy of module [m]. + See the [llvm::CloneModule] function. *) +external clone_module : Llvm.llmodule -> Llvm.llmodule = "llvm_clone_module" diff --git a/bindings/ocaml/transforms/utils/transform_utils_ocaml.c b/bindings/ocaml/transforms/utils/transform_utils_ocaml.c new file mode 100644 index 0000000..75b2052 --- /dev/null +++ b/bindings/ocaml/transforms/utils/transform_utils_ocaml.c @@ -0,0 +1,31 @@ +/*===-- vectorize_ocaml.c - LLVM OCaml Glue ---------------------*- C++ -*-===*\ +|* *| +|* The LLVM Compiler Infrastructure *| +|* *| +|* This file is distributed under the University of Illinois Open Source *| +|* License. See LICENSE.TXT for details. *| +|* *| +|*===----------------------------------------------------------------------===*| +|* *| +|* This file glues LLVM's OCaml interface to its C interface. These functions *| +|* are by and large transparent wrappers to the corresponding C functions. *| +|* *| +|* Note that these functions intentionally take liberties with the CAMLparamX *| +|* macros, since most of the parameters are not GC heap objects. *| +|* *| +\*===----------------------------------------------------------------------===*/ + +#include "llvm-c/Core.h" +#include "caml/mlvalues.h" +#include "caml/misc.h" + +/* + * Do not move directly into external. This function is here to pull in + * -lLLVMTransformUtils, which would otherwise be not linked on static builds, + * as ld can't see the reference from OCaml code. + */ + +/* llmodule -> llmodule */ +CAMLprim LLVMModuleRef llvm_clone_module(LLVMModuleRef M) { + return LLVMCloneModule(M); +} diff --git a/bindings/ocaml/transforms/vectorize/CMakeLists.txt b/bindings/ocaml/transforms/vectorize/CMakeLists.txt new file mode 100644 index 0000000..af0ffce --- /dev/null +++ b/bindings/ocaml/transforms/vectorize/CMakeLists.txt @@ -0,0 +1,5 @@ +add_ocaml_library(llvm_vectorize + OCAML llvm_vectorize + OCAMLDEP llvm + C vectorize_ocaml + LLVM vectorize) diff --git a/bindings/ocaml/transforms/vectorize/Makefile b/bindings/ocaml/transforms/vectorize/Makefile index 5a854d1..64ac5c3 100644 --- a/bindings/ocaml/transforms/vectorize/Makefile +++ b/bindings/ocaml/transforms/vectorize/Makefile @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## # -# This is the makefile for the Objective Caml Llvm_vectorize_opts interface. +# This is the makefile for the Objective Caml Llvm_vectorize interface. # ##===----------------------------------------------------------------------===## diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml index 4fc53c6..88831da 100644 --- a/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.ml @@ -7,9 +7,12 @@ * *===----------------------------------------------------------------------===*) -external add_bb_vectorize : [ unit - = "llvm_add_bb_vectorize" -external add_loop_vectorize : [ unit - = "llvm_add_loop_vectorize" -external add_slp_vectorize : [ unit - = "llvm_add_slp_vectorize" +external add_bb_vectorize + : [ unit + = "llvm_add_bb_vectorize" +external add_loop_vectorize + : [ unit + = "llvm_add_loop_vectorize" +external add_slp_vectorize + : [ unit + = "llvm_add_slp_vectorize" diff --git a/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli index 0253039..23a68a2 100644 --- a/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli +++ b/bindings/ocaml/transforms/vectorize/llvm_vectorize.mli @@ -13,13 +13,16 @@ classes in the [LLVMVectorize] library. *) (** See the [llvm::createBBVectorizePass] function. *) -external add_bb_vectorize : [ unit - = "llvm_add_bb_vectorize" +external add_bb_vectorize + : [ unit + = "llvm_add_bb_vectorize" (** See the [llvm::createLoopVectorizePass] function. *) -external add_loop_vectorize : [ unit - = "llvm_add_loop_vectorize" +external add_loop_vectorize + : [ unit + = "llvm_add_loop_vectorize" -(** See [llvm::createSLPVectorizerPass] function. *) -external add_slp_vectorize : [ unit - = "llvm_add_slp_vectorize" +(** See the [llvm::createSLPVectorizerPass] function. *) +external add_slp_vectorize + : [ unit + = "llvm_add_slp_vectorize" diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index b862ceb..f806d9c 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -42,7 +42,6 @@ function(check_type_exists type files variable) endfunction() # include checks -check_include_file_cxx(cxxabi.h HAVE_CXXABI_H) check_include_file(dirent.h HAVE_DIRENT_H) check_include_file(dlfcn.h HAVE_DLFCN_H) check_include_file(errno.h HAVE_ERRNO_H) @@ -50,6 +49,7 @@ check_include_file(execinfo.h HAVE_EXECINFO_H) check_include_file(fcntl.h HAVE_FCNTL_H) check_include_file(inttypes.h HAVE_INTTYPES_H) check_include_file(limits.h HAVE_LIMITS_H) +check_include_file(link.h HAVE_LINK_H) check_include_file(malloc.h HAVE_MALLOC_H) check_include_file(malloc/malloc.h HAVE_MALLOC_MALLOC_H) check_include_file(ndir.h HAVE_NDIR_H) @@ -80,6 +80,13 @@ check_symbol_exists(FE_INEXACT "fenv.h" HAVE_DECL_FE_INEXACT) check_include_file(mach/mach.h HAVE_MACH_MACH_H) check_include_file(mach-o/dyld.h HAVE_MACH_O_DYLD_H) +# size_t must be defined before including cxxabi.h on FreeBSD 10.0. +check_cxx_source_compiles(" +#include +#include +int main() { return 0; } +" HAVE_CXXABI_H) + # library checks if( NOT PURE_WINDOWS ) check_library_exists(pthread pthread_create "" HAVE_LIBPTHREAD) @@ -258,12 +265,12 @@ endif () if( LLVM_ENABLE_FFI ) find_path(FFI_INCLUDE_PATH ffi.h PATHS ${FFI_INCLUDE_DIR}) - if( FFI_INCLUDE_PATH ) + if( EXISTS "${FFI_INCLUDE_PATH}/ffi.h" ) set(FFI_HEADER ffi.h CACHE INTERNAL "") set(HAVE_FFI_H 1 CACHE INTERNAL "") else() find_path(FFI_INCLUDE_PATH ffi/ffi.h PATHS ${FFI_INCLUDE_DIR}) - if( FFI_INCLUDE_PATH ) + if( EXISTS "${FFI_INCLUDE_PATH}/ffi/ffi.h" ) set(FFI_HEADER ffi/ffi.h CACHE INTERNAL "") set(HAVE_FFI_FFI_H 1 CACHE INTERNAL "") endif() @@ -490,3 +497,48 @@ if (LLVM_ENABLE_SPHINX) else() message(STATUS "Sphinx disabled.") endif() + +set(LLVM_BINDINGS "") +if(WIN32) + message(STATUS "Go bindings disabled.") +else() + find_program(GO_EXECUTABLE NAMES go DOC "go executable") + if(GO_EXECUTABLE STREQUAL "GO_EXECUTABLE-NOTFOUND") + message(STATUS "Go bindings disabled.") + else() + execute_process(COMMAND ${GO_EXECUTABLE} run ${CMAKE_SOURCE_DIR}/bindings/go/conftest.go + RESULT_VARIABLE GO_CONFTEST) + if(GO_CONFTEST STREQUAL "0") + set(LLVM_BINDINGS "${LLVM_BINDINGS} go") + message(STATUS "Go bindings enabled.") + else() + message(STATUS "Go bindings disabled, need at least Go 1.2.") + endif() + endif() +endif() + +include(FindOCaml) +include(AddOCaml) +if(WIN32) + message(STATUS "OCaml bindings disabled.") +else() + find_package(OCaml) + if( NOT OCAML_FOUND ) + message(STATUS "OCaml bindings disabled.") + else() + if( OCAML_VERSION VERSION_LESS "4.00.0" ) + message(STATUS "OCaml bindings disabled, need OCaml >=4.00.0.") + else() + find_ocamlfind_package(ctypes VERSION 0.3 OPTIONAL) + if( HAVE_OCAML_CTYPES ) + message(STATUS "OCaml bindings enabled.") + find_ocamlfind_package(oUnit VERSION 2 OPTIONAL) + set(LLVM_BINDINGS "${LLVM_BINDINGS} ocaml") + else() + message(STATUS "OCaml bindings disabled, need ctypes >=0.3.") + endif() + endif() + endif() +endif() + +string(REPLACE " " ";" LLVM_BINDINGS_LIST "${LLVM_BINDINGS}") diff --git a/cmake/modules/AddLLVM.cmake b/cmake/modules/AddLLVM.cmake index 409a5d6..ee55c52 100755 --- a/cmake/modules/AddLLVM.cmake +++ b/cmake/modules/AddLLVM.cmake @@ -85,27 +85,29 @@ function(add_llvm_symbol_exports target_name export_file) else() set(native_export_file "${target_name}.def") - set(CAT "type") - if(CYGWIN) - set(CAT "cat") + set(CAT "cat") + set(export_file_nativeslashes ${export_file}) + if(WIN32 AND NOT CYGWIN) + set(CAT "type") + # Convert ${export_file} to native format (backslashes) for "type" + # Does not use file(TO_NATIVE_PATH) as it doesn't create a native + # path but a build-system specific format (see CMake bug + # http://public.kitware.com/Bug/print_bug_page.php?bug_id=5939 ) + string(REPLACE / \\ export_file_nativeslashes ${export_file}) endif() - # Using ${export_file} in add_custom_command directly confuses cmd.exe. - file(TO_NATIVE_PATH ${export_file} export_file_backslashes) - add_custom_command(OUTPUT ${native_export_file} COMMAND ${CMAKE_COMMAND} -E echo "EXPORTS" > ${native_export_file} - COMMAND ${CAT} ${export_file_backslashes} >> ${native_export_file} + COMMAND ${CAT} ${export_file_nativeslashes} >> ${native_export_file} DEPENDS ${export_file} VERBATIM COMMENT "Creating export file for ${target_name}") - if(CYGWIN OR MINGW) - set_property(TARGET ${target_name} APPEND_STRING PROPERTY - LINK_FLAGS " ${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") - else() - set_property(TARGET ${target_name} APPEND_STRING PROPERTY - LINK_FLAGS " /DEF:${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") + set(export_file_linker_flag "${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") + if(MSVC) + set(export_file_linker_flag "/DEF:${export_file_linker_flag}") endif() + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " ${export_file_linker_flag}") endif() add_custom_target(${target_name}_exports DEPENDS ${native_export_file}) @@ -140,18 +142,48 @@ function(add_llvm_symbol_exports target_name export_file) set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} PARENT_SCOPE) endfunction(add_llvm_symbol_exports) -function(add_dead_strip target_name) +if(NOT WIN32 AND NOT APPLE) + execute_process( + COMMAND ${CMAKE_C_COMPILER} -Wl,--version + OUTPUT_VARIABLE stdout + ERROR_QUIET + ) + if("${stdout}" MATCHES "GNU gold") + set(LLVM_LINKER_IS_GOLD ON) + endif() +endif() + +function(add_link_opts target_name) + # Pass -O3 to the linker. This enabled different optimizations on different + # linkers. + if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32)) + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,-O3") + endif() + + if(LLVM_LINKER_IS_GOLD) + # With gold gc-sections is always safe. + set_property(TARGET ${target_name} APPEND_STRING PROPERTY + LINK_FLAGS " -Wl,--gc-sections") + # Note that there is a bug with -Wl,--icf=safe so it is not safe + # to enable. See https://sourceware.org/bugzilla/show_bug.cgi?id=17704. + endif() + if(NOT LLVM_NO_DEAD_STRIP) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + # ld64's implementation of -dead_strip breaks tools that use plugins. set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-dead_strip") - elseif(NOT WIN32) + elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD) # Object files are compiled with -ffunction-data-sections. + # Versions of bfd ld < 2.23.1 have a bug in --gc-sections that breaks + # tools that use plugins. Always pass --gc-sections once we require + # a newer linker. set_property(TARGET ${target_name} APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--gc-sections") endif() endif() -endfunction(add_dead_strip) +endfunction(add_link_opts) # Set each output directory according to ${CMAKE_CONFIGURATION_TYPES}. # Note: Don't set variables CMAKE_*_OUTPUT_DIRECTORY any more, @@ -281,7 +313,7 @@ function(llvm_add_library name) endif() set_output_directory(${name} ${LLVM_RUNTIME_OUTPUT_INTDIR} ${LLVM_LIBRARY_OUTPUT_INTDIR}) llvm_update_compile_flags(${name}) - add_dead_strip( ${name} ) + add_link_opts( ${name} ) if(ARG_OUTPUT_NAME) set_target_properties(${name} PROPERTIES @@ -310,6 +342,12 @@ function(llvm_add_library name) endif() if(ARG_MODULE OR ARG_SHARED) + # Do not add -Dname_EXPORTS to the command-line when building files in this + # target. Doing so is actively harmful for the modules build because it + # creates extra module variants, and not useful because we don't use these + # macros. + set_target_properties( ${name} PROPERTIES DEFINE_SYMBOL "" ) + if (LLVM_EXPORTED_SYMBOL_FILE) add_llvm_symbol_exports( ${name} ${LLVM_EXPORTED_SYMBOL_FILE} ) endif() @@ -340,22 +378,8 @@ function(llvm_add_library name) ${lib_deps} ${llvm_libs} ) - elseif((CYGWIN OR WIN32) AND ARG_SHARED) - # Win32's import library may be unaware of its dependent libs. - target_link_libraries(${name} PRIVATE - ${ARG_LINK_LIBS} - ${lib_deps} - ${llvm_libs} - ) - elseif(ARG_SHARED AND BUILD_SHARED_LIBS) - # FIXME: It may be PRIVATE since SO knows its dependent libs. - target_link_libraries(${name} PUBLIC - ${ARG_LINK_LIBS} - ${lib_deps} - ${llvm_libs} - ) else() - # MODULE|SHARED + # We can use PRIVATE since SO knows its dependent libs. target_link_libraries(${name} PRIVATE ${ARG_LINK_LIBS} ${lib_deps} @@ -433,7 +457,13 @@ macro(add_llvm_executable name) add_executable(${name} ${ALL_FILES}) endif() llvm_update_compile_flags(${name}) - add_dead_strip( ${name} ) + add_link_opts( ${name} ) + + # Do not add -Dname_EXPORTS to the command-line when building files in this + # target. Doing so is actively harmful for the modules build because it + # creates extra module variants, and not useful because we don't use these + # macros. + set_target_properties( ${name} PROPERTIES DEFINE_SYMBOL "" ) if (LLVM_EXPORTED_SYMBOL_FILE) add_llvm_symbol_exports( ${name} ${LLVM_EXPORTED_SYMBOL_FILE} ) @@ -592,6 +622,36 @@ function(add_unittest test_suite test_name) endif () endfunction() +function(llvm_add_go_executable binary pkgpath) + cmake_parse_arguments(ARG "ALL" "" "DEPENDS;GOFLAGS" ${ARGN}) + + if(LLVM_BINDINGS MATCHES "go") + # FIXME: This should depend only on the libraries Go needs. + get_property(llvmlibs GLOBAL PROPERTY LLVM_LIBS) + set(binpath ${CMAKE_BINARY_DIR}/bin/${binary}${CMAKE_EXECUTABLE_SUFFIX}) + set(cc "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}") + set(cxx "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}") + set(cppflags "") + get_property(include_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES) + foreach(d ${include_dirs}) + set(cppflags "${cppflags} -I${d}") + endforeach(d) + set(ldflags "${CMAKE_EXE_LINKER_FLAGS}") + add_custom_command(OUTPUT ${binpath} + COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}" + ${ARG_GOFLAGS} build -o ${binpath} ${pkgpath} + DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX} + ${llvmlibs} ${ARG_DEPENDS} + COMMENT "Building Go executable ${binary}" + VERBATIM) + if (ARG_ALL) + add_custom_target(${binary} ALL DEPENDS ${binpath}) + else() + add_custom_target(${binary} DEPENDS ${binpath}) + endif() + endif() +endfunction() + # This function provides an automatic way to 'configure'-like generate a file # based on a set of common and custom variables, specifically targeting the # variables needed for the 'lit.site.cfg' files. This function bundles the @@ -639,6 +699,10 @@ function(configure_lit_site_cfg input output) set(HOST_OS ${CMAKE_SYSTEM_NAME}) set(HOST_ARCH ${CMAKE_SYSTEM_PROCESSOR}) + set(HOST_CC "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}") + set(HOST_CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}") + set(HOST_LDFLAGS "${CMAKE_EXE_LINKER_FLAGS}") + configure_file(${input} ${output} @ONLY) endfunction() @@ -664,6 +728,7 @@ function(add_lit_target target comment) add_custom_target(${target} COMMAND ${LIT_COMMAND} ${ARG_DEFAULT_ARGS} COMMENT "${comment}" + ${cmake_3_2_USES_TERMINAL} ) add_dependencies(${target} ${ARG_DEPENDS}) else() diff --git a/cmake/modules/AddOCaml.cmake b/cmake/modules/AddOCaml.cmake new file mode 100644 index 0000000..c58ac9c --- /dev/null +++ b/cmake/modules/AddOCaml.cmake @@ -0,0 +1,201 @@ +# CMake build rules for the OCaml language. +# Assumes FindOCaml is used. +# http://ocaml.org/ +# +# Example usage: +# +# add_ocaml_library(pkg_a OCAML mod_a OCAMLDEP pkg_b C mod_a_stubs PKG ctypes LLVM core) +# +# Unnamed parameters: +# +# * Library name. +# +# Named parameters: +# +# OCAML OCaml module names. Imply presence of a corresponding .ml and .mli files. +# OCAMLDEP Names of libraries this library depends on. +# C C stub sources. Imply presence of a corresponding .c file. +# CFLAGS Additional arguments passed when compiling C stubs. +# PKG Names of ocamlfind packages this library depends on. +# LLVM Names of LLVM libraries this library depends on. +# NOCOPY Do not automatically copy sources (.c, .ml, .mli) from the source directory, +# e.g. if they are generated. +# + +function(add_ocaml_library name) + CMAKE_PARSE_ARGUMENTS(ARG "NOCOPY" "" "OCAML;OCAMLDEP;C;CFLAGS;PKG;LLVM" ${ARGN}) + + set(src ${CMAKE_CURRENT_SOURCE_DIR}) + set(bin ${CMAKE_CURRENT_BINARY_DIR}) + + set(ocaml_pkgs) + foreach( ocaml_pkg ${ARG_PKG} ) + list(APPEND ocaml_pkgs "-package" "${ocaml_pkg}") + endforeach() + + set(sources) + + set(ocaml_inputs) + + set(ocaml_outputs "${bin}/${name}.cma") + if( ARG_C ) + list(APPEND ocaml_outputs + "${bin}/lib${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") + if ( BUILD_SHARED_LIBS ) + list(APPEND ocaml_outputs + "${bin}/dll${name}${CMAKE_SHARED_LIBRARY_SUFFIX}") + endif() + endif() + if( HAVE_OCAMLOPT ) + list(APPEND ocaml_outputs + "${bin}/${name}.cmxa" + "${bin}/${name}${CMAKE_STATIC_LIBRARY_SUFFIX}") + endif() + + set(ocaml_flags "-lstdc++" "-ldopt" "-L${LLVM_LIBRARY_DIR}" + "-ccopt" "-L\\$CAMLORIGIN/.." + "-ccopt" "-Wl,-rpath,\\$CAMLORIGIN/.." + ${ocaml_pkgs}) + + foreach( ocaml_dep ${ARG_OCAMLDEP} ) + get_target_property(dep_ocaml_flags "ocaml_${ocaml_dep}" OCAML_FLAGS) + list(APPEND ocaml_flags ${dep_ocaml_flags}) + endforeach() + + if( NOT BUILD_SHARED_LIBS ) + list(APPEND ocaml_flags "-custom") + endif() + + explicit_map_components_to_libraries(llvm_libs ${ARG_LLVM}) + foreach( llvm_lib ${llvm_libs} ) + list(APPEND ocaml_flags "-l${llvm_lib}" ) + endforeach() + + get_property(system_libs TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS) + foreach(system_lib ${system_libs}) + list(APPEND ocaml_flags "-l${system_lib}" ) + endforeach() + + string(REPLACE ";" " " ARG_CFLAGS "${ARG_CFLAGS}") + set(c_flags "${ARG_CFLAGS} ${LLVM_DEFINITIONS}") + foreach( include_dir ${LLVM_INCLUDE_DIR} ${LLVM_MAIN_INCLUDE_DIR} ) + set(c_flags "${c_flags} -I${include_dir}") + endforeach() + + foreach( ocaml_file ${ARG_OCAML} ) + list(APPEND sources "${ocaml_file}.mli" "${ocaml_file}.ml") + + list(APPEND ocaml_inputs "${bin}/${ocaml_file}.mli" "${bin}/${ocaml_file}.ml") + + list(APPEND ocaml_outputs "${bin}/${ocaml_file}.cmi" "${bin}/${ocaml_file}.cmo") + if( HAVE_OCAMLOPT ) + list(APPEND ocaml_outputs + "${bin}/${ocaml_file}.cmx" + "${bin}/${ocaml_file}${CMAKE_C_OUTPUT_EXTENSION}") + endif() + endforeach() + + foreach( c_file ${ARG_C} ) + list(APPEND sources "${c_file}.c") + + list(APPEND c_inputs "${bin}/${c_file}.c") + list(APPEND c_outputs "${bin}/${c_file}${CMAKE_C_OUTPUT_EXTENSION}") + endforeach() + + if( NOT ARG_NOCOPY ) + foreach( source ${sources} ) + add_custom_command( + OUTPUT "${bin}/${source}" + COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${src}/${source}" "${bin}" + DEPENDS "${src}/${source}" + COMMENT "Copying ${source} to build area") + endforeach() + endif() + + foreach( c_input ${c_inputs} ) + get_filename_component(basename "${c_input}" NAME_WE) + add_custom_command( + OUTPUT "${basename}${CMAKE_C_OUTPUT_EXTENSION}" + COMMAND "${OCAMLFIND}" "ocamlc" "-c" "${c_input}" -ccopt ${c_flags} + DEPENDS "${c_input}" + COMMENT "Building OCaml stub object file ${basename}${CMAKE_C_OUTPUT_EXTENSION}" + VERBATIM) + endforeach() + + set(ocaml_params) + foreach( ocaml_input ${ocaml_inputs} ${c_outputs}) + get_filename_component(filename "${ocaml_input}" NAME) + list(APPEND ocaml_params "${filename}") + endforeach() + + if( APPLE ) + set(ocaml_rpath "@executable_path/../../lib") + elseif( UNIX ) + set(ocaml_rpath "\\$ORIGIN/../../lib") + endif() + list(APPEND ocaml_flags "-ldopt" "-Wl,-rpath,${ocaml_rpath}") + + add_custom_command( + OUTPUT ${ocaml_outputs} + COMMAND "${OCAMLFIND}" "ocamlmklib" "-o" "${name}" ${ocaml_flags} ${ocaml_params} + DEPENDS ${ocaml_inputs} ${c_outputs} + COMMENT "Building OCaml library ${name}" + VERBATIM) + + add_custom_command( + OUTPUT "${bin}/${name}.odoc" + COMMAND "${OCAMLFIND}" "ocamldoc" + "-I" "${bin}" + "-I" "${LLVM_LIBRARY_DIR}/ocaml/" + "-dump" "${bin}/${name}.odoc" + ${ocaml_pkgs} ${ocaml_inputs} + DEPENDS ${ocaml_inputs} + COMMENT "Building OCaml documentation for ${name}" + VERBATIM) + + add_custom_target("ocaml_${name}" ALL DEPENDS ${ocaml_outputs} "${bin}/${name}.odoc") + + set_target_properties("ocaml_${name}" PROPERTIES + OCAML_FLAGS "-I;${bin}") + set_target_properties("ocaml_${name}" PROPERTIES + OCAML_ODOC "${bin}/${name}.odoc") + + foreach( ocaml_dep ${ARG_OCAMLDEP} ) + add_dependencies("ocaml_${name}" "ocaml_${ocaml_dep}") + endforeach() + + foreach( llvm_lib ${llvm_libs} ) + add_dependencies("ocaml_${name}" "${llvm_lib}") + endforeach() + + set(install_files) + set(install_shlibs) + foreach( ocaml_output ${ocaml_outputs} ) + get_filename_component(ext "${ocaml_output}" EXT) + + if( NOT (ext STREQUAL ".cmo" OR + ext STREQUAL CMAKE_C_OUTPUT_EXTENSION OR + ext STREQUAL CMAKE_SHARED_LIBRARY_SUFFIX) ) + list(APPEND install_files "${ocaml_output}") + elseif( ext STREQUAL CMAKE_SHARED_LIBRARY_SUFFIX) + list(APPEND install_shlibs "${ocaml_output}") + endif() + endforeach() + + install(FILES ${install_files} + DESTINATION lib/ocaml) + install(FILES ${install_shlibs} + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + DESTINATION lib/ocaml) + + foreach( install_file ${install_files} ${install_shlibs} ) + get_filename_component(filename "${install_file}" NAME) + add_custom_command(TARGET "ocaml_${name}" POST_BUILD + COMMAND "${CMAKE_COMMAND}" "-E" "copy" "${install_file}" + "${LLVM_LIBRARY_DIR}/ocaml/" + COMMENT "Copying OCaml library component ${filename} to intermediate area" + VERBATIM) + endforeach() +endfunction() diff --git a/cmake/modules/AddSphinxTarget.cmake b/cmake/modules/AddSphinxTarget.cmake index fc28a49..045dc23 100644 --- a/cmake/modules/AddSphinxTarget.cmake +++ b/cmake/modules/AddSphinxTarget.cmake @@ -8,16 +8,23 @@ function (add_sphinx_target builder project) set(SPHINX_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${builder}") set(SPHINX_DOC_TREE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_doctrees") set(SPHINX_TARGET_NAME docs-${project}-${builder}) + + if (SPHINX_WARNINGS_AS_ERRORS) + set(SPHINX_WARNINGS_AS_ERRORS_FLAG "-W") + else() + set(SPHINX_WARNINGS_AS_ERRORS_FLAG "") + endif() + add_custom_target(${SPHINX_TARGET_NAME} COMMAND ${SPHINX_EXECUTABLE} -b ${builder} -d "${SPHINX_DOC_TREE_DIR}" -q # Quiet: no output other than errors and warnings. - -W # Warnings are errors. + ${SPHINX_WARNINGS_AS_ERRORS_FLAG} # Treat warnings as errors if requested "${CMAKE_CURRENT_SOURCE_DIR}" # Source "${SPHINX_BUILD_DIR}" # Output COMMENT - "Generating ${builder} Sphinx documentation for ${project}") + "Generating ${builder} Sphinx documentation for ${project} into \"${SPHINX_BUILD_DIR}\"") # When "clean" target is run, remove the Sphinx build directory set_property(DIRECTORY APPEND PROPERTY diff --git a/cmake/modules/CMakeLists.txt b/cmake/modules/CMakeLists.txt index c87193d..5f3f255 100644 --- a/cmake/modules/CMakeLists.txt +++ b/cmake/modules/CMakeLists.txt @@ -58,7 +58,7 @@ foreach(p ${_count}) get_filename_component(LLVM_INSTALL_PREFIX \"\${LLVM_INSTALL_PREFIX}\" PATH)") endforeach(p) set(LLVM_CONFIG_INCLUDE_DIRS "\${LLVM_INSTALL_PREFIX}/include") -set(LLVM_CONFIG_LIBRARY_DIRS "\${LLVM_INSTALL_PREFIX}/lib") +set(LLVM_CONFIG_LIBRARY_DIRS "\${LLVM_INSTALL_PREFIX}/lib\${LLVM_LIBDIR_SUFFIX}") set(LLVM_CONFIG_CMAKE_DIR "\${LLVM_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}") set(LLVM_CONFIG_TOOLS_BINARY_DIR "\${LLVM_INSTALL_PREFIX}/bin") set(LLVM_CONFIG_EXPORTS_FILE "\${LLVM_CMAKE_DIR}/LLVMExports.cmake") diff --git a/cmake/modules/CheckAtomic.cmake b/cmake/modules/CheckAtomic.cmake index 0d63a82..2ed4819 100644 --- a/cmake/modules/CheckAtomic.cmake +++ b/cmake/modules/CheckAtomic.cmake @@ -2,6 +2,11 @@ INCLUDE(CheckCXXSourceCompiles) +check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) +if (HAVE_LIBATOMIC) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") +endif() + CHECK_CXX_SOURCE_COMPILES(" #ifdef _MSC_VER #include diff --git a/cmake/modules/CrossCompile.cmake b/cmake/modules/CrossCompile.cmake new file mode 100644 index 0000000..400381c --- /dev/null +++ b/cmake/modules/CrossCompile.cmake @@ -0,0 +1,33 @@ +if(NOT DEFINED LLVM_NATIVE_BUILD) + set(LLVM_NATIVE_BUILD "${CMAKE_BINARY_DIR}/native") + message(STATUS "Setting native build dir to ${LLVM_NATIVE_BUILD}") +endif(NOT DEFINED LLVM_NATIVE_BUILD) + +add_custom_command(OUTPUT ${LLVM_NATIVE_BUILD} + COMMAND ${CMAKE_COMMAND} -E make_directory ${LLVM_NATIVE_BUILD} + COMMENT "Creating ${LLVM_NATIVE_BUILD}...") + +add_custom_command(OUTPUT ${LLVM_NATIVE_BUILD}/CMakeCache.txt + COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${LLVM_NATIVE_BUILD} + DEPENDS ${LLVM_NATIVE_BUILD} + COMMENT "Configuring native LLVM...") + +add_custom_target(ConfigureNativeLLVM DEPENDS ${LLVM_NATIVE_BUILD}/CMakeCache.txt) + +set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${LLVM_NATIVE_BUILD}) + +if(NOT IS_DIRECTORY ${LLVM_NATIVE_BUILD}) + if(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin") + set(HOST_SYSROOT_FLAGS -DCMAKE_OSX_SYSROOT=macosx) + endif(${CMAKE_HOST_SYSTEM_NAME} MATCHES "Darwin") + + message(STATUS "Configuring native build...") + execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory + ${LLVM_NATIVE_BUILD} ) + + message(STATUS "Configuring native targets...") + execute_process(COMMAND ${CMAKE_COMMAND} -DCMAKE_BUILD_TYPE=Release + -G "${CMAKE_GENERATOR}" -DLLVM_TARGETS_TO_BUILD=${LLVM_TARGETS_TO_BUILD} ${HOST_SYSROOT_FLAGS} ${CMAKE_SOURCE_DIR} + WORKING_DIRECTORY ${LLVM_NATIVE_BUILD} ) +endif(NOT IS_DIRECTORY ${LLVM_NATIVE_BUILD}) diff --git a/cmake/modules/FindOCaml.cmake b/cmake/modules/FindOCaml.cmake new file mode 100644 index 0000000..8eba212 --- /dev/null +++ b/cmake/modules/FindOCaml.cmake @@ -0,0 +1,103 @@ +# CMake find_package() module for the OCaml language. +# Assumes ocamlfind will be used for compilation. +# http://ocaml.org/ +# +# Example usage: +# +# find_package(OCaml) +# +# If successful, the following variables will be defined: +# OCAMLFIND +# OCAML_VERSION +# OCAML_STDLIB_PATH +# HAVE_OCAMLOPT +# +# Also provides find_ocamlfind_package() macro. +# +# Example usage: +# +# find_ocamlfind_package(ctypes) +# +# In any case, the following variables are defined: +# +# HAVE_OCAML_${pkg} +# +# If successful, the following variables will be defined: +# +# OCAML_${pkg}_VERSION + +include( FindPackageHandleStandardArgs ) + +find_program(OCAMLFIND + NAMES ocamlfind) + +if( OCAMLFIND ) + execute_process( + COMMAND ${OCAMLFIND} ocamlc -version + OUTPUT_VARIABLE OCAML_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + + execute_process( + COMMAND ${OCAMLFIND} ocamlc -where + OUTPUT_VARIABLE OCAML_STDLIB_PATH + OUTPUT_STRIP_TRAILING_WHITESPACE) + + execute_process( + COMMAND ${OCAMLFIND} ocamlc -version + OUTPUT_QUIET + RESULT_VARIABLE find_ocaml_result) + if( find_ocaml_result EQUAL 0 ) + set(HAVE_OCAMLOPT TRUE) + else() + set(HAVE_OCAMLOPT FALSE) + endif() +endif() + +find_package_handle_standard_args( OCaml DEFAULT_MSG + OCAMLFIND + OCAML_VERSION + OCAML_STDLIB_PATH) + +mark_as_advanced( + OCAMLFIND) + +function(find_ocamlfind_package pkg) + CMAKE_PARSE_ARGUMENTS(ARG "OPTIONAL" "VERSION" "" ${ARGN}) + + execute_process( + COMMAND "${OCAMLFIND}" "query" "${pkg}" "-format" "%v" + RESULT_VARIABLE result + OUTPUT_VARIABLE version + ERROR_VARIABLE error + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE) + + if( NOT result EQUAL 0 AND NOT ARG_OPTIONAL ) + message(FATAL_ERROR ${error}) + endif() + + if( result EQUAL 0 ) + set(found TRUE) + else() + set(found FALSE) + endif() + + if( found AND ARG_VERSION ) + if( version VERSION_LESS ARG_VERSION AND ARG_OPTIONAL ) + # If it's optional and the constraint is not satisfied, pretend + # it wasn't found. + set(found FALSE) + elseif( version VERSION_LESS ARG_VERSION ) + message(FATAL_ERROR + "ocamlfind package ${pkg} should have version ${ARG_VERSION} or newer") + endif() + endif() + + string(TOUPPER ${pkg} pkg) + + set(HAVE_OCAML_${pkg} ${found} + PARENT_SCOPE) + + set(OCAML_${pkg}_VERSION ${version} + PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/FindSphinx.cmake b/cmake/modules/FindSphinx.cmake index a2adcae..9d252e8 100644 --- a/cmake/modules/FindSphinx.cmake +++ b/cmake/modules/FindSphinx.cmake @@ -23,3 +23,5 @@ find_package_handle_standard_args(Sphinx # Provide options for controlling different types of output option(SPHINX_OUTPUT_HTML "Output standalone HTML files" ON) option(SPHINX_OUTPUT_MAN "Output man pages" ON) + +option(SPHINX_WARNINGS_AS_ERRORS "When building documentation treat warnings as errors" ON) diff --git a/cmake/modules/GetSVN.cmake b/cmake/modules/GetSVN.cmake index acccc12..d512bd2 100644 --- a/cmake/modules/GetSVN.cmake +++ b/cmake/modules/GetSVN.cmake @@ -2,24 +2,114 @@ # # Input variables: # FIRST_SOURCE_DIR - First source directory -# FIRST_REPOSITORY - The macro to define to the first revision number. -# SECOND_SOURCE_DIR - Second source directory -# SECOND_REPOSITORY - The macro to define to the second revision number. +# FIRST_NAME - The macro prefix for the first repository's info +# SECOND_SOURCE_DIR - Second source directory (opt) +# SECOND_NAME - The macro prefix for the second repository's info (opt) # HEADER_FILE - The header file to write -include(FindSubversion) -if (Subversion_FOUND AND EXISTS "${FIRST_SOURCE_DIR}/.svn") - # Repository information for the first repository. - Subversion_WC_INFO(${FIRST_SOURCE_DIR} MY) - file(WRITE ${HEADER_FILE}.txt "#define ${FIRST_REPOSITORY} \"${MY_WC_REVISION}\"\n") - - # Repository information for the second repository. - if (EXISTS "${SECOND_SOURCE_DIR}/.svn") - Subversion_WC_INFO(${SECOND_SOURCE_DIR} MY) - file(APPEND ${HEADER_FILE}.txt - "#define ${SECOND_REPOSITORY} \"${MY_WC_REVISION}\"\n") - endif () - - # Copy the file only if it has changed. - execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${HEADER_FILE}.txt ${HEADER_FILE}) +# +# The output header will contain macros FIRST_REPOSITORY and FIRST_REVISION, +# and SECOND_REPOSITORY and SECOND_REVISION if requested, where "FIRST" and +# "SECOND" are substituted with the names specified in the input variables. + +# Chop off cmake/modules/GetSVN.cmake +get_filename_component(LLVM_DIR "${CMAKE_SCRIPT_MODE_FILE}" PATH) +get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH) +get_filename_component(LLVM_DIR "${LLVM_DIR}" PATH) + +# Handle strange terminals +set(ENV{TERM} "dumb") + +macro(get_source_info_svn path revision repository) + # If svn is a bat file, find_program(Subversion) doesn't find it. + # Explicitly search for that here; Subversion_SVN_EXECUTABLE will override + # the find_program call in FindSubversion.cmake. + find_program(Subversion_SVN_EXECUTABLE NAMES svn svn.bat) + + # FindSubversion does not work with symlinks. See PR 8437 + if (NOT IS_SYMLINK "${path}") + find_package(Subversion) + endif() + if (Subversion_FOUND) + subversion_wc_info( ${path} Project ) + if (Project_WC_REVISION) + set(${revision} ${Project_WC_REVISION} PARENT_SCOPE) + endif() + if (Project_WC_URL) + set(${repository} ${Project_WC_URL} PARENT_SCOPE) + endif() + endif() +endmacro() + +macro(get_source_info_git_svn path revision repository) + find_program(git_executable NAMES git git.exe git.cmd) + if (git_executable) + execute_process(COMMAND ${git_executable} svn info + WORKING_DIRECTORY ${path} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if (git_result EQUAL 0) + string(REGEX REPLACE "^(.*\n)?Revision: ([^\n]+).*" + "\\2" git_svn_rev "${git_output}") + set(${revision} ${git_svn_rev} PARENT_SCOPE) + string(REGEX REPLACE "^(.*\n)?URL: ([^\n]+).*" + "\\2" git_url "${git_output}") + set(${repository} ${git_url} PARENT_SCOPE) + endif() + endif() +endmacro() + +macro(get_source_info_git path revision repository) + find_program(git_executable NAMES git git.exe git.cmd) + if (git_executable) + execute_process(COMMAND ${git_executable} log -1 --pretty=format:%H + WORKING_DIRECTORY ${path} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if (git_result EQUAL 0) + set(${revision} ${git_output} PARENT_SCOPE) + endif() + execute_process(COMMAND ${git_executable} remote -v + WORKING_DIRECTORY ${path} + TIMEOUT 5 + RESULT_VARIABLE git_result + OUTPUT_VARIABLE git_output) + if (git_result EQUAL 0) + string(REGEX REPLACE "^(.*\n)?[^ \t]+[ \t]+([^ \t\n]+)[ \t]+\\(fetch\\).*" + "\\2" git_url "${git_output}") + set(${repository} "${git_url}" PARENT_SCOPE) + endif() + endif() +endmacro() + +function(get_source_info path revision repository) + if (EXISTS "${path}/.svn") + get_source_info_svn("${path}" revision repository) + elseif (EXISTS "${path}/.git/svn") + get_source_info_git_svn("${path}" revision repository) + elseif (EXISTS "${path}/.git") + get_source_info_git("${path}" revision repository) + endif() +endfunction() + +function(append_info name path) + get_source_info("${path}" revision repository) + string(STRIP "${revision}" revision) + string(STRIP "${repository}" repository) + file(APPEND "${HEADER_FILE}.txt" + "#define ${name}_REVISION \"${revision}\"\n") + file(APPEND "${HEADER_FILE}.txt" + "#define ${name}_REPOSITORY \"${repository}\"\n") +endfunction() + +append_info(${FIRST_NAME} "${FIRST_SOURCE_DIR}") +if(DEFINED SECOND_SOURCE_DIR) + append_info(${SECOND_NAME} "${SECOND_SOURCE_DIR}") endif() + +# Copy the file only if it has changed. +execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${HEADER_FILE}.txt" "${HEADER_FILE}") +file(REMOVE "${HEADER_FILE}.txt") + diff --git a/cmake/modules/HandleLLVMOptions.cmake b/cmake/modules/HandleLLVMOptions.cmake index 8258512..2ee0dd5 100644 --- a/cmake/modules/HandleLLVMOptions.cmake +++ b/cmake/modules/HandleLLVMOptions.cmake @@ -2,6 +2,10 @@ # options and executing the appropriate CMake commands to realize the users' # selections. +# This is commonly needed so make sure it's defined before we include anything +# else. +string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE) + include(HandleLLVMStdlib) include(AddLLVMDefinitions) include(CheckCCompilerFlag) @@ -25,9 +29,6 @@ if(NOT LLVM_FORCE_USE_OLD_TOOLCHAIN) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(OLD_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) set(CMAKE_REQUIRED_FLAGS "-std=c++0x") - if (ANDROID) - set(CMAKE_REQUIRED_LIBRARIES "atomic") - endif() check_cxx_source_compiles(" #include std::atomic x(0.0f); @@ -78,8 +79,6 @@ if(WIN32) set(LLVM_ON_WIN32 1) set(LLVM_ON_UNIX 0) endif(CYGWIN) - # Maximum path length is 160 for non-unicode paths - set(MAXPATHLEN 160) else(WIN32) if(UNIX) set(LLVM_ON_WIN32 0) @@ -89,8 +88,6 @@ else(WIN32) else(APPLE) set(LLVM_HAVE_LINK_VERSION_SCRIPT 1) endif(APPLE) - # FIXME: Maximum path length is currently set to 'safe' fixed value - set(MAXPATHLEN 2024) else(UNIX) MESSAGE(SEND_ERROR "Unable to determine platform") endif(UNIX) @@ -131,7 +128,7 @@ endmacro() function(add_flag_or_print_warning flag name) check_c_compiler_flag("-Werror ${flag}" "C_SUPPORTS_${name}") check_cxx_compiler_flag("-Werror ${flag}" "CXX_SUPPORTS_${name}") - if ("C_SUPPORTS_${name}" AND "CXX_SUPPORTS_${name}") + if (C_SUPPORTS_${name} AND CXX_SUPPORTS_${name}) message(STATUS "Building with ${flag}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE) @@ -170,6 +167,10 @@ if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) endif( LLVM_BUILD_32_BITS ) endif( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) +if (LLVM_BUILD_STATIC) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static") +endif() + if( XCODE ) # For Xcode enable several build settings that correspond to # many warnings that are on by default in Clang but are @@ -240,11 +241,16 @@ if( MSVC ) -wd4146 # Suppress 'unary minus operator applied to unsigned type, result still unsigned' -wd4180 # Suppress 'qualifier applied to function type has no meaning; ignored' -wd4244 # Suppress ''argument' : conversion from 'type1' to 'type2', possible loss of data' + -wd4258 # Suppress ''var' : definition from the for loop is ignored; the definition from the enclosing scope is used' -wd4267 # Suppress ''var' : conversion from 'size_t' to 'type', possible loss of data' -wd4291 # Suppress ''declaration' : no matching operator delete found; memory will not be freed if initialization throws an exception' -wd4345 # Suppress 'behavior change: an object of POD type constructed with an initializer of the form () will be default-initialized' -wd4351 # Suppress 'new behavior: elements of array 'array' will be default initialized' -wd4355 # Suppress ''this' : used in base member initializer list' + -wd4456 # Suppress 'declaration of 'var' hides local variable' + -wd4457 # Suppress 'declaration of 'var' hides function parameter' + -wd4458 # Suppress 'declaration of 'var' hides class member' + -wd4459 # Suppress 'declaration of 'var' hides global declaration' -wd4503 # Suppress ''identifier' : decorated name length exceeded, name was truncated' -wd4624 # Suppress ''derived class' : destructor could not be generated because a base class destructor is inaccessible' -wd4722 # Suppress 'function' : destructor never returns, potential memory leak @@ -270,6 +276,7 @@ if( MSVC ) elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE ) if (LLVM_ENABLE_WARNINGS) append("-Wall -W -Wno-unused-parameter -Wwrite-strings" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + append("-Wcast-qual" CMAKE_CXX_FLAGS) # Turn off missing field initializer warnings for gcc to avoid noise from # false positives with empty {}. Turn them on otherwise (they're off by @@ -287,13 +294,25 @@ elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE ) add_flag_if_supported("-Wcovered-switch-default" COVERED_SWITCH_DEFAULT_FLAG) append_if(USE_NO_UNINITIALIZED "-Wno-uninitialized" CMAKE_CXX_FLAGS) append_if(USE_NO_MAYBE_UNINITIALIZED "-Wno-maybe-uninitialized" CMAKE_CXX_FLAGS) - check_cxx_compiler_flag("-Werror -Wnon-virtual-dtor" CXX_SUPPORTS_NON_VIRTUAL_DTOR_FLAG) - append_if(CXX_SUPPORTS_NON_VIRTUAL_DTOR_FLAG "-Wnon-virtual-dtor" CMAKE_CXX_FLAGS) + + # Check if -Wnon-virtual-dtor warns even though the class is marked final. + # If it does, don't add it. So it won't be added on clang 3.4 and older. + # This also catches cases when -Wnon-virtual-dtor isn't supported by + # the compiler at all. + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11 -Werror=non-virtual-dtor") + CHECK_CXX_SOURCE_COMPILES("class base {public: virtual void anchor();protected: ~base();}; + class derived final : public base { public: ~derived();}; + int main() { return 0; }" + CXX_WONT_WARN_ON_FINAL_NONVIRTUALDTOR) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) + append_if(CXX_WONT_WARN_ON_FINAL_NONVIRTUALDTOR + "-Wnon-virtual-dtor" CMAKE_CXX_FLAGS) # Check if -Wcomment is OK with an // comment ending with '\' if the next # line is also a // comment. set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} -Werror -Wcomment) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Werror -Wcomment") CHECK_C_SOURCE_COMPILES("// \\\\\\n//\\nint main() {return 0;}" C_WCOMMENT_ALLOWS_LINE_WRAP) set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) @@ -322,6 +341,25 @@ elseif( LLVM_COMPILER_IS_GCC_COMPATIBLE ) message(FATAL_ERROR "LLVM requires C++11 support but the '-std=c++11' flag isn't supported.") endif() endif() + if (LLVM_ENABLE_MODULES) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fmodules -fcxx-modules") + # Check that we can build code with modules enabled, and that repeatedly + # including still manages to respect NDEBUG properly. + CHECK_CXX_SOURCE_COMPILES("#undef NDEBUG + #include + #define NDEBUG + #include + int main() { assert(this code is not compiled); }" + CXX_SUPPORTS_MODULES) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) + if (CXX_SUPPORTS_MODULES) + append_if(CXX_SUPPORTS_MODULES "-fmodules" CMAKE_C_FLAGS) + append_if(CXX_SUPPORTS_MODULES "-fmodules -fcxx-modules" CMAKE_CXX_FLAGS) + else() + message(FATAL_ERROR "LLVM_ENABLE_MODULES is not supported by this compiler") + endif() + endif(LLVM_ENABLE_MODULES) endif( MSVC ) macro(append_common_sanitizer_flags) @@ -350,6 +388,13 @@ if(LLVM_USE_SANITIZER) if(LLVM_USE_SANITIZER STREQUAL "MemoryWithOrigins") append("-fsanitize-memory-track-origins" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) endif() + elseif (LLVM_USE_SANITIZER STREQUAL "Undefined") + append_common_sanitizer_flags() + append("-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover" + CMAKE_C_FLAGS CMAKE_CXX_FLAGS) + elseif (LLVM_USE_SANITIZER STREQUAL "Thread") + append_common_sanitizer_flags() + append("-fsanitize=thread" CMAKE_C_FLAGS CMAKE_CXX_FLAGS) else() message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${LLVM_USE_SANITIZER}") endif() @@ -360,7 +405,7 @@ endif() # Turn on -gsplit-dwarf if requested if(LLVM_USE_SPLIT_DWARF) - add_llvm_definitions("-gsplit-dwarf") + add_definitions("-gsplit-dwarf") endif() add_llvm_definitions( -D__STDC_CONSTANT_MACROS ) diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index 8ae1d23..b24c129 100755 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -40,9 +40,9 @@ function(explicit_llvm_config executable) llvm_map_components_to_libnames(LIBRARIES ${link_components}) get_target_property(t ${executable} TYPE) - if("${t}" STREQUAL "STATIC_LIBRARY") + if("x${t}" STREQUAL "xSTATIC_LIBRARY") target_link_libraries(${executable} ${cmake_2_8_12_INTERFACE} ${LIBRARIES}) - elseif("${t}" STREQUAL "SHARED_LIBRARY" OR "${t}" STREQUAL "MODULE_LIBRARY") + elseif("x${t}" STREQUAL "xSHARED_LIBRARY" OR "x${t}" STREQUAL "xMODULE_LIBRARY") target_link_libraries(${executable} ${cmake_2_8_12_PRIVATE} ${LIBRARIES}) else() # Use plain form for legacy user. @@ -152,29 +152,39 @@ function(llvm_map_components_to_libnames out_libs) set(${out_libs} ${expanded_components} PARENT_SCOPE) endfunction() +# Perform a post-order traversal of the dependency graph. +# This duplicates the algorithm used by llvm-config, originally +# in tools/llvm-config/llvm-config.cpp, function ComputeLibsForComponents. +function(expand_topologically name required_libs visited_libs) + list(FIND visited_libs ${name} found) + if( found LESS 0 ) + list(APPEND visited_libs ${name}) + set(visited_libs ${visited_libs} PARENT_SCOPE) + + get_property(lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${name}) + foreach( lib_dep ${lib_deps} ) + expand_topologically(${lib_dep} "${required_libs}" "${visited_libs}") + set(required_libs ${required_libs} PARENT_SCOPE) + set(visited_libs ${visited_libs} PARENT_SCOPE) + endforeach() + + list(APPEND required_libs ${name}) + set(required_libs ${required_libs} PARENT_SCOPE) + endif() +endfunction() + # Expand dependencies while topologically sorting the list of libraries: function(llvm_expand_dependencies out_libs) set(expanded_components ${ARGN}) - list(LENGTH expanded_components lst_size) - set(cursor 0) - set(processed) - while( cursor LESS lst_size ) - list(GET expanded_components ${cursor} lib) - get_property(lib_deps GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_${lib}) - list(APPEND expanded_components ${lib_deps}) - # Remove duplicates at the front: - list(REVERSE expanded_components) - list(REMOVE_DUPLICATES expanded_components) - list(REVERSE expanded_components) - list(APPEND processed ${lib}) - # Find the maximum index that doesn't have to be re-processed: - while(NOT "${expanded_components}" MATCHES "^${processed}.*" ) - list(REMOVE_AT processed -1) - endwhile() - list(LENGTH processed cursor) - list(LENGTH expanded_components lst_size) - endwhile( cursor LESS lst_size ) - set(${out_libs} ${expanded_components} PARENT_SCOPE) + + set(required_libs) + set(visited_libs) + foreach( lib ${expanded_components} ) + expand_topologically(${lib} "${required_libs}" "${visited_libs}") + endforeach() + + list(REVERSE required_libs) + set(${out_libs} ${required_libs} PARENT_SCOPE) endfunction() function(explicit_map_components_to_libraries out_libs) diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in index 780a608..9a9cd85 100644 --- a/cmake/modules/LLVMConfig.cmake.in +++ b/cmake/modules/LLVMConfig.cmake.in @@ -40,6 +40,8 @@ set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) set(LLVM_ON_UNIX @LLVM_ON_UNIX@) set(LLVM_ON_WIN32 @LLVM_ON_WIN32@) +set(LLVM_LIBDIR_SUFFIX @LLVM_LIBDIR_SUFFIX@) + set(LLVM_INCLUDE_DIRS "@LLVM_CONFIG_INCLUDE_DIRS@") set(LLVM_LIBRARY_DIRS "@LLVM_CONFIG_LIBRARY_DIRS@") set(LLVM_DEFINITIONS "-D__STDC_LIMIT_MACROS" "-D__STDC_CONSTANT_MACROS") diff --git a/cmake/modules/LLVMProcessSources.cmake b/cmake/modules/LLVMProcessSources.cmake index 08b9c8e..64ebce8 100644 --- a/cmake/modules/LLVMProcessSources.cmake +++ b/cmake/modules/LLVMProcessSources.cmake @@ -59,12 +59,17 @@ function(llvm_check_source_file_list) file(GLOB globbed *.c *.cpp) foreach(g ${globbed}) get_filename_component(fn ${g} NAME) - list(FIND LLVM_OPTIONAL_SOURCES ${fn} idx) - if( idx LESS 0 ) - list(FIND listed ${fn} idx) + + # Don't reject hidden files. Some editors create backups in the + # same directory as the file. + if (NOT "${fn}" MATCHES "^\\.") + list(FIND LLVM_OPTIONAL_SOURCES ${fn} idx) if( idx LESS 0 ) - message(SEND_ERROR "Found unknown source file ${g} + list(FIND listed ${fn} idx) + if( idx LESS 0 ) + message(SEND_ERROR "Found unknown source file ${g} Please update ${CMAKE_CURRENT_LIST_FILE}\n") + endif() endif() endif() endforeach() diff --git a/cmake/modules/Makefile b/cmake/modules/Makefile index dd31aa7..e38f5a6 100644 --- a/cmake/modules/Makefile +++ b/cmake/modules/Makefile @@ -48,7 +48,7 @@ endif OBJMODS := LLVMConfig.cmake LLVMConfigVersion.cmake LLVMExports.cmake -$(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in $(LLVMBuildCMakeFrag) +$(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeFrag) $(Echo) 'Generating LLVM CMake package config file' $(Verb) ( \ cat $< | sed \ @@ -73,6 +73,7 @@ $(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in $(LLVMBuildCMakeFrag) -e 's/@LLVM_ENABLE_PIC@/'"$(ENABLE_PIC)"'/' \ -e 's/@LLVM_ON_UNIX@/'"$(LLVM_ON_UNIX)"'/' \ -e 's/@LLVM_ON_WIN32@/'"$(LLVM_ON_WIN32)"'/' \ + -e 's/@LLVM_LIBDIR_SUFFIX@//' \ -e 's/@LLVM_CONFIG_INCLUDE_DIRS@/'"$(subst /,\/,$(PROJ_includedir))"'/' \ -e 's/@LLVM_CONFIG_LIBRARY_DIRS@/'"$(subst /,\/,$(PROJ_libdir))"'/' \ -e 's/@LLVM_CONFIG_CMAKE_DIR@/'"$(subst /,\/,$(PROJ_cmake))"'/' \ diff --git a/cmake/modules/TableGen.cmake b/cmake/modules/TableGen.cmake index 845c986..67031a5 100644 --- a/cmake/modules/TableGen.cmake +++ b/cmake/modules/TableGen.cmake @@ -70,35 +70,6 @@ function(add_public_tablegen_target target) set(LLVM_COMMON_DEPENDS ${LLVM_COMMON_DEPENDS} ${target} PARENT_SCOPE) endfunction() -if(CMAKE_CROSSCOMPILING) - set(CX_NATIVE_TG_DIR "${CMAKE_BINARY_DIR}/native") - - add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR} - COMMAND ${CMAKE_COMMAND} -E make_directory ${CX_NATIVE_TG_DIR} - COMMENT "Creating ${CX_NATIVE_TG_DIR}...") - - # Forward a subset of configure options to discover additional tablegen modules. - get_cmake_property(_variableNames CACHE_VARIABLES) - foreach (_variableName ${_variableNames}) - if (_variableName MATCHES "^(LLVM_EXTERNAL_.*_SOURCE_DIR)$") - list(APPEND CX_CMAKE_ARGUMENTS "-D${_variableName}=\"${${_variableName}}\"") - endif () - endforeach() - - add_custom_command(OUTPUT ${CX_NATIVE_TG_DIR}/CMakeCache.txt - # TODO: Clear the old CMakeCache.txt somehow without breaking restat. - COMMAND ${CMAKE_COMMAND} -UMAKE_TOOLCHAIN_FILE -DCMAKE_BUILD_TYPE=Release - -DLLVM_BUILD_POLLY=OFF ${CX_CMAKE_ARGUMENTS} - -G "${CMAKE_GENERATOR}" ${CMAKE_SOURCE_DIR} - WORKING_DIRECTORY ${CX_NATIVE_TG_DIR} - DEPENDS ${CX_NATIVE_TG_DIR} - COMMENT "Configuring native TableGen...") - - add_custom_target(ConfigureNativeTableGen DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt) - - set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES ${CX_NATIVE_TG_DIR}) -endif() - macro(add_tablegen target project) set(${target}_OLD_LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS}) set(LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} TableGen) @@ -122,16 +93,16 @@ macro(add_tablegen target project) if(CMAKE_CROSSCOMPILING) if( ${${project}_TABLEGEN} STREQUAL "${target}" ) - set(${project}_TABLEGEN_EXE "${CX_NATIVE_TG_DIR}/bin/${target}") + set(${project}_TABLEGEN_EXE "${LLVM_NATIVE_BUILD}/bin/${target}") set(${project}_TABLEGEN_EXE ${${project}_TABLEGEN_EXE} PARENT_SCOPE) add_custom_command(OUTPUT ${${project}_TABLEGEN_EXE} - COMMAND ${CMAKE_BUILD_TOOL} ${target} - DEPENDS ${CX_NATIVE_TG_DIR}/CMakeCache.txt - WORKING_DIRECTORY ${CX_NATIVE_TG_DIR} + COMMAND ${CMAKE_COMMAND} --build . --target ${target} --config $ + DEPENDS ${LLVM_NATIVE_BUILD}/CMakeCache.txt + WORKING_DIRECTORY ${LLVM_NATIVE_BUILD} COMMENT "Building native TableGen...") add_custom_target(${project}NativeTableGen DEPENDS ${${project}_TABLEGEN_EXE}) - add_dependencies(${project}NativeTableGen ConfigureNativeTableGen) + add_dependencies(${project}NativeTableGen ConfigureNativeLLVM) add_dependencies(${target} ${project}NativeTableGen) endif() diff --git a/cmake/platforms/iOS.cmake b/cmake/platforms/iOS.cmake new file mode 100644 index 0000000..4973643 --- /dev/null +++ b/cmake/platforms/iOS.cmake @@ -0,0 +1,47 @@ +# Toolchain config for iOS. +# +# Usage: +# mkdir build; cd build +# cmake ..; make +# mkdir ios; cd ios +# cmake -DLLVM_IOS_TOOLCHAIN_DIR=/path/to/ios/ndk \ +# -DCMAKE_TOOLCHAIN_FILE=../../cmake/platforms/iOS.cmake ../.. +# make + +SET(CMAKE_SYSTEM_NAME Darwin) +SET(CMAKE_SYSTEM_VERSION 13) +SET(CMAKE_CXX_COMPILER_WORKS True) +SET(CMAKE_C_COMPILER_WORKS True) +SET(DARWIN_TARGET_OS_NAME ios) + +IF(NOT DEFINED ENV{SDKROOT}) + MESSAGE(FATAL_ERROR "SDKROOT env var must be set: " $ENV{SDKROOT}) +ENDIF() + +IF(NOT CMAKE_C_COMPILER) + execute_process(COMMAND xcrun -sdk iphoneos -find clang + OUTPUT_VARIABLE CMAKE_C_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + message(STATUS "Using c compiler ${CMAKE_C_COMPILER}") +ENDIF() + +IF(NOT CMAKE_CXX_COMPILER) + execute_process(COMMAND xcrun -sdk iphoneos -find clang++ + OUTPUT_VARIABLE CMAKE_CXX_COMPILER + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + message(STATUS "Using c compiler ${CMAKE_CXX_COMPILER}") +ENDIF() + +IF (NOT DEFINED IOS_MIN_TARGET) +execute_process(COMMAND xcodebuild -sdk iphoneos -version SDKVersion + OUTPUT_VARIABLE IOS_MIN_TARGET + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) +ENDIF() + +SET(IOS_COMMON_FLAGS "-isysroot $ENV{SDKROOT} -mios-version-min=${IOS_MIN_TARGET}") +SET(CMAKE_C_FLAGS "${IOS_COMMON_FLAGS}" CACHE STRING "toolchain_cflags" FORCE) +SET(CMAKE_CXX_FLAGS "${IOS_COMMON_FLAGS}" CACHE STRING "toolchain_cxxflags" FORCE) +SET(CMAKE_LINK_FLAGS "${IOS_COMMON_FLAGS}" CACHE STRING "toolchain_linkflags" FORCE) diff --git a/configure b/configure index de6fe38..ba5ecbe 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.60 for LLVM 3.5.1. +# Generated by GNU Autoconf 2.60 for LLVM 3.6.0. # # Report bugs to . # @@ -561,8 +561,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='LLVM' PACKAGE_TARNAME='llvm' -PACKAGE_VERSION='3.5.1' -PACKAGE_STRING='LLVM 3.5.1' +PACKAGE_VERSION='3.6.0' +PACKAGE_STRING='LLVM 3.6.0' PACKAGE_BUGREPORT='http://llvm.org/bugs/' ac_unique_file="lib/IR/Module.cpp" @@ -752,10 +752,8 @@ GROFF GZIPBIN PDFROFF ZIP -OCAMLC -OCAMLOPT -OCAMLDEP -OCAMLDOC +GO +OCAMLFIND GAS HAVE_LINK_VERSION_SCRIPT EGREP @@ -764,6 +762,7 @@ NO_MISSING_FIELD_INITIALIZERS COVERED_SWITCH_DEFAULT NO_MAYBE_UNINITIALIZED NO_UNINITIALIZED +NO_COMMENT PYTHON HAVE_DLOPEN HAVE_TERMINFO @@ -772,7 +771,6 @@ USE_INTEL_JITEVENTS XML2CONFIG LIBXML2_LIBS LIBXML2_INC -CXXCPP HAVE_PTHREAD HAVE_LIBZ HUGE_VAL_SANITY @@ -788,7 +786,8 @@ LLVM_INFODIR LLVM_MANDIR LLVM_CONFIGTIME BINDINGS_TO_BUILD -ALL_BINDINGS +HAVE_OCAMLOPT +HAVE_OCAML_OUNIT OCAML_LIBDIR ENABLE_VISIBILITY_INLINES_HIDDEN RPATH @@ -807,8 +806,7 @@ CPPFLAGS CXX CXXFLAGS CCC -CPP -CXXCPP' +CPP' ac_subdirs_all='projects/test-suite projects/llvm-test projects/poolalloc @@ -1316,7 +1314,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures LLVM 3.5.1 to adapt to many kinds of systems. +\`configure' configures LLVM 3.6.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1382,7 +1380,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of LLVM 3.5.1:";; + short | recursive ) echo "Configuration of LLVM 3.6.0:";; esac cat <<\_ACEOF @@ -1487,7 +1485,6 @@ Some influential environment variables: CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor - CXXCPP C++ preprocessor Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1553,7 +1550,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -LLVM configure 3.5.1 +LLVM configure 3.6.0 generated by GNU Autoconf 2.60 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1569,7 +1566,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by LLVM $as_me 3.5.1, which was +It was created by LLVM $as_me 3.6.0, which was generated by GNU Autoconf 2.60. Invocation command line was $ $0 $@ @@ -1924,8 +1921,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu LLVM_VERSION_MAJOR=3 -LLVM_VERSION_MINOR=5 -LLVM_VERSION_PATCH=1 +LLVM_VERSION_MINOR=6 +LLVM_VERSION_PATCH=0 LLVM_VERSION_SUFFIX= @@ -1944,6 +1941,11 @@ cat >>confdefs.h <<_ACEOF _ACEOF +cat >>confdefs.h <<_ACEOF +#define LLVM_VERSION_STRING "$PACKAGE_VERSION" +_ACEOF + + @@ -3989,11 +3991,6 @@ else llvm_cv_no_link_all_option="-Wl,-z,defaultextract" llvm_cv_os_type="SunOS" llvm_cv_platform_type="Unix" ;; - *-*-auroraux*) - llvm_cv_link_all_option="-Wl,-z,allextract" - llvm_cv_link_all_option="-Wl,-z,defaultextract" - llvm_cv_os_type="AuroraUX" - llvm_cv_platform_type="Unix" ;; *-*-win32*) llvm_cv_link_all_option="-Wl,--whole-archive" llvm_cv_no_link_all_option="-Wl,--no-whole-archive" @@ -4065,8 +4062,6 @@ else llvm_cv_target_os_type="GNU" ;; *-*-solaris*) llvm_cv_target_os_type="SunOS" ;; - *-*-auroraux*) - llvm_cv_target_os_type="AuroraUX" ;; *-*-win32*) llvm_cv_target_os_type="Win32" ;; *-*-mingw*) @@ -6879,18 +6874,16 @@ echo "${ECHO_T}no" >&6; } fi -for ac_prog in ocamlc -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 +# Extract the first word of "go", so it can be a program name with args. +set dummy go; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_path_OCAMLC+set}" = set; then +if test "${ac_cv_path_GO+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - case $OCAMLC in + case $GO in [\\/]* | ?:[\\/]*) - ac_cv_path_OCAMLC="$OCAMLC" # Let the user override the test with a path. + ac_cv_path_GO="$GO" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -6900,7 +6893,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_OCAMLC="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_GO="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -6911,31 +6904,28 @@ IFS=$as_save_IFS ;; esac fi -OCAMLC=$ac_cv_path_OCAMLC -if test -n "$OCAMLC"; then - { echo "$as_me:$LINENO: result: $OCAMLC" >&5 -echo "${ECHO_T}$OCAMLC" >&6; } +GO=$ac_cv_path_GO +if test -n "$GO"; then + { echo "$as_me:$LINENO: result: $GO" >&5 +echo "${ECHO_T}$GO" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi - test -n "$OCAMLC" && break -done - -for ac_prog in ocamlopt +for ac_prog in ocamlfind do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_path_OCAMLOPT+set}" = set; then +if test "${ac_cv_path_OCAMLFIND+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 else - case $OCAMLOPT in + case $OCAMLFIND in [\\/]* | ?:[\\/]*) - ac_cv_path_OCAMLOPT="$OCAMLOPT" # Let the user override the test with a path. + ac_cv_path_OCAMLFIND="$OCAMLFIND" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -6945,7 +6935,7 @@ do test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_OCAMLOPT="$as_dir/$ac_word$ac_exec_ext" + ac_cv_path_OCAMLFIND="$as_dir/$ac_word$ac_exec_ext" echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -6956,107 +6946,17 @@ IFS=$as_save_IFS ;; esac fi -OCAMLOPT=$ac_cv_path_OCAMLOPT -if test -n "$OCAMLOPT"; then - { echo "$as_me:$LINENO: result: $OCAMLOPT" >&5 -echo "${ECHO_T}$OCAMLOPT" >&6; } +OCAMLFIND=$ac_cv_path_OCAMLFIND +if test -n "$OCAMLFIND"; then + { echo "$as_me:$LINENO: result: $OCAMLFIND" >&5 +echo "${ECHO_T}$OCAMLFIND" >&6; } else { echo "$as_me:$LINENO: result: no" >&5 echo "${ECHO_T}no" >&6; } fi - test -n "$OCAMLOPT" && break -done - -for ac_prog in ocamldep -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_path_OCAMLDEP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $OCAMLDEP in - [\\/]* | ?:[\\/]*) - ac_cv_path_OCAMLDEP="$OCAMLDEP" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_OCAMLDEP="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - - ;; -esac -fi -OCAMLDEP=$ac_cv_path_OCAMLDEP -if test -n "$OCAMLDEP"; then - { echo "$as_me:$LINENO: result: $OCAMLDEP" >&5 -echo "${ECHO_T}$OCAMLDEP" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$OCAMLDEP" && break -done - -for ac_prog in ocamldoc -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ echo "$as_me:$LINENO: checking for $ac_word" >&5 -echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } -if test "${ac_cv_path_OCAMLDOC+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - case $OCAMLDOC in - [\\/]* | ?:[\\/]*) - ac_cv_path_OCAMLDOC="$OCAMLDOC" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_OCAMLDOC="$as_dir/$ac_word$ac_exec_ext" - echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - - ;; -esac -fi -OCAMLDOC=$ac_cv_path_OCAMLDOC -if test -n "$OCAMLDOC"; then - { echo "$as_me:$LINENO: result: $OCAMLDOC" >&5 -echo "${ECHO_T}$OCAMLDOC" >&6; } -else - { echo "$as_me:$LINENO: result: no" >&5 -echo "${ECHO_T}no" >&6; } -fi - - - test -n "$OCAMLDOC" && break + test -n "$OCAMLFIND" && break done for ac_prog in gas as @@ -8172,8 +8072,74 @@ then fi fi -{ echo "$as_me:$LINENO: result: $NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS $COVERED_SWITCH_DEFAULT $NO_UNINITIALIZED $NO_MAYBE_UNINITIALIZED" >&5 -echo "${ECHO_T}$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS $COVERED_SWITCH_DEFAULT $NO_UNINITIALIZED $NO_MAYBE_UNINITIALIZED" >&6; } + +no_comment= +llvm_cv_old_cxxflags="$CXXFLAGS" +CXXFLAGS="$CXXFLAGS -Wcomment -Werror" +cat >conftest.$ac_ext <<_ACEOF + + /* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +// Comment \o\ +// Another comment +int main() { return 0; } + + +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + + no_comment=-Wno-comment + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +NO_COMMENT=$no_comment + +CXXFLAGS="$llvm_cv_old_cxxflags" + +{ echo "$as_me:$LINENO: result: $NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS $COVERED_SWITCH_DEFAULT $NO_UNINITIALIZED $NO_MAYBE_UNINITIALIZED $NO_COMMENT" >&5 +echo "${ECHO_T}$NO_VARIADIC_MACROS $NO_MISSING_FIELD_INITIALIZERS $COVERED_SWITCH_DEFAULT $NO_UNINITIALIZED $NO_MAYBE_UNINITIALIZED $NO_COMMENT" >&6; } # Check whether --with-python was given. @@ -8193,8 +8159,8 @@ else echo "$as_me: WARNING: specified python ($PYTHON) is not usable, searching path" >&2;} fi - # Extract the first word of "python python2 python26", so it can be a program name with args. -set dummy python python2 python26; ac_word=$2 + # Extract the first word of "python python2 python27", so it can be a program name with args. +set dummy python python2 python27; ac_word=$2 { echo "$as_me:$LINENO: checking for $ac_word" >&5 echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } if test "${ac_cv_path_PYTHON+set}" = set; then @@ -8222,8 +8188,8 @@ IFS=$as_save_IFS test -z "$ac_cv_path_PYTHON" && ac_cv_path_PYTHON="{ echo "$as_me:$LINENO: result: not found" >&5 echo "${ECHO_T}not found" >&6; } - { { echo "$as_me:$LINENO: error: could not find python 2.5 or higher" >&5 -echo "$as_me: error: could not find python 2.5 or higher" >&2;} + { { echo "$as_me:$LINENO: error: could not find python 2.7 or higher" >&5 +echo "$as_me: error: could not find python 2.7 or higher" >&2;} { (exit 1); exit 1; }; }" ;; esac @@ -8240,23 +8206,23 @@ fi fi -{ echo "$as_me:$LINENO: checking for python >= 2.5" >&5 -echo $ECHO_N "checking for python >= 2.5... $ECHO_C" >&6; } +{ echo "$as_me:$LINENO: checking for python >= 2.7" >&5 +echo $ECHO_N "checking for python >= 2.7... $ECHO_C" >&6; } ac_python_version=`$PYTHON -V 2>&1 | cut -d' ' -f2` ac_python_version_major=`echo $ac_python_version | cut -d'.' -f1` ac_python_version_minor=`echo $ac_python_version | cut -d'.' -f2` ac_python_version_patch=`echo $ac_python_version | cut -d'.' -f3` if test "$ac_python_version_major" -gt "2" || \ (test "$ac_python_version_major" -eq "2" && \ - test "$ac_python_version_minor" -ge "5") ; then + test "$ac_python_version_minor" -ge "7") ; then { echo "$as_me:$LINENO: result: $PYTHON ($ac_python_version)" >&5 echo "${ECHO_T}$PYTHON ($ac_python_version)" >&6; } else { echo "$as_me:$LINENO: result: not found" >&5 echo "${ECHO_T}not found" >&6; } - { { echo "$as_me:$LINENO: error: found python $ac_python_version ($PYTHON); required >= 2.5 + { { echo "$as_me:$LINENO: error: found python $ac_python_version ($PYTHON); required >= 2.7 See \`config.log' for more details." >&5 -echo "$as_me: error: found python $ac_python_version ($PYTHON); required >= 2.5 +echo "$as_me: error: found python $ac_python_version ($PYTHON); required >= 2.7 See \`config.log' for more details." >&2;} { (exit 1); exit 1; }; } fi @@ -10920,285 +10886,24 @@ ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu -{ echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 -echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6; } -if test -z "$CXXCPP"; then - if test "${ac_cv_prog_CXXCPP+set}" = set; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - # Double quotes because CXXCPP needs to be expanded - for CXXCPP in "$CXX -E" "/lib/cpp" - do - ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - break -fi - - done - ac_cv_prog_CXXCPP=$CXXCPP - -fi - CXXCPP=$ac_cv_prog_CXXCPP -else - ac_cv_prog_CXXCPP=$CXXCPP -fi -{ echo "$as_me:$LINENO: result: $CXXCPP" >&5 -echo "${ECHO_T}$CXXCPP" >&6; } -ac_preproc_ok=false -for ac_cxx_preproc_warn_flag in '' yes -do - # Use a header file that comes with gcc, so configuring glibc - # with a fresh cross-compiler works. - # Prefer to if __STDC__ is defined, since - # exists even on freestanding compilers. - # On the NeXT, cc -E runs the code through the compiler's parser, - # not just through cpp. "Syntax error" is here to catch this case. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#ifdef __STDC__ -# include -#else -# include -#endif - Syntax error -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - : -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Broken: fails on valid input. -continue -fi - -rm -f conftest.err conftest.$ac_ext - - # OK, works on sane cases. Now check whether nonexistent headers - # can be detected and how. - cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - # Broken: success on invalid input. -continue -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - # Passes both tests. -ac_preproc_ok=: -break -fi - -rm -f conftest.err conftest.$ac_ext - -done -# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext -if $ac_preproc_ok; then - : -else - { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&5 -echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } -fi - -ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - for ac_header in cxxabi.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - { echo "$as_me:$LINENO: checking for $ac_header" >&5 +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then echo $ECHO_N "(cached) $ECHO_C" >&6 -fi -ac_res=`eval echo '${'$as_ac_Header'}'` - { echo "$as_me:$LINENO: result: $ac_res" >&5 -echo "${ECHO_T}$ac_res" >&6; } else - # Is the header compilable? -{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 -echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF + cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ _ACEOF cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ -$ac_includes_default +#include + + #include <$ac_header> _ACEOF rm -f conftest.$ac_objext @@ -11235,106 +10940,19 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; }; then - ac_header_compiler=yes + eval "$as_ac_Header=yes" else echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 - ac_header_compiler=no + eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 -echo "${ECHO_T}$ac_header_compiler" >&6; } - -# Is the header present? -{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 -echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } -cat >conftest.$ac_ext <<_ACEOF -/* confdefs.h. */ -_ACEOF -cat confdefs.h >>conftest.$ac_ext -cat >>conftest.$ac_ext <<_ACEOF -/* end confdefs.h. */ -#include <$ac_header> -_ACEOF -if { (ac_try="$ac_cpp conftest.$ac_ext" -case "(($ac_try" in - *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; - *) ac_try_echo=$ac_try;; -esac -eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 - (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 - ac_status=$? - grep -v '^ *+' conftest.er1 >conftest.err - rm -f conftest.er1 - cat conftest.err >&5 - echo "$as_me:$LINENO: \$? = $ac_status" >&5 - (exit $ac_status); } >/dev/null; then - if test -s conftest.err; then - ac_cpp_err=$ac_cxx_preproc_warn_flag - ac_cpp_err=$ac_cpp_err$ac_cxx_werror_flag - else - ac_cpp_err= - fi -else - ac_cpp_err=yes -fi -if test -z "$ac_cpp_err"; then - ac_header_preproc=yes -else - echo "$as_me: failed program was:" >&5 -sed 's/^/| /' conftest.$ac_ext >&5 - - ac_header_preproc=no -fi - -rm -f conftest.err conftest.$ac_ext -{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 -echo "${ECHO_T}$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in - yes:no: ) - { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 -echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} - ac_header_preproc=yes - ;; - no:yes:* ) - { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 -echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 -echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 -echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 -echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 -echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} - { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 -echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} - ( cat <<\_ASBOX -## ------------------------------------ ## -## Report this to http://llvm.org/bugs/ ## -## ------------------------------------ ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac -{ echo "$as_me:$LINENO: checking for $ac_header" >&5 -echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } -if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then - echo $ECHO_N "(cached) $ECHO_C" >&6 -else - eval "$as_ac_Header=\$ac_header_preproc" fi ac_res=`eval echo '${'$as_ac_Header'}'` { echo "$as_me:$LINENO: result: $ac_res" >&5 echo "${ECHO_T}$ac_res" >&6; } - -fi if test `eval echo '${'$as_ac_Header'}'` = yes; then cat >>confdefs.h <<_ACEOF #define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 @@ -11355,6 +10973,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu + for ac_header in dlfcn.h execinfo.h fcntl.h inttypes.h link.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` @@ -18618,39 +18237,55 @@ _ACEOF if test "$BINDINGS_TO_BUILD" = auto ; then BINDINGS_TO_BUILD="" - if test "x$OCAMLC" != x -a "x$OCAMLDEP" != x ; then + if test "x$OCAMLFIND" != x ; then BINDINGS_TO_BUILD="ocaml $BINDINGS_TO_BUILD" fi + if test "x$GO" != x ; then + if $GO run ${srcdir}/bindings/go/conftest.go ; then + BINDINGS_TO_BUILD="go $BINDINGS_TO_BUILD" + fi + fi fi BINDINGS_TO_BUILD=$BINDINGS_TO_BUILD -ALL_BINDINGS=ocaml - - binding_prereqs_failed=0 for a_binding in $BINDINGS_TO_BUILD ; do case "$a_binding" in ocaml) - if test "x$OCAMLC" = x ; then - { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&5 -echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlc not found. Try configure OCAMLC=/path/to/ocamlc" >&2;} + if test "x$OCAMLFIND" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlfind not found. Try configure OCAMLFIND=/path/to/ocamlfind" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlfind not found. Try configure OCAMLFIND=/path/to/ocamlfind" >&2;} binding_prereqs_failed=1 fi - if test "x$OCAMLDEP" = x ; then - { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&5 -echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamldep not found. Try configure OCAMLDEP=/path/to/ocamldep" >&2;} + + if $OCAMLFIND opt -version >/dev/null 2>/dev/null ; then + HAVE_OCAMLOPT=1 + else + HAVE_OCAMLOPT=0 + fi + + + if ! $OCAMLFIND query ctypes >/dev/null 2>/dev/null; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ctypes is not installed" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ctypes is not installed" >&2;} binding_prereqs_failed=1 fi - if test "x$OCAMLOPT" = x ; then - { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&5 -echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found. Try configure OCAMLOPT=/path/to/ocamlopt" >&2;} + + if $OCAMLFIND query oUnit >/dev/null 2>/dev/null; then + HAVE_OCAML_OUNIT=1 + else + HAVE_OCAML_OUNIT=0 + { echo "$as_me:$LINENO: WARNING: --enable-bindings=ocaml specified, but OUnit 2 is not installed. Tests will not run" >&5 +echo "$as_me: WARNING: --enable-bindings=ocaml specified, but OUnit 2 is not installed. Tests will not run" >&2;} fi + + if test "x$with_ocaml_libdir" != xauto ; then OCAML_LIBDIR=$with_ocaml_libdir else - ocaml_stdlib="`"$OCAMLC" -where`" + ocaml_stdlib="`"$OCAMLFIND" ocamlc -where`" if test "$LLVM_PREFIX" '<' "$ocaml_stdlib" -a "$ocaml_stdlib" '<' "$LLVM_PREFIX~" then # ocaml stdlib is beneath our prefix; use stdlib @@ -18663,6 +18298,21 @@ echo "$as_me: WARNING: --enable-bindings=ocaml specified, but ocamlopt not found fi fi ;; + go) + if test "x$GO" = x ; then + { echo "$as_me:$LINENO: WARNING: --enable-bindings=go specified, but go not found. Try configure GO=/path/to/go" >&5 +echo "$as_me: WARNING: --enable-bindings=go specified, but go not found. Try configure GO=/path/to/go" >&2;} + binding_prereqs_failed=1 + else + if $GO run ${srcdir}/bindings/go/conftest.go ; then + : + else + { echo "$as_me:$LINENO: WARNING: --enable-bindings=go specified, but need at least Go 1.2. Try configure GO=/path/to/go" >&5 +echo "$as_me: WARNING: --enable-bindings=go specified, but need at least Go 1.2. Try configure GO=/path/to/go" >&2;} + binding_prereqs_failed=1 + fi + fi + ;; esac done if test "$binding_prereqs_failed" = 1 ; then @@ -18808,6 +18458,12 @@ if test "${clang_src_root}" = ""; then clang_src_root="$srcdir/tools/clang" fi if test -f ${clang_src_root}/README.txt; then + +cat >>confdefs.h <<_ACEOF +#define CLANG_LIBDIR_SUFFIX "" +_ACEOF + + configh="include/clang/Config/config.h" doxy="docs/doxygen.cfg" ac_config_headers="$ac_config_headers tools/clang/${configh}:${clang_src_root}/${configh}.in" @@ -19245,7 +18901,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by LLVM $as_me 3.5.1, which was +This file was extended by LLVM $as_me 3.6.0, which was generated by GNU Autoconf 2.60. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19298,7 +18954,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -LLVM config.status 3.5.1 +LLVM config.status 3.6.0 configured by $0, generated by GNU Autoconf 2.60, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" @@ -19690,10 +19346,8 @@ GROFF!$GROFF$ac_delim GZIPBIN!$GZIPBIN$ac_delim PDFROFF!$PDFROFF$ac_delim ZIP!$ZIP$ac_delim -OCAMLC!$OCAMLC$ac_delim -OCAMLOPT!$OCAMLOPT$ac_delim -OCAMLDEP!$OCAMLDEP$ac_delim -OCAMLDOC!$OCAMLDOC$ac_delim +GO!$GO$ac_delim +OCAMLFIND!$OCAMLFIND$ac_delim GAS!$GAS$ac_delim HAVE_LINK_VERSION_SCRIPT!$HAVE_LINK_VERSION_SCRIPT$ac_delim EGREP!$EGREP$ac_delim @@ -19702,6 +19356,7 @@ NO_MISSING_FIELD_INITIALIZERS!$NO_MISSING_FIELD_INITIALIZERS$ac_delim COVERED_SWITCH_DEFAULT!$COVERED_SWITCH_DEFAULT$ac_delim NO_MAYBE_UNINITIALIZED!$NO_MAYBE_UNINITIALIZED$ac_delim NO_UNINITIALIZED!$NO_UNINITIALIZED$ac_delim +NO_COMMENT!$NO_COMMENT$ac_delim PYTHON!$PYTHON$ac_delim HAVE_DLOPEN!$HAVE_DLOPEN$ac_delim HAVE_TERMINFO!$HAVE_TERMINFO$ac_delim @@ -19710,7 +19365,6 @@ USE_INTEL_JITEVENTS!$USE_INTEL_JITEVENTS$ac_delim XML2CONFIG!$XML2CONFIG$ac_delim LIBXML2_LIBS!$LIBXML2_LIBS$ac_delim LIBXML2_INC!$LIBXML2_INC$ac_delim -CXXCPP!$CXXCPP$ac_delim HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim HAVE_LIBZ!$HAVE_LIBZ$ac_delim HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim @@ -19726,7 +19380,8 @@ LLVM_INFODIR!$LLVM_INFODIR$ac_delim LLVM_MANDIR!$LLVM_MANDIR$ac_delim LLVM_CONFIGTIME!$LLVM_CONFIGTIME$ac_delim BINDINGS_TO_BUILD!$BINDINGS_TO_BUILD$ac_delim -ALL_BINDINGS!$ALL_BINDINGS$ac_delim +HAVE_OCAMLOPT!$HAVE_OCAMLOPT$ac_delim +HAVE_OCAML_OUNIT!$HAVE_OCAML_OUNIT$ac_delim OCAML_LIBDIR!$OCAML_LIBDIR$ac_delim ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim RPATH!$RPATH$ac_delim @@ -19736,7 +19391,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 96; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/docs/Atomics.rst b/docs/Atomics.rst index 5f17c61..6c8303b 100644 --- a/docs/Atomics.rst +++ b/docs/Atomics.rst @@ -18,16 +18,16 @@ clarified in the IR. The atomic instructions are designed specifically to provide readable IR and optimized code generation for the following: -* The new C++0x ```` header. (`C++0x draft available here - `_.) (`C1x draft available here +* The new C++11 ```` header. (`C++11 draft available here + `_.) (`C11 draft available here `_.) * Proper semantics for Java-style memory, for both ``volatile`` and regular shared variables. (`Java Specification - `_) + `_) * gcc-compatible ``__sync_*`` builtins. (`Description - `_) + `_) * Other scenarios with atomic semantics, including ``static`` variables with non-trivial constructors in C++. @@ -115,7 +115,10 @@ memory operation can happen on any thread between the load and store. A ``fence`` provides Acquire and/or Release ordering which is not part of another operation; it is normally used along with Monotonic memory operations. A Monotonic load followed by an Acquire fence is roughly equivalent to an -Acquire load. +Acquire load, and a Monotonic store following a Release fence is roughly +equivalent to a Release store. SequentiallyConsistent fences behave as both +an Acquire and a Release fence, and offer some additional complicated +guarantees, see the C++11 standard for details. Frontends generating atomic instructions generally need to be aware of the target to some degree; atomic instructions are guaranteed to be lock-free, and @@ -177,10 +180,10 @@ Unordered Unordered is the lowest level of atomicity. It essentially guarantees that races produce somewhat sane results instead of having undefined behavior. It also -guarantees the operation to be lock-free, so it do not depend on the data being -part of a special atomic structure or depend on a separate per-process global -lock. Note that code generation will fail for unsupported atomic operations; if -you need such an operation, use explicit locking. +guarantees the operation to be lock-free, so it does not depend on the data +being part of a special atomic structure or depend on a separate per-process +global lock. Note that code generation will fail for unsupported atomic +operations; if you need such an operation, use explicit locking. Relevant standard This is intended to match the Java memory model for shared variables. @@ -221,7 +224,7 @@ essentially guarantees that if you take all the operations affecting a specific address, a consistent ordering exists. Relevant standard - This corresponds to the C++0x/C1x ``memory_order_relaxed``; see those + This corresponds to the C++11/C11 ``memory_order_relaxed``; see those standards for the exact definition. Notes for frontends @@ -251,8 +254,8 @@ Acquire provides a barrier of the sort necessary to acquire a lock to access other memory with normal loads and stores. Relevant standard - This corresponds to the C++0x/C1x ``memory_order_acquire``. It should also be - used for C++0x/C1x ``memory_order_consume``. + This corresponds to the C++11/C11 ``memory_order_acquire``. It should also be + used for C++11/C11 ``memory_order_consume``. Notes for frontends If you are writing a frontend which uses this directly, use with caution. @@ -281,7 +284,7 @@ Release is similar to Acquire, but with a barrier of the sort necessary to release a lock. Relevant standard - This corresponds to the C++0x/C1x ``memory_order_release``. + This corresponds to the C++11/C11 ``memory_order_release``. Notes for frontends If you are writing a frontend which uses this directly, use with caution. @@ -307,7 +310,7 @@ AcquireRelease (``acq_rel`` in IR) provides both an Acquire and a Release barrier (for fences and operations which both read and write memory). Relevant standard - This corresponds to the C++0x/C1x ``memory_order_acq_rel``. + This corresponds to the C++11/C11 ``memory_order_acq_rel``. Notes for frontends If you are writing a frontend which uses this directly, use with caution. @@ -330,7 +333,7 @@ and Release semantics for stores. Additionally, it guarantees that a total ordering exists between all SequentiallyConsistent operations. Relevant standard - This corresponds to the C++0x/C1x ``memory_order_seq_cst``, Java volatile, and + This corresponds to the C++11/C11 ``memory_order_seq_cst``, Java volatile, and the gcc-compatible ``__sync_*`` builtins which do not specify otherwise. Notes for frontends @@ -368,6 +371,11 @@ Predicates for optimizer writers to query: that they return true for any operation which is volatile or at least Monotonic. +* ``isAtLeastAcquire()``/``isAtLeastRelease()``: These are predicates on + orderings. They can be useful for passes that are aware of atomics, for + example to do DSE across a single atomic access, but not across a + release-acquire pair (see MemoryDependencyAnalysis for an example of this) + * Alias analysis: Note that AA will return ModRef for anything Acquire or Release, and for the address accessed by any Monotonic operation. @@ -389,7 +397,9 @@ operations: * DSE: Unordered stores can be DSE'ed like normal stores. Monotonic stores can be DSE'ed in some cases, but it's tricky to reason about, and not especially - important. + important. It is possible in some case for DSE to operate across a stronger + atomic operation, but it is fairly tricky. DSE delegates this reasoning to + MemoryDependencyAnalysis (which is also used by other passes like GVN). * Folding a load: Any atomic load from a constant global can be constant-folded, because it cannot be observed. Similar reasoning allows scalarrepl with @@ -400,7 +410,8 @@ Atomics and Codegen Atomic operations are represented in the SelectionDAG with ``ATOMIC_*`` opcodes. On architectures which use barrier instructions for all atomic ordering (like -ARM), appropriate fences are split out as the DAG is built. +ARM), appropriate fences can be emitted by the AtomicExpand Codegen pass if +``setInsertFencesForAtomic()`` was used. The MachineMemOperand for all atomic operations is currently marked as volatile; this is not correct in the IR sense of volatile, but CodeGen handles anything @@ -415,11 +426,6 @@ error when given an operation which cannot be implemented. (The LLVM code generator is not very helpful here at the moment, but hopefully that will change.) -The implementation of atomics on LL/SC architectures (like ARM) is currently a -bit of a mess; there is a lot of copy-pasted code across targets, and the -representation is relatively unsuited to optimization (it would be nice to be -able to optimize loops involving cmpxchg etc.). - On x86, all atomic loads generate a ``MOV``. SequentiallyConsistent stores generate an ``XCHG``, other stores generate a ``MOV``. SequentiallyConsistent fences generate an ``MFENCE``, other fences do not cause any code to be @@ -435,3 +441,19 @@ operation. Loads and stores generate normal instructions. ``cmpxchg`` and ``atomicrmw`` can be represented using a loop with LL/SC-style instructions which take some sort of exclusive lock on a cache line (``LDREX`` and ``STREX`` on ARM, etc.). + +It is often easiest for backends to use AtomicExpandPass to lower some of the +atomic constructs. Here are some lowerings it can do: + +* cmpxchg -> loop with load-linked/store-conditional + by overriding ``hasLoadLinkedStoreConditional()``, ``emitLoadLinked()``, + ``emitStoreConditional()`` +* large loads/stores -> ll-sc/cmpxchg + by overriding ``shouldExpandAtomicStoreInIR()``/``shouldExpandAtomicLoadInIR()`` +* strong atomic accesses -> monotonic accesses + fences + by using ``setInsertFencesForAtomic()`` and overriding ``emitLeadingFence()`` + and ``emitTrailingFence()`` +* atomic rmw -> loop with cmpxchg or load-linked/store-conditional + by overriding ``expandAtomicRMWInIR()`` + +For an example of all of these, look at the ARM backend. diff --git a/docs/BitCodeFormat.rst b/docs/BitCodeFormat.rst index fce1e37..fc553f7 100644 --- a/docs/BitCodeFormat.rst +++ b/docs/BitCodeFormat.rst @@ -28,8 +28,9 @@ Unlike XML, the bitstream format is a binary encoding, and unlike XML it provides a mechanism for the file to self-describe "abbreviations", which are effectively size optimizations for the content. -LLVM IR files may be optionally embedded into a `wrapper`_ structure that makes -it easy to embed extra data along with LLVM IR files. +LLVM IR files may be optionally embedded into a `wrapper`_ structure, or in a +`native object file`_. Both of these mechanisms make it easy to embed extra +data along with LLVM IR files. This document first describes the LLVM bitstream format, describes the wrapper format, then describes the record structure used by LLVM IR files. @@ -460,6 +461,19 @@ to the start of the bitcode stream in the file, and the Size field is the size in bytes of the stream. CPUType is a target-specific value that can be used to encode the CPU of the target. +.. _native object file: + +Native Object File Wrapper Format +================================= + +Bitcode files for LLVM IR may also be wrapped in a native object file +(i.e. ELF, COFF, Mach-O). The bitcode must be stored in a section of the +object file named ``.llvmbc``. This wrapper format is useful for accommodating +LTO in compilation pipelines where intermediate objects must be native object +files which contain metadata in other sections. + +Not all tools support this format. + .. _encoding of LLVM IR: LLVM IR Encoding @@ -714,7 +728,7 @@ global variable. The operand fields are: * *unnamed_addr*: If present and non-zero, indicates that the variable has ``unnamed_addr`` -.. _dllstorageclass: +.. _bcdllstorageclass: * *dllstorageclass*: If present, an encoding of the DLL storage class of this variable: @@ -727,7 +741,7 @@ global variable. The operand fields are: MODULE_CODE_FUNCTION Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prefix, dllstorageclass]`` +``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata]`` The ``FUNCTION`` record (code 8) marks the declaration or definition of a function. The operand fields are: @@ -770,10 +784,17 @@ function. The operand fields are: * *unnamed_addr*: If present and non-zero, indicates that the function has ``unnamed_addr`` -* *prefix*: If non-zero, the value index of the prefix data for this function, +* *prologuedata*: If non-zero, the value index of the prologue data for this function, + plus 1. + +* *dllstorageclass*: An encoding of the + :ref:`dllstorageclass` of this function + +* *comdat*: An encoding of the COMDAT of this function + +* *prefixdata*: If non-zero, the value index of the prefix data for this function, plus 1. -* *dllstorageclass*: An encoding of the `dllstorageclass`_ of this function MODULE_CODE_ALIAS Record ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -791,7 +812,8 @@ fields are * *visibility*: If present, an encoding of the `visibility`_ of the alias -* *dllstorageclass*: If present, an encoding of the `dllstorageclass`_ of the alias +* *dllstorageclass*: If present, an encoding of the + :ref:`dllstorageclass` of the alias MODULE_CODE_PURGEVALS Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/docs/CMake.rst b/docs/CMake.rst index 957c5d4..47cb2f3 100644 --- a/docs/CMake.rst +++ b/docs/CMake.rst @@ -234,7 +234,7 @@ LLVM-specific variables Enable all compiler warnings. Defaults to ON. **LLVM_ENABLE_PEDANTIC**:BOOL - Enable pedantic mode. This disable compiler specific extensions, is + Enable pedantic mode. This disables compiler specific extensions, if possible. Defaults to ON. **LLVM_ENABLE_WERROR**:BOOL @@ -288,8 +288,14 @@ LLVM-specific variables **LLVM_USE_SANITIZER**:STRING Define the sanitizer used to build LLVM binaries and tests. Possible values - are ``Address``, ``Memory`` and ``MemoryWithOrigins``. Defaults to empty - string. + are ``Address``, ``Memory``, ``MemoryWithOrigins`` and ``Undefined``. + Defaults to empty string. + +**LLVM_PARALLEL_COMPILE_JOBS**:STRING + Define the maximum number of concurrent compilation jobs. + +**LLVM_PARALLEL_LINK_JOBS**:STRING + Define the maximum number of concurrent link jobs. **LLVM_BUILD_DOCS**:BOOL Enables all enabled documentation targets (i.e. Doxgyen and Sphinx targets) to @@ -363,6 +369,10 @@ LLVM-specific variables is enabled). Currently the only target added is ``docs-llvm-man``. Defaults to ON. +**SPHINX_WARNINGS_AS_ERRORS**:BOOL + If enabled then sphinx documentation warnings will be treated as + errors. Defaults to ON. + Executing the test suite ======================== @@ -389,8 +399,6 @@ for a quick solution. Also see the `LLVM-specific variables`_ section for variables used when cross-compiling. -.. _Embedding LLVM in your project: - Embedding LLVM in your project ============================== diff --git a/docs/CMakeLists.txt b/docs/CMakeLists.txt index d310a0a..da27627 100644 --- a/docs/CMakeLists.txt +++ b/docs/CMakeLists.txt @@ -104,3 +104,46 @@ if (LLVM_ENABLE_SPHINX) endif() endif() + +list(FIND LLVM_BINDINGS_LIST ocaml uses_ocaml) +if( NOT uses_ocaml LESS 0 ) + set(doc_targets + ocaml_llvm + ocaml_llvm_all_backends + ocaml_llvm_analysis + ocaml_llvm_bitreader + ocaml_llvm_bitwriter + ocaml_llvm_executionengine + ocaml_llvm_irreader + ocaml_llvm_linker + ocaml_llvm_target + ocaml_llvm_ipo + ocaml_llvm_passmgr_builder + ocaml_llvm_scalar_opts + ocaml_llvm_transform_utils + ocaml_llvm_vectorize + ) + + foreach(llvm_target ${LLVM_TARGETS_TO_BUILD}) + list(APPEND doc_targets ocaml_llvm_${llvm_target}) + endforeach() + + set(odoc_files) + foreach( doc_target ${doc_targets} ) + get_target_property(odoc_file ${doc_target} OCAML_ODOC) + list(APPEND odoc_files -load ${odoc_file}) + endforeach() + + add_custom_target(ocaml_doc + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + COMMAND ${OCAMLFIND} ocamldoc -d ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + -sort -colorize-code -html ${odoc_files}) + + add_dependencies(ocaml_doc ${doc_targets}) + + if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html + DESTINATION docs/ocaml/html) + endif() +endif() diff --git a/docs/CodeGenerator.rst b/docs/CodeGenerator.rst index 5736e43..7e5b6eb 100644 --- a/docs/CodeGenerator.rst +++ b/docs/CodeGenerator.rst @@ -290,10 +290,10 @@ the opcode, the number of operands, the list of implicit register uses and defs, whether the instruction has certain target-independent properties (accesses memory, is commutable, etc), and holds any target-specific flags. -The ``TargetFrameInfo`` class ------------------------------ +The ``TargetFrameLowering`` class +--------------------------------- -The ``TargetFrameInfo`` class is used to provide information about the stack +The ``TargetFrameLowering`` class is used to provide information about the stack frame layout of the target. It holds the direction of stack growth, the known stack alignment on entry to each function, and the offset to the local area. The offset to the local area is the offset from the stack pointer on function @@ -464,7 +464,7 @@ code: mov %EAX, %EDX sar %EDX, 31 idiv %ECX - ret + ret This approach is extremely general (if it can handle the X86 architecture, it can handle anything!) and allows all of the target specific knowledge about the @@ -769,7 +769,9 @@ provide an ordering between nodes that have side effects (such as loads, stores, calls, returns, etc). All nodes that have side effects should take a token chain as input and produce a new one as output. By convention, token chain inputs are always operand #0, and chain results are always the last value -produced by an operation. +produced by an operation. However, after instruction selection, the +machine nodes have their chain after the instruction's operands, and +may be followed by glue nodes. A SelectionDAG has designated "Entry" and "Root" nodes. The Entry node is always a marker node with an Opcode of ``ISD::EntryToken``. The Root node is @@ -846,6 +848,10 @@ is based on the final SelectionDAG, with nodes that must be scheduled together bundled into a single scheduling-unit node, and with immediate operands and other nodes that aren't relevant for scheduling omitted. +The option ``-filter-view-dags`` allows to select the name of the basic block +that you are interested to visualize and filters all the previous +``view-*-dags`` options. + .. _Build initial DAG: Initial SelectionDAG Construction diff --git a/docs/CodingStandards.rst b/docs/CodingStandards.rst index 3cfa1f66..0552c71 100644 --- a/docs/CodingStandards.rst +++ b/docs/CodingStandards.rst @@ -162,6 +162,8 @@ being aware of: * ``std::initializer_list`` (and the constructors and functions that take it as an argument) are not always available, so you cannot (for example) initialize a ``std::vector`` with a braced initializer list. +* ``std::equal()`` (and other algorithms) incorrectly assert in MSVC when given + ``nullptr`` as an iterator. Other than these areas you should assume the standard library is available and working as expected until some build bot tells you otherwise. If you're in an @@ -174,6 +176,25 @@ traits header to emulate it. .. _the libstdc++ manual: http://gcc.gnu.org/onlinedocs/gcc-4.7.3/libstdc++/manual/manual/status.html#status.iso.2011 +Other Languages +--------------- + +Any code written in the Go programming language is not subject to the +formatting rules below. Instead, we adopt the formatting rules enforced by +the `gofmt`_ tool. + +Go code should strive to be idiomatic. Two good sets of guidelines for what +this means are `Effective Go`_ and `Go Code Review Comments`_. + +.. _gofmt: + https://golang.org/cmd/gofmt/ + +.. _Effective Go: + https://golang.org/doc/effective_go.html + +.. _Go Code Review Comments: + https://code.google.com/p/go-wiki/wiki/CodeReviewComments + Mechanical Source Issues ======================== diff --git a/docs/CommandGuide/lit.rst b/docs/CommandGuide/lit.rst index 4d84be6..2708e9d 100644 --- a/docs/CommandGuide/lit.rst +++ b/docs/CommandGuide/lit.rst @@ -84,6 +84,14 @@ OUTPUT OPTIONS Do not use curses based progress bar. +.. option:: --show-unsupported + + Show the names of unsupported tests. + +.. option:: --show-xfail + + Show the names of tests that were expected to fail. + .. _execution-options: EXECUTION OPTIONS @@ -262,7 +270,7 @@ Once a test suite is discovered, its config file is loaded. Config files themselves are Python modules which will be executed. When the config file is executed, two important global variables are predefined: -**lit** +**lit_config** The global **lit** configuration object (a *LitConfig* instance), which defines the builtin test formats, global configuration parameters, and other helper @@ -307,14 +315,6 @@ executed, two important global variables are predefined: **root** The root configuration. This is the top-most :program:`lit` configuration in the project. - **on_clone** The config is actually cloned for every subdirectory inside a test - suite, to allow local configuration on a per-directory basis. The *on_clone* - variable can be set to a Python function which will be called whenever a - configuration is cloned (for a subdirectory). The function should takes three - arguments: (1) the parent configuration, (2) the new configuration (which the - *on_clone* function will generally modify), and (3) the test path to the new - directory being scanned. - **pipefail** Normally a test using a shell pipe fails if any of the commands on the pipe fail. If this is not desired, setting this variable to false makes the test fail only if the last command in the pipe fails. diff --git a/docs/CommandGuide/llvm-config.rst b/docs/CommandGuide/llvm-config.rst index 0ebb344..34075d0 100644 --- a/docs/CommandGuide/llvm-config.rst +++ b/docs/CommandGuide/llvm-config.rst @@ -151,7 +151,7 @@ libraries. Useful "virtual" components include: **all** - Includes all LLVM libaries. The default if no components are specified. + Includes all LLVM libraries. The default if no components are specified. diff --git a/docs/CommandGuide/llvm-symbolizer.rst b/docs/CommandGuide/llvm-symbolizer.rst index ce2d9c0..96720e6 100644 --- a/docs/CommandGuide/llvm-symbolizer.rst +++ b/docs/CommandGuide/llvm-symbolizer.rst @@ -92,6 +92,13 @@ OPTIONS input (see example above). If architecture is not specified in either way, address will not be symbolized. Defaults to empty string. +.. option:: -dsym-hint= + + (Darwin-only flag). If the debug info for a binary isn't present in the default + location, look for the debug info at the .dSYM path provided via the + ``-dsym-hint`` flag. This flag can be used multiple times. + + EXIT STATUS ----------- diff --git a/docs/CommandGuide/opt.rst b/docs/CommandGuide/opt.rst index ad5b62c..3a050f7 100644 --- a/docs/CommandGuide/opt.rst +++ b/docs/CommandGuide/opt.rst @@ -62,27 +62,14 @@ OPTIONS available. The order in which the options occur on the command line are the order in which they are executed (within pass constraints). -.. option:: -std-compile-opts - - This is short hand for a standard list of *compile time optimization* passes. - It might be useful for other front end compilers as well. To discover the - full set of options available, use the following command: - - .. code-block:: sh - - llvm-as < /dev/null | opt -std-compile-opts -disable-output -debug-pass=Arguments - .. option:: -disable-inlining - This option is only meaningful when :option:`-std-compile-opts` is given. It - simply removes the inlining pass from the standard list. + This option simply removes the inlining pass from the standard list. .. option:: -disable-opt - This option is only meaningful when :option:`-std-compile-opts` is given. It - disables most, but not all, of the :option:`-std-compile-opts`. The ones that - remain are :option:`-verify`, :option:`-lower-setjmp`, and - :option:`-funcresolve`. + This option is only meaningful when :option:`-std-link-opts` is given. It + disables most passes. .. option:: -strip-debug @@ -95,9 +82,7 @@ OPTIONS This option causes opt to add a verify pass after every pass otherwise specified on the command line (including :option:`-verify`). This is useful for cases where it is suspected that a pass is creating an invalid module but - it is not clear which pass is doing it. The combination of - :option:`-std-compile-opts` and :option:`-verify-each` can quickly track down - this kind of problem. + it is not clear which pass is doing it. .. option:: -stats diff --git a/docs/CommandLine.rst b/docs/CommandLine.rst index 1b342e3..1d85215 100644 --- a/docs/CommandLine.rst +++ b/docs/CommandLine.rst @@ -1630,13 +1630,13 @@ To start out, we declare our new ``FileSizeParser`` class: .. code-block:: c++ - struct FileSizeParser : public cl::basic_parser { + struct FileSizeParser : public cl::parser { // parse - Return true on error. - bool parse(cl::Option &O, const char *ArgName, const std::string &ArgValue, + bool parse(cl::Option &O, StringRef ArgName, const std::string &ArgValue, unsigned &Val); }; -Our new class inherits from the ``cl::basic_parser`` template class to fill in +Our new class inherits from the ``cl::parser`` template class to fill in the default, boiler plate code for us. We give it the data type that we parse into, the last argument to the ``parse`` method, so that clients of our custom parser know what object type to pass in to the parse method. (Here we declare @@ -1652,7 +1652,7 @@ implement ``parse`` as: .. code-block:: c++ - bool FileSizeParser::parse(cl::Option &O, const char *ArgName, + bool FileSizeParser::parse(cl::Option &O, StringRef ArgName, const std::string &Arg, unsigned &Val) { const char *ArgStart = Arg.c_str(); char *End; @@ -1698,7 +1698,7 @@ Which adds this to the output of our program: OPTIONS: -help - display available options (-help-hidden for more) ... - -max-file-size= - Maximum file size to accept + -max-file-size= - Maximum file size to accept And we can test that our parse works correctly now (the test program just prints out the max-file-size argument value): diff --git a/docs/CompilerWriterInfo.rst b/docs/CompilerWriterInfo.rst index 606b5f5..a012c32 100644 --- a/docs/CompilerWriterInfo.rst +++ b/docs/CompilerWriterInfo.rst @@ -74,6 +74,7 @@ R600 * `AMD Evergreen shader ISA `_ * `AMD Cayman/Trinity shader ISA `_ * `AMD Southern Islands Series ISA `_ +* `AMD Sea Islands Series ISA `_ * `AMD GPU Programming Guide `_ * `AMD Compute Resources `_ diff --git a/docs/CoverageMappingFormat.rst b/docs/CoverageMappingFormat.rst new file mode 100644 index 0000000..8fcffb8 --- /dev/null +++ b/docs/CoverageMappingFormat.rst @@ -0,0 +1,576 @@ +.. role:: raw-html(raw) + :format: html + +================================= +LLVM Code Coverage Mapping Format +================================= + +.. contents:: + :local: + +Introduction +============ + +LLVM's code coverage mapping format is used to provide code coverage +analysis using LLVM's and Clang's instrumenation based profiling +(Clang's ``-fprofile-instr-generate`` option). + +This document is aimed at those who use LLVM's code coverage mapping to provide +code coverage analysis for their own programs, and for those who would like +to know how it works under the hood. A prior knowledge of how Clang's profile +guided optimization works is useful, but not required. + +We start by showing how to use LLVM and Clang for code coverage analysis, +then we briefly desribe LLVM's code coverage mapping format and the +way that Clang and LLVM's code coverage tool work with this format. After +the basics are down, more advanced features of the coverage mapping format +are discussed - such as the data structures, LLVM IR representation and +the binary encoding. + +Quick Start +=========== + +Here's a short story that describes how to generate code coverage overview +for a sample source file called *test.c*. + +* First, compile an instrumented version of your program using Clang's + ``-fprofile-instr-generate`` option with the additional ``-fcoverage-mapping`` + option: + + ``clang -o test -fprofile-instr-generate -fcoverage-mapping test.c`` +* Then, run the instrumented binary. The runtime will produce a file called + *default.profraw* containing the raw profile instrumentation data: + + ``./test`` +* After that, merge the profile data using the *llvm-profdata* tool: + + ``llvm-profdata merge -o test.profdata default.profraw`` +* Finally, run LLVM's code coverage tool (*llvm-cov*) to produce the code + coverage overview for the sample source file: + + ``llvm-cov show ./test -instr-profile=test.profdata test.c`` + +High Level Overview +=================== + +LLVM's code coverage mapping format is designed to be a self contained +data format, that can be embedded into the LLVM IR and object files. +It's described in this document as a **mapping** format because its goal is +to store the data that is required for a code coverage tool to map between +the specific source ranges in a file and the execution counts obtained +after running the instrumented version of the program. + +The mapping data is used in two places in the code coverage process: + +1. When clang compiles a source file with ``-fcoverage-mapping``, it + generates the mapping information that describes the mapping between the + source ranges and the profiling instrumentation counters. + This information gets embedded into the LLVM IR and conveniently + ends up in the final executable file when the program is linked. + +2. It is also used by *llvm-cov* - the mapping information is extracted from an + object file and is used to associate the execution counts (the values of the + profile instrumentation counters), and the source ranges in a file. + After that, the tool is able to generate various code coverage reports + for the program. + +The coverage mapping format aims to be a "universal format" that would be +suitable for usage by any frontend, and not just by Clang. It also aims to +provide the frontend the possibility of generating the minimal coverage mapping +data in order to reduce the size of the IR and object files - for example, +instead of emitting mapping information for each statement in a function, the +frontend is allowed to group the statements with the same execution count into +regions of code, and emit the mapping information only for those regions. + +Advanced Concepts +================= + +The remainder of this guide is meant to give you insight into the way the +coverage mapping format works. + +The coverage mapping format operates on a per-function level as the +profile instrumentation counters are associated with a specific function. +For each function that requires code coverage, the frontend has to create +coverage mapping data that can map between the source code ranges and +the profile instrumentation counters for that function. + +Mapping Region +-------------- + +The function's coverage mapping data contains an array of mapping regions. +A mapping region stores the `source code range`_ that is covered by this region, +the `file id `_, the `coverage mapping counter`_ and +the region's kind. +There are several kinds of mapping regions: + +* Code regions associate portions of source code and `coverage mapping + counters`_. They make up the majority of the mapping regions. They are used + by the code coverage tool to compute the execution counts for lines, + highlight the regions of code that were never executed, and to obtain + the various code coverage statistics for a function. + For example: + + :raw-html:`
int main(int argc, const char *argv[]) {     // Code Region from 1:40 to 9:2
+                                              
+    if (argc > 1) {                            // Code Region from 3:17 to 5:4
+      printf("%s\n", argv[1]);              
+    } else {                                   // Code Region from 5:10 to 7:4
+      printf("\n");                         
+    }                                         
+    return 0;                                 
+  }
+  
` +* Skipped regions are used to represent source ranges that were skipped + by Clang's preprocessor. They don't associate with + `coverage mapping counters`_, as the frontend knows that they are never + executed. They are used by the code coverage tool to mark the skipped lines + inside a function as non-code lines that don't have execution counts. + For example: + + :raw-html:`
int main() {                // Code Region from 1:12 to 6:2
+  #ifdef DEBUG                // Skipped Region from 2:1 to 4:2
+    printf("Hello world"); 
+  #endif                     
+    return 0;                
+  }
+  
` +* Expansion regions are used to represent Clang's macro expansions. They + have an additional property - *expanded file id*. This property can be + used by the code coverage tool to find the mapping regions that are created + as a result of this macro expansion, by checking if their file id matches the + expanded file id. They don't associate with `coverage mapping counters`_, + as the code coverage tool can determine the execution count for this region + by looking up the execution count of the first region with a corresponding + file id. + For example: + + :raw-html:`
int func(int x) {                             
+    #define MAX(x,y) ((x) > (y)? (x) : (y))     
+    return MAX(x, 42);                           // Expansion Region from 3:10 to 3:13
+  }
+  
` + +.. _source code range: + +Source Range: +^^^^^^^^^^^^^ + +The source range record contains the starting and ending location of a certain +mapping region. Both locations include the line and the column numbers. + +.. _coverage file id: + +File ID: +^^^^^^^^ + +The file id an integer value that tells us +in which source file or macro expansion is this region located. +It enables Clang to produce mapping information for the code +defined inside macros, like this example demonstrates: + +:raw-html:`
void func(const char *str) {         // Code Region from 1:28 to 6:2 with file id 0
+  #define PUT printf("%s\n", str)    // 2 Code Regions from 2:15 to 2:34 with file ids 1 and 2
+  if(*str)                          
+    PUT;                             // Expansion Region from 4:5 to 4:8 with file id 0 that expands a macro with file id 1
+  PUT;                               // Expansion Region from 5:3 to 5:6 with file id 0 that expands a macro with file id 2
+}
+
` + +.. _coverage mapping counter: +.. _coverage mapping counters: + +Counter: +^^^^^^^^ + +A coverage mapping counter can represents a reference to the profile +instrumentation counter. The execution count for a region with such counter +is determined by looking up the value of the corresponding profile +instrumentation counter. + +It can also represent a binary arithmetical expression that operates on +coverage mapping counters or other expressions. +The execution count for a region with an expression counter is determined by +evaluating the expression's arguments and then adding them together or +subtracting them from one another. +In the example below, a subtraction expression is used to compute the execution +count for the compound statement that follows the *else* keyword: + +:raw-html:`
int main(int argc, const char *argv[]) {    // Region's counter is a reference to the profile counter #0
+                                           
+  if (argc > 1) {                           // Region's counter is a reference to the profile counter #1
+    printf("%s\n", argv[1]);                
+  } else {                                  // Region's counter is an expression (reference to the profile counter #0 - reference to the profile counter #1)
+    printf("\n");                        
+  }                                        
+  return 0;                                
+}
+
` + +Finally, a coverage mapping counter can also represent an execution count of +of zero. The zero counter is used to provide coverage mapping for +unreachable statements and expressions, like in the example below: + +:raw-html:`
int main() {                  
+  return 0;                   
+  printf("Hello world!\n");    // Unreachable region's counter is zero
+}
+
` + +The zero counters allow the code coverage tool to display proper line execution +counts for the unreachable lines and highlight the unreachable code. +Without them, the tool would think that those lines and regions were still +executed, as it doesn't possess the frontend's knowledge. + +LLVM IR Representation +====================== + +The coverage mapping data is stored in the LLVM IR using a single global +constant structure variable called *__llvm_coverage_mapping* +with the *__llvm_covmap* section specifier. + +For example, let’s consider a C file and how it gets compiled to LLVM: + +.. _coverage mapping sample: + +.. code-block:: c + + int foo() { + return 42; + } + int bar() { + return 13; + } + +The coverage mapping variable generated by Clang is: + +.. code-block:: llvm + + @__llvm_coverage_mapping = internal constant { i32, i32, i32, i32, [2 x { i8*, i32, i32 }], [40 x i8] } + { i32 2, ; The number of function records + i32 20, ; The length of the string that contains the encoded translation unit filenames + i32 20, ; The length of the string that contains the encoded coverage mapping data + i32 0, ; Coverage mapping format version + [2 x { i8*, i32, i32 }] [ ; Function records + { i8*, i32, i32 } { i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_foo, i32 0, i32 0), ; Function's name + i32 3, ; Function's name length + i32 9 ; Function's encoded coverage mapping data string length + }, + { i8*, i32, i32 } { i8* getelementptr inbounds ([3 x i8]* @__llvm_profile_name_bar, i32 0, i32 0), ; Function's name + i32 3, ; Function's name length + i32 9 ; Function's encoded coverage mapping data string length + }], + [40 x i8] c"..." ; Encoded data (dissected later) + }, section "__llvm_covmap", align 8 + +Version: +-------- + +The coverage mapping version number can have the following values: + +* 0 — The first (current) version of the coverage mapping format. + +.. _function records: + +Function record: +---------------- + +A function record is a structure of the following type: + +.. code-block:: llvm + + { i8*, i32, i32 } + +It contains the pointer to the function's name, function's name length, +and the length of the encoded mapping data for that function. + +Encoded data: +------------- + +The encoded data is stored in a single string that contains +the encoded filenames used by this translation unit and the encoded coverage +mapping data for each function in this translation unit. + +The encoded data has the following structure: + +``[filenames, coverageMappingDataForFunctionRecord0, coverageMappingDataForFunctionRecord1, ..., padding]`` + +If necessary, the encoded data is padded with zeroes so that the size +of the data string is rounded up to the nearest multiple of 8 bytes. + +Dissecting the sample: +^^^^^^^^^^^^^^^^^^^^^^ + +Here's an overview of the encoded data that was stored in the +IR for the `coverage mapping sample`_ that was shown earlier: + +* The IR contains the following string constant that represents the encoded + coverage mapping data for the sample translation unit: + + .. code-block:: llvm + + c"\01\12/Users/alex/test.c\01\00\00\01\01\01\0C\02\02\01\00\00\01\01\04\0C\02\02\00\00" + +* The string contains values that are encoded in the LEB128 format, which is + used throughout for storing integers. It also contains a string value. + +* The length of the substring that contains the encoded translation unit + filenames is the value of the second field in the *__llvm_coverage_mapping* + structure, which is 20, thus the filenames are encoded in this string: + + .. code-block:: llvm + + c"\01\12/Users/alex/test.c" + + This string contains the following data: + + * Its first byte has a value of ``0x01``. It stores the number of filenames + contained in this string. + * Its second byte stores the length of the first filename in this string. + * The remaining 18 bytes are used to store the first filename. + +* The length of the substring that contains the encoded coverage mapping data + for the first function is the value of the third field in the first + structure in an array of `function records`_ stored in the + fifth field of the *__llvm_coverage_mapping* structure, which is the 9. + Therefore, the coverage mapping for the first function record is encoded + in this string: + + .. code-block:: llvm + + c"\01\00\00\01\01\01\0C\02\02" + + This string consists of the following bytes: + + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x01`` | The number of file ids used by this function. There is only one file id used by the mapping data in this function. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x00`` | An index into the filenames array which corresponds to the file "/Users/alex/test.c". | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x00`` | The number of counter expressions used by this function. This function doesn't use any expressions. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x01`` | The number of mapping regions that are stored in an array for the function's file id #0. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x01`` | The coverage mapping counter for the first region in this function. The value of 1 tells us that it's a coverage | + | | mapping counter that is a reference ot the profile instrumentation counter with an index of 0. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x01`` | The starting line of the first mapping region in this function. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x0C`` | The starting column of the first mapping region in this function. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x02`` | The ending line of the first mapping region in this function. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + | ``0x02`` | The ending column of the first mapping region in this function. | + +----------+-------------------------------------------------------------------------------------------------------------------------+ + +* The length of the substring that contains the encoded coverage mapping data + for the second function record is also 9. It's structured like the mapping data + for the first function record. + +* The two trailing bytes are zeroes and are used to pad the coverage mapping + data to give it the 8 byte alignment. + +Encoding +======== + +The per-function coverage mapping data is encoded as a stream of bytes, +with a simple structure. The structure consists of the encoding +`types `_ like variable-length unsigned integers, that +are used to encode `File ID Mapping`_, `Counter Expressions`_ and +the `Mapping Regions`_. + +The format of the structure follows: + + ``[file id mapping, counter expressions, mapping regions]`` + +The translation unit filenames are encoded using the same encoding +`types `_ as the per-function coverage mapping data, with the +following structure: + + ``[numFilenames : LEB128, filename0 : string, filename1 : string, ...]`` + +.. _cvmtypes: + +Types +----- + +This section describes the basic types that are used by the encoding format +and can appear after ``:`` in the ``[foo : type]`` description. + +.. _LEB128: + +LEB128 +^^^^^^ + +LEB128 is an unsigned interger value that is encoded using DWARF's LEB128 +encoding, optimizing for the case where values are small +(1 byte for values less than 128). + +.. _strings: + +Strings +^^^^^^^ + +``[length : LEB128, characters...]`` + +String values are encoded with a `LEB value `_ for the length +of the string and a sequence of bytes for its characters. + +.. _file id mapping: + +File ID Mapping +--------------- + +``[numIndices : LEB128, filenameIndex0 : LEB128, filenameIndex1 : LEB128, ...]`` + +File id mapping in a function's coverage mapping stream +contains the indices into the translation unit's filenames array. + +Counter +------- + +``[value : LEB128]`` + +A `coverage mapping counter`_ is stored in a single `LEB value `_. +It is composed of two things --- the `tag `_ +which is stored in the lowest 2 bits, and the `counter data`_ which is stored +in the remaining bits. + +.. _counter-tag: + +Tag: +^^^^ + +The counter's tag encodes the counter's kind +and, if the counter is an expression, the expression's kind. +The possible tag values are: + +* 0 - The counter is zero. + +* 1 - The counter is a reference to the profile instrumentation counter. + +* 2 - The counter is a subtraction expression. + +* 3 - The counter is an addition expression. + +.. _counter data: + +Data: +^^^^^ + +The counter's data is interpreted in the following manner: + +* When the counter is a reference to the profile instrumentation counter, + then the counter's data is the id of the profile counter. +* When the counter is an expression, then the counter's data + is the index into the array of counter expressions. + +.. _Counter Expressions: + +Counter Expressions +------------------- + +``[numExpressions : LEB128, expr0LHS : LEB128, expr0RHS : LEB128, expr1LHS : LEB128, expr1RHS : LEB128, ...]`` + +Counter expressions consist of two counters as they +represent binary arithmetic operations. +The expression's kind is determined from the `tag `_ of the +counter that references this expression. + +.. _Mapping Regions: + +Mapping Regions +--------------- + +``[numRegionArrays : LEB128, regionsForFile0, regionsForFile1, ...]`` + +The mapping regions are stored in an array of sub-arrays where every +region in a particular sub-array has the same file id. + +The file id for a sub-array of regions is the index of that +sub-array in the main array e.g. The first sub-array will have the file id +of 0. + +Sub-Array of Regions +^^^^^^^^^^^^^^^^^^^^ + +``[numRegions : LEB128, region0, region1, ...]`` + +The mapping regions for a specific file id are stored in an array that is +sorted in an ascending order by the region's starting location. + +Mapping Region +^^^^^^^^^^^^^^ + +``[header, source range]`` + +The mapping region record contains two sub-records --- +the `header`_, which stores the counter and/or the region's kind, +and the `source range`_ that contains the starting and ending +location of this region. + +.. _header: + +Header +^^^^^^ + +``[counter]`` + +or + +``[pseudo-counter]`` + +The header encodes the region's counter and the region's kind. + +The value of the counter's tag distinguishes between the counters and +pseudo-counters --- if the tag is zero, than this header contains a +pseudo-counter, otherwise this header contains an ordinary counter. + +Counter: +"""""""" + +A mapping region whose header has a counter with a non-zero tag is +a code region. + +Pseudo-Counter: +""""""""""""""" + +``[value : LEB128]`` + +A pseudo-counter is stored in a single `LEB value `_, just like +the ordinary counter. It has the following interpretation: + +* bits 0-1: tag, which is always 0. + +* bit 2: expansionRegionTag. If this bit is set, then this mapping region + is an expansion region. + +* remaining bits: data. If this region is an expansion region, then the data + contains the expanded file id of that region. + + Otherwise, the data contains the region's kind. The possible region + kind values are: + + * 0 - This mapping region is a code region with a counter of zero. + * 2 - This mapping region is a skipped region. + +.. _source range: + +Source Range +^^^^^^^^^^^^ + +``[deltaLineStart : LEB128, columnStart : LEB128, numLines : LEB128, columnEnd : LEB128]`` + +The source range record contains the following fields: + +* *deltaLineStart*: The difference between the starting line of the + current mapping region and the starting line of the previous mapping region. + + If the current mapping region is the first region in the current + sub-array, then it stores the starting line of that region. + +* *columnStart*: The starting column of the mapping region. + +* *numLines*: The difference between the ending line and the starting line + of the current mapping region. + +* *columnEnd*: The ending column of the mapping region. diff --git a/docs/DeveloperPolicy.rst b/docs/DeveloperPolicy.rst index 74a8979..508a04f 100644 --- a/docs/DeveloperPolicy.rst +++ b/docs/DeveloperPolicy.rst @@ -436,6 +436,29 @@ list, development list, or LLVM bug tracker component. If someone sends you a patch privately, encourage them to submit it to the appropriate list first. +IR Backwards Compatibility +-------------------------- + +When the IR format has to be changed, keep in mind that we try to maintain some +backwards compatibility. The rules are intended as a balance between convenience +for llvm users and not imposing a big burden on llvm developers: + +* The textual format is not backwards compatible. We don't change it too often, + but there are no specific promises. + +* The bitcode format produced by a X.Y release will be readable by all following + X.Z releases and the (X+1).0 release. + +* Newer releases can ignore features from older releases, but they cannot + miscompile them. For example, if nsw is ever replaced with something else, + dropping it would be a valid way to upgrade the IR. + +* Debug metadata is special in that it is currently dropped during upgrades. + +* Non-debug metadata is defined to be safe to drop, so a valid way to upgrade + it is to drop it. That is not very user friendly and a bit more effort is + expected, but no promises are made. + .. _copyright-license-patents: Copyright, License, and Patents diff --git a/docs/ExtendingLLVM.rst b/docs/ExtendingLLVM.rst index 60cbf01..2552c07 100644 --- a/docs/ExtendingLLVM.rst +++ b/docs/ExtendingLLVM.rst @@ -58,7 +58,7 @@ function and then be turned into an instruction if warranted. If it is possible to constant fold your intrinsic, add support to it in the ``canConstantFoldCallTo`` and ``ConstantFoldCall`` functions. -#. ``llvm/test/Regression/*``: +#. ``llvm/test/*``: Add test cases for your test cases to the test suite @@ -164,10 +164,10 @@ complicated behavior in a single node (rotate). #. TODO: document complex patterns. -#. ``llvm/test/Regression/CodeGen/*``: +#. ``llvm/test/CodeGen/*``: Add test cases for your new node to the test suite. - ``llvm/test/Regression/CodeGen/X86/bswap.ll`` is a good example. + ``llvm/test/CodeGen/X86/bswap.ll`` is a good example. Adding a new instruction ======================== @@ -217,7 +217,7 @@ Adding a new instruction add support for your instruction to code generators, or add a lowering pass. -#. ``llvm/test/Regression/*``: +#. ``llvm/test/*``: add your test cases to the test suite. diff --git a/docs/GarbageCollection.rst b/docs/GarbageCollection.rst index dc6dab1..49d3496 100644 --- a/docs/GarbageCollection.rst +++ b/docs/GarbageCollection.rst @@ -923,7 +923,7 @@ a realistic example: void MyGCPrinter::finishAssembly(AsmPrinter &AP) { MCStreamer &OS = AP.OutStreamer; - unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(); + unsigned IntPtrSize = AP.TM.getSubtargetImpl()->getDataLayout()->getPointerSize(); // Put this in the data section. OS.SwitchSection(AP.getObjFileLowering().getDataSection()); diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst index d409f62..316f1f7 100644 --- a/docs/GettingStarted.rst +++ b/docs/GettingStarted.rst @@ -115,7 +115,6 @@ LLVM is known to work on the following host platforms: ================== ===================== ============= OS Arch Compilers ================== ===================== ============= -AuroraUX x86\ :sup:`1` GCC Linux x86\ :sup:`1` GCC, Clang Linux amd64 GCC, Clang Linux ARM\ :sup:`4` GCC, Clang @@ -165,7 +164,7 @@ Package Version Notes =========================================================== ============ ========================================== `GNU Make `_ 3.79, 3.79.1 Makefile/build processor `GCC `_ >=4.7.0 C/C++ compiler\ :sup:`1` -`python `_ >=2.5 Automated test suite\ :sup:`2` +`python `_ >=2.7 Automated test suite\ :sup:`2` `GNU M4 `_ 1.4 Macro processor for configuration\ :sup:`3` `GNU Autoconf `_ 2.60 Configuration script builder\ :sup:`3` `GNU Automake `_ 1.9.6 aclocal macro generator\ :sup:`3` @@ -331,10 +330,23 @@ of this information from. .. _GCC wiki entry: http://gcc.gnu.org/wiki/InstallingGCC -Once you have a GCC toolchain, use it as your host compiler. Things should -generally "just work". You may need to pass a special linker flag, -``-Wl,-rpath,$HOME/toolchains/lib`` or some variant thereof to get things to -find the libstdc++ DSO in this toolchain. +Once you have a GCC toolchain, configure your build of LLVM to use the new +toolchain for your host compiler and C++ standard library. Because the new +version of libstdc++ is not on the system library search path, you need to pass +extra linker flags so that it can be found at link time (``-L``) and at runtime +(``-rpath``). If you are using CMake, this invocation should produce working +binaries: + +.. code-block:: console + + % mkdir build + % cd build + % CC=$HOME/toolchains/bin/gcc CXX=$HOME/toolchains/bin/g++ \ + cmake .. -DCMAKE_CXX_LINK_FLAGS="-Wl,-rpath,$HOME/toolchains/lib64 -L$HOME/toolchains/lib64" + +If you fail to set rpath, most LLVM binaries will fail on startup with a message +from the loader similar to ``libstdc++.so.6: version `GLIBCXX_3.4.20' not +found``. This means you need to tweak the -rpath linker flag. When you build Clang, you will need to give *it* access to modern C++11 standard library in order to use it as your new host in part of a bootstrap. @@ -1006,7 +1018,7 @@ This directory contains most of the source files of the LLVM system. In LLVM, almost all code exists in libraries, making it very easy to share code among the different `tools`_. -``llvm/lib/VMCore/`` +``llvm/lib/IR/`` This directory holds the core LLVM source files that implement core classes like Instruction and BasicBlock. diff --git a/docs/GettingStartedVS.rst b/docs/GettingStartedVS.rst index d914cc1..fa20912 100644 --- a/docs/GettingStartedVS.rst +++ b/docs/GettingStartedVS.rst @@ -57,8 +57,8 @@ You will also need the `CMake `_ build system since it generates the project files you will use to build with. If you would like to run the LLVM tests you will need `Python -`_. Versions 2.4-2.7 are known to work. You will need -`GnuWin32 `_ tools, too. +`_. Version 2.7 and newer are known to work. You will +need `GnuWin32 `_ tools, too. Do not install the LLVM directory tree into a path containing spaces (e.g. ``C:\Documents and Settings\...``) as the configure step will fail. diff --git a/docs/GoldPlugin.rst b/docs/GoldPlugin.rst index 28b202a..6328934 100644 --- a/docs/GoldPlugin.rst +++ b/docs/GoldPlugin.rst @@ -44,9 +44,11 @@ will either need to build gold or install a version with plugin support. the ``-plugin`` option. Running ``make`` will additionally build ``build/binutils/ar`` and ``nm-new`` binaries supporting plugins. -* Build the LLVMgold plugin: Configure LLVM with - ``--with-binutils-include=/path/to/binutils/include`` and run - ``make``. +* Build the LLVMgold plugin. If building with autotools, run configure with + ``--with-binutils-include=/path/to/binutils/include`` and run ``make``. + If building with CMake, run cmake with + ``-DLLVM_BINUTILS_INCDIR=/path/to/binutils/include``. The correct include + path will contain the file ``plugin-api.h``. Usage ===== diff --git a/docs/HowToSubmitABug.rst b/docs/HowToSubmitABug.rst index 702dc0c..9f997d2 100644 --- a/docs/HowToSubmitABug.rst +++ b/docs/HowToSubmitABug.rst @@ -89,7 +89,7 @@ Then run: .. code-block:: bash - opt -std-compile-opts -debug-pass=Arguments foo.bc -disable-output + opt -O3 -debug-pass=Arguments foo.bc -disable-output This command should do two things: it should print out a list of passes, and then it should crash in the same way as clang. If it doesn't crash, please diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 17ccf9b..b184749 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -75,11 +75,12 @@ identifiers, for different purposes: #. Named values are represented as a string of characters with their prefix. For example, ``%foo``, ``@DivisionByZero``, ``%a.really.long.identifier``. The actual regular expression used is - '``[%@][a-zA-Z$._][a-zA-Z$._0-9]*``'. Identifiers which require other + '``[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*``'. Identifiers that require other characters in their names can be surrounded with quotes. Special characters may be escaped using ``"\xx"`` where ``xx`` is the ASCII code for the character in hexadecimal. In this way, any character can - be used in a name value, even quotes themselves. + be used in a name value, even quotes themselves. The ``"\01"`` prefix + can be used on global variables to suppress mangling. #. Unnamed values are represented as an unsigned numeric value with their prefix. For example, ``%12``, ``@2``, ``%44``. #. Constants, which are described in the section Constants_ below. @@ -128,9 +129,10 @@ lexical features of LLVM: #. Unnamed temporaries are created when the result of a computation is not assigned to a named value. #. Unnamed temporaries are numbered sequentially (using a per-function - incrementing counter, starting with 0). Note that basic blocks are - included in this numbering. For example, if the entry basic block is not - given a label name, then it will get number 0. + incrementing counter, starting with 0). Note that basic blocks and unnamed + function parameters are included in this numbering. For example, if the + entry basic block is not given a label name and all function parameters are + named, then it will get number 0. It also shows a convention that we follow in this document. When demonstrating instructions, we will follow an instruction with a comment @@ -168,8 +170,8 @@ symbol table entries. Here is an example of the "hello world" module: } ; Named metadata - !1 = metadata !{i32 42} - !foo = !{!1, null} + !0 = !{i32 42, null, !"string"} + !foo = !{!0} This example is made up of a :ref:`global variable ` named "``.str``", an external declaration of the "``puts``" function, a @@ -500,7 +502,7 @@ Structure Types LLVM IR allows you to specify both "identified" and "literal" :ref:`structure types `. Literal types are uniqued structurally, but identified types are never uniqued. An :ref:`opaque structural type ` can also be used -to forward declare a type which is not yet available. +to forward declare a type that is not yet available. An example of a identified structure specification is: @@ -594,7 +596,8 @@ Syntax:: [@ =] [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [unnamed_addr] [AddrSpace] [ExternallyInitialized] [] - [, section "name"] [, align ] + [, section "name"] [, comdat [($name)]] + [, align ] For example, the following defines a global in a numbered address space with an initializer, section, and alignment: @@ -631,7 +634,8 @@ name, a (possibly empty) argument list (each with optional :ref:`parameter attributes `), optional :ref:`function attributes `, an optional section, an optional alignment, an optional :ref:`comdat `, -an optional :ref:`garbage collector name `, an optional :ref:`prefix `, an opening +an optional :ref:`garbage collector name `, an optional :ref:`prefix `, +an optional :ref:`prologue `, an opening curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations consist of the "``declare``" keyword, an @@ -641,7 +645,8 @@ an optional :ref:`calling convention `, an optional ``unnamed_addr`` attribute, a return type, an optional :ref:`parameter attribute ` for the return type, a function name, a possibly empty list of arguments, an optional alignment, an optional -:ref:`garbage collector name ` and an optional :ref:`prefix `. +:ref:`garbage collector name `, an optional :ref:`prefix `, +and an optional :ref:`prologue `. A function definition contains a list of basic blocks, forming the CFG (Control Flow Graph) for the function. Each basic block may optionally start with a label @@ -677,8 +682,16 @@ Syntax:: define [linkage] [visibility] [DLLStorageClass] [cconv] [ret attrs] @ ([argument list]) - [unnamed_addr] [fn Attrs] [section "name"] [comdat $] - [align N] [gc] [prefix Constant] { ... } + [unnamed_addr] [fn Attrs] [section "name"] [comdat [($name)]] + [align N] [gc] [prefix Constant] [prologue Constant] { ... } + +The argument list is a comma seperated sequence of arguments where each +argument is of the following form + +Syntax:: + + [parameter Attrs] [name] + .. _langref_aliases: @@ -697,7 +710,7 @@ Aliases may have an optional :ref:`linkage type `, an optional Syntax:: - @ = [Visibility] [DLLStorageClass] [ThreadLocal] [unnamed_addr] alias [Linkage] @ + @ = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [unnamed_addr] alias @ The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``, ``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers @@ -727,7 +740,7 @@ Comdats Comdat IR provides access to COFF and ELF object file COMDAT functionality. -Comdats have a name which represents the COMDAT key. All global objects which +Comdats have a name which represents the COMDAT key. All global objects that specify this key will only end up in the final object file if the linker chooses that key over some other key. Aliases are placed in the same COMDAT that their aliasee computes to, if any. @@ -763,17 +776,26 @@ the COMDAT key's section is the largest: .. code-block:: llvm $foo = comdat largest - @foo = global i32 2, comdat $foo + @foo = global i32 2, comdat($foo) - define void @bar() comdat $foo { + define void @bar() comdat($foo) { ret void } +As a syntactic sugar the ``$name`` can be omitted if the name is the same as +the global name: + +.. code-block:: llvm + + $foo = comdat any + @foo = global i32 2, comdat + + In a COFF object file, this will create a COMDAT section with selection kind ``IMAGE_COMDAT_SELECT_LARGEST`` containing the contents of the ``@foo`` symbol and another COMDAT section with selection kind ``IMAGE_COMDAT_SELECT_ASSOCIATIVE`` which is associated with the first COMDAT -section and contains the contents of the ``@baz`` symbol. +section and contains the contents of the ``@bar`` symbol. There are some restrictions on the properties of the global object. It, or an alias to it, must have the same name as the COMDAT group when @@ -791,8 +813,8 @@ For example: $foo = comdat any $bar = comdat any - @g1 = global i32 42, section "sec", comdat $foo - @g2 = global i32 42, section "sec", comdat $bar + @g1 = global i32 42, section "sec", comdat($foo) + @g2 = global i32 42, section "sec", comdat($bar) From the object file perspective, this requires the creation of two sections with the same name. This is necessary because both globals belong to different @@ -815,9 +837,9 @@ operands for a named metadata. Syntax:: ; Some unnamed metadata nodes, which are referenced by the named metadata. - !0 = metadata !{metadata !"zero"} - !1 = metadata !{metadata !"one"} - !2 = metadata !{metadata !"two"} + !0 = !{!"zero"} + !1 = !{!"one"} + !2 = !{!"two"} ; A named metadata. !name = !{!0, !1, !2} @@ -921,26 +943,36 @@ Currently, only the following parameter attributes are defined: the first parameter. This is not a valid attribute for return values. +``align `` + This indicates that the pointer value may be assumed by the optimizer to + have the specified alignment. + + Note that this attribute has additional semantics when combined with the + ``byval`` attribute. + .. _noalias: ``noalias`` - This indicates that pointer values :ref:`based ` on - the argument or return value do not alias pointer values which are - not *based* on it, ignoring certain "irrelevant" dependencies. For a - call to the parent function, dependencies between memory references - from before or after the call and from those during the call are - "irrelevant" to the ``noalias`` keyword for the arguments and return - value used in that call. The caller shares the responsibility with - the callee for ensuring that these requirements are met. For further - details, please see the discussion of the NoAlias response in :ref:`alias - analysis `. + This indicates that objects accessed via pointer values + :ref:`based ` on the argument or return value are not also + accessed, during the execution of the function, via pointer values not + *based* on the argument or return value. The attribute on a return value + also has additional semantics described below. The caller shares the + responsibility with the callee for ensuring that these requirements are met. + For further details, please see the discussion of the NoAlias response in + :ref:`alias analysis `. Note that this definition of ``noalias`` is intentionally similar - to the definition of ``restrict`` in C99 for function arguments, - though it is slightly weaker. + to the definition of ``restrict`` in C99 for function arguments. For function return values, C99's ``restrict`` is not meaningful, - while LLVM's ``noalias`` is. + while LLVM's ``noalias`` is. Furthermore, the semantics of the ``noalias`` + attribute on return values are stronger than the semantics of the attribute + when used on function arguments. On function return values, the ``noalias`` + attribute indicates that the function acts like a system memory allocation + function, returning a pointer to allocated storage disjoint from the + storage for any other object accessible to the caller. + ``nocapture`` This indicates that the callee does not make any copies of the pointer that outlive the callee itself. This is not a valid @@ -993,7 +1025,7 @@ string: define void @f() gc "name" { ... } The compiler declares the supported values of *name*. Specifying a -collector which will cause the compiler to alter its output in order to +collector will cause the compiler to alter its output in order to support the named garbage collection algorithm. .. _prefixdata: @@ -1001,47 +1033,79 @@ support the named garbage collection algorithm. Prefix Data ----------- -Prefix data is data associated with a function which the code generator -will emit immediately before the function body. The purpose of this feature -is to allow frontends to associate language-specific runtime metadata with -specific functions and make it available through the function pointer while -still allowing the function pointer to be called. To access the data for a -given function, a program may bitcast the function pointer to a pointer to -the constant's type. This implies that the IR symbol points to the start -of the prefix data. +Prefix data is data associated with a function which the code +generator will emit immediately before the function's entrypoint. +The purpose of this feature is to allow frontends to associate +language-specific runtime metadata with specific functions and make it +available through the function pointer while still allowing the +function pointer to be called. + +To access the data for a given function, a program may bitcast the +function pointer to a pointer to the constant's type and dereference +index -1. This implies that the IR symbol points just past the end of +the prefix data. For instance, take the example of a function annotated +with a single ``i32``, + +.. code-block:: llvm + + define void @f() prefix i32 123 { ... } + +The prefix data can be referenced as, -To maintain the semantics of ordinary function calls, the prefix data must +.. code-block:: llvm + + %0 = bitcast *void () @f to *i32 + %a = getelementptr inbounds *i32 %0, i32 -1 + %b = load i32* %a + +Prefix data is laid out as if it were an initializer for a global variable +of the prefix data's type. The function will be placed such that the +beginning of the prefix data is aligned. This means that if the size +of the prefix data is not a multiple of the alignment size, the +function's entrypoint will not be aligned. If alignment of the +function's entrypoint is desired, padding must be added to the prefix +data. + +A function may have prefix data but no body. This has similar semantics +to the ``available_externally`` linkage in that the data may be used by the +optimizers but will not be emitted in the object file. + +.. _prologuedata: + +Prologue Data +------------- + +The ``prologue`` attribute allows arbitrary code (encoded as bytes) to +be inserted prior to the function body. This can be used for enabling +function hot-patching and instrumentation. + +To maintain the semantics of ordinary function calls, the prologue data must have a particular format. Specifically, it must begin with a sequence of bytes which decode to a sequence of machine instructions, valid for the module's target, which transfer control to the point immediately succeeding -the prefix data, without performing any other visible action. This allows +the prologue data, without performing any other visible action. This allows the inliner and other passes to reason about the semantics of the function -definition without needing to reason about the prefix data. Obviously this -makes the format of the prefix data highly target dependent. +definition without needing to reason about the prologue data. Obviously this +makes the format of the prologue data highly target dependent. -Prefix data is laid out as if it were an initializer for a global variable -of the prefix data's type. No padding is automatically placed between the -prefix data and the function body. If padding is required, it must be part -of the prefix data. - -A trivial example of valid prefix data for the x86 architecture is ``i8 144``, +A trivial example of valid prologue data for the x86 architecture is ``i8 144``, which encodes the ``nop`` instruction: .. code-block:: llvm - define void @f() prefix i8 144 { ... } + define void @f() prologue i8 144 { ... } -Generally prefix data can be formed by encoding a relative branch instruction -which skips the metadata, as in this example of valid prefix data for the +Generally prologue data can be formed by encoding a relative branch instruction +which skips the metadata, as in this example of valid prologue data for the x86_64 architecture, where the first two bytes encode ``jmp .+10``: .. code-block:: llvm %0 = type <{ i8, i8, i8* }> - define void @f() prefix %0 <{ i8 235, i8 8, i8* @md}> { ... } + define void @f() prologue %0 <{ i8 235, i8 8, i8* @md}> { ... } -A function may have prefix data but no body. This has similar semantics +A function may have prologue data but no body. This has similar semantics to the ``available_externally`` linkage in that the data may be used by the optimizers but will not be emitted in the object file. @@ -1109,7 +1173,7 @@ example: This indicates that the callee function at a call site should be recognized as a built-in function, even though the function's declaration uses the ``nobuiltin`` attribute. This is only valid at call sites for - direct calls to functions which are declared with the ``nobuiltin`` + direct calls to functions that are declared with the ``nobuiltin`` attribute. ``cold`` This attribute indicates that this function is rarely called. When @@ -1604,7 +1668,7 @@ Given that definition, R\ :sub:`byte` is defined as follows: - If R is volatile, the result is target-dependent. (Volatile is supposed to give guarantees which can support ``sig_atomic_t`` in - C/C++, and may be used for accesses to addresses which do not behave + C/C++, and may be used for accesses to addresses that do not behave like normal memory. It does not generally provide cross-thread synchronization.) - Otherwise, if there is no write to the same byte that happens before @@ -1692,7 +1756,7 @@ For a simpler introduction to the ordering constraints, see the address. This corresponds to the C++0x/C1x ``memory_order_acq_rel``. ``seq_cst`` (sequentially consistent) In addition to the guarantees of ``acq_rel`` (``acquire`` for an - operation which only reads, ``release`` for an operation which only + operation that only reads, ``release`` for an operation that only writes), there is a global total order on all sequentially-consistent operations on all addresses, which is consistent with the *happens-before* partial order and with the @@ -1741,6 +1805,52 @@ otherwise unsafe floating point operations dramatically change results in floating point (e.g. reassociate). This flag implies all the others. +.. _uselistorder: + +Use-list Order Directives +------------------------- + +Use-list directives encode the in-memory order of each use-list, allowing the +order to be recreated. ```` is a comma-separated list of +indexes that are assigned to the referenced value's uses. The referenced +value's use-list is immediately sorted by these indexes. + +Use-list directives may appear at function scope or global scope. They are not +instructions, and have no effect on the semantics of the IR. When they're at +function scope, they must appear after the terminator of the final basic block. + +If basic blocks have their address taken via ``blockaddress()`` expressions, +``uselistorder_bb`` can be used to reorder their use-lists from outside their +function's scope. + +:Syntax: + +:: + + uselistorder , { } + uselistorder_bb @function, %block { } + +:Examples: + +:: + + define void @foo(i32 %arg1, i32 %arg2) { + entry: + ; ... instructions ... + bb: + ; ... instructions ... + + ; At function scope. + uselistorder i32 %arg1, { 1, 0, 2 } + uselistorder label %bb, { 1, 0 } + } + + ; At global scope. + uselistorder i32* @global, { 1, 2, 0 } + uselistorder i32 7, { 1, 0 } + uselistorder i32 (i32) @bar, { 1, 0 } + uselistorder_bb @foo, %bb, { 5, 1, 3, 2, 0, 4 } + .. _typesystem: Type System @@ -1959,8 +2069,8 @@ type. Vector types are considered :ref:`first class `. < <# elements> x > The number of elements is a constant integer value larger than 0; -elementtype may be any integer or floating point type, or a pointer to -these types. Vectors of size zero are not allowed. +elementtype may be any integer, floating point or pointer type. Vectors +of size zero are not allowed. :Examples: @@ -2213,7 +2323,9 @@ constants and smaller complex constants. square brackets (``[]``)). For example: "``[ i32 42, i32 11, i32 74 ]``". Array constants must have :ref:`array type `, and the number and types of elements must - match those specified by the type. + match those specified by the type. As a special case, character array + constants may also be represented as a double-quoted string using the ``c`` + prefix. For example: "``c"Hello World\0A\00"``". **Vector constants** Vector constants are represented with notation similar to vector type definitions (a comma separated list of elements, surrounded by @@ -2228,11 +2340,11 @@ constants and smaller complex constants. having to print large zero initializers (e.g. for large arrays) and is always exactly equivalent to using explicit zero initializers. **Metadata node** - A metadata node is a structure-like constant with :ref:`metadata - type `. For example: - "``metadata !{ i32 0, metadata !"test" }``". Unlike other - constants that are meant to be interpreted as part of the - instruction stream, metadata is a place to attach additional + A metadata node is a constant tuple without types. For example: + "``!{!0, !{!2, !0}, !"test"}``". Metadata can reference constant values, + for example: "``!{!0, i32 0, i8* @global, i64 (i64)* @function, !"str"}``". + Unlike other typed constants that are meant to be interpreted as part of + the instruction stream, metadata is a place to attach additional information such as debug info. Global Variable and Function Addresses @@ -2330,7 +2442,7 @@ allowed to assume that the '``undef``' operand could be the same as %C = xor %B, %B %D = undef - %E = icmp lt %D, 4 + %E = icmp slt %D, 4 %F = icmp gte %D, 4 Safe: @@ -2395,8 +2507,8 @@ Poison Values Poison values are similar to :ref:`undef values `, however they also represent the fact that an instruction or constant expression -which cannot evoke side effects has nevertheless detected a condition -which results in undefined behavior. +that cannot evoke side effects has nevertheless detected a condition +that results in undefined behavior. There is currently no way of representing a poison value in the IR; they only exist when produced by operations such as :ref:`add ` with @@ -2433,8 +2545,8 @@ Poison value behavior is defined in terms of value *dependence*: successor. - Dependence is transitive. -Poison Values have the same behavior as :ref:`undef values `, -with the additional affect that any instruction which has a *dependence* +Poison values have the same behavior as :ref:`undef values `, +with the additional effect that any instruction that has a *dependence* on a poison value has undefined behavior. Here are some examples: @@ -2706,15 +2818,21 @@ occurs on. .. _metadata: -Metadata Nodes and Metadata Strings ------------------------------------ +Metadata +======== LLVM IR allows metadata to be attached to instructions in the program that can convey extra information about the code to the optimizers and code generator. One example application of metadata is source-level debug information. There are two metadata primitives: strings and nodes. -All metadata has the ``metadata`` type and is identified in syntax by a -preceding exclamation point ('``!``'). + +Metadata does not have a type, and is not a value. If referenced from a +``call`` instruction, it uses the ``metadata`` type. + +All metadata are identified in syntax by a exclamation point ('``!``'). + +Metadata Nodes and Metadata Strings +----------------------------------- A metadata string is a string surrounded by double quotes. It can contain any character by escaping non-printable characters with @@ -2728,7 +2846,17 @@ their operand. For example: .. code-block:: llvm - !{ metadata !"test\00", i32 10} + !{ !"test\00", i32 10} + +Metadata nodes that aren't uniqued use the ``distinct`` keyword. For example: + +.. code-block:: llvm + + !0 = distinct !{!"test\00", i32 10} + +``distinct`` nodes are useful when nodes shouldn't be merged based on their +content. They can also occur when transformations cause uniquing collisions +when metadata operands change. A :ref:`named metadata ` is a collection of metadata nodes, which can be looked up in the module symbol table. For @@ -2736,7 +2864,7 @@ example: .. code-block:: llvm - !foo = metadata !{!4, !3} + !foo = !{!4, !3} Metadata can be used as function arguments. Here ``llvm.dbg.value`` function is using two metadata arguments: @@ -2755,6 +2883,23 @@ attached to the ``add`` instruction using the ``!dbg`` identifier: More information about specific metadata nodes recognized by the optimizers and code generator is found below. +Specialized Metadata Nodes +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Specialized metadata nodes are custom data structures in metadata (as opposed +to generic tuples). Their fields are labelled, and can be specified in any +order. + +MDLocation +"""""""""" + +``MDLocation`` nodes represent source debug locations. The ``scope:`` field is +mandatory. + +.. code-block:: llvm + + !0 = !MDLocation(line: 2900, column: 42, scope: !1, inlinedAt: !2) + '``tbaa``' Metadata ^^^^^^^^^^^^^^^^^^^ @@ -2769,10 +2914,10 @@ to three fields, e.g.: .. code-block:: llvm - !0 = metadata !{ metadata !"an example type tree" } - !1 = metadata !{ metadata !"int", metadata !0 } - !2 = metadata !{ metadata !"float", metadata !0 } - !3 = metadata !{ metadata !"const float", metadata !2, i64 1 } + !0 = !{ !"an example type tree" } + !1 = !{ !"int", !0 } + !2 = !{ !"float", !0 } + !3 = !{ !"const float", !2, i64 1 } The first field is an identity field. It can be any value, usually a metadata string, which uniquely identifies the type. The most important @@ -2812,7 +2957,7 @@ its tbaa tag. e.g.: .. code-block:: llvm - !4 = metadata !{ i64 0, i64 4, metadata !1, i64 8, i64 4, metadata !2 } + !4 = !{ i64 0, i64 4, !1, i64 8, i64 4, !2 } This describes a struct with two fields. The first is at offset 0 bytes with size 4 bytes, and has tbaa tag !1. The second is at offset 8 bytes @@ -2822,6 +2967,67 @@ Note that the fields need not be contiguous. In this example, there is a 4 byte gap between the two fields. This gap represents padding which does not carry useful data and need not be preserved. +'``noalias``' and '``alias.scope``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``noalias`` and ``alias.scope`` metadata provide the ability to specify generic +noalias memory-access sets. This means that some collection of memory access +instructions (loads, stores, memory-accessing calls, etc.) that carry +``noalias`` metadata can specifically be specified not to alias with some other +collection of memory access instructions that carry ``alias.scope`` metadata. +Each type of metadata specifies a list of scopes where each scope has an id and +a domain. When evaluating an aliasing query, if for some some domain, the set +of scopes with that domain in one instruction's ``alias.scope`` list is a +subset of (or qual to) the set of scopes for that domain in another +instruction's ``noalias`` list, then the two memory accesses are assumed not to +alias. + +The metadata identifying each domain is itself a list containing one or two +entries. The first entry is the name of the domain. Note that if the name is a +string then it can be combined accross functions and translation units. A +self-reference can be used to create globally unique domain names. A +descriptive string may optionally be provided as a second list entry. + +The metadata identifying each scope is also itself a list containing two or +three entries. The first entry is the name of the scope. Note that if the name +is a string then it can be combined accross functions and translation units. A +self-reference can be used to create globally unique scope names. A metadata +reference to the scope's domain is the second entry. A descriptive string may +optionally be provided as a third list entry. + +For example, + +.. code-block:: llvm + + ; Two scope domains: + !0 = !{!0} + !1 = !{!1} + + ; Some scopes in these domains: + !2 = !{!2, !0} + !3 = !{!3, !0} + !4 = !{!4, !1} + + ; Some scope lists: + !5 = !{!4} ; A list containing only scope !4 + !6 = !{!4, !3, !2} + !7 = !{!3} + + ; These two instructions don't alias: + %0 = load float* %c, align 4, !alias.scope !5 + store float %0, float* %arrayidx.i, align 4, !noalias !5 + + ; These two instructions also don't alias (for domain !1, the set of scopes + ; in the !alias.scope equals that in the !noalias list): + %2 = load float* %c, align 4, !alias.scope !5 + store float %2, float* %arrayidx.i2, align 4, !noalias !6 + + ; These two instructions don't alias (for domain !0, the set of scopes in + ; the !noalias list is not a superset of, or equal to, the scopes in the + ; !alias.scope list): + %2 = load float* %c, align 4, !alias.scope !6 + store float %0, float* %arrayidx.i, align 4, !noalias !7 + '``fpmath``' Metadata ^^^^^^^^^^^^^^^^^^^^^ @@ -2842,7 +3048,7 @@ number representing the maximum relative error, for example: .. code-block:: llvm - !0 = metadata !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs + !0 = !{ float 2.5 } ; maximum acceptable inaccuracy is 2.5 ULPs '``range``' Metadata ^^^^^^^^^^^^^^^^^^^^ @@ -2874,10 +3080,10 @@ Examples: %d = invoke i8 @bar() to label %cont unwind label %lpad, !range !3 ; Can only be -2, -1, 3, 4 or 5 ... - !0 = metadata !{ i8 0, i8 2 } - !1 = metadata !{ i8 255, i8 2 } - !2 = metadata !{ i8 0, i8 2, i8 3, i8 6 } - !3 = metadata !{ i8 -2, i8 0, i8 3, i8 6 } + !0 = !{ i8 0, i8 2 } + !1 = !{ i8 255, i8 2 } + !2 = !{ i8 0, i8 2, i8 3, i8 6 } + !3 = !{ i8 -2, i8 0, i8 3, i8 6 } '``llvm.loop``' ^^^^^^^^^^^^^^^ @@ -2897,20 +3103,20 @@ constructs: .. code-block:: llvm - !0 = metadata !{ metadata !0 } - !1 = metadata !{ metadata !1 } + !0 = !{!0} + !1 = !{!1} The loop identifier metadata can be used to specify additional per-loop metadata. Any operands after the first operand can be treated -as user-defined metadata. For example the ``llvm.loop.interleave.count`` -suggests an interleave factor to the loop interleaver: +as user-defined metadata. For example the ``llvm.loop.unroll.count`` +suggests an unroll factor to the loop unroller: .. code-block:: llvm br i1 %exitcond, label %._crit_edge, label %.lr.ph, !llvm.loop !0 ... - !0 = metadata !{ metadata !0, metadata !1 } - !1 = metadata !{ metadata !"llvm.loop.interleave.count", i32 4 } + !0 = !{!0, !1} + !1 = !{!"llvm.loop.unroll.count", i32 4} '``llvm.loop.vectorize``' and '``llvm.loop.interleave``' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -2935,7 +3141,7 @@ example: .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.interleave.count", i32 4 } + !0 = !{!"llvm.loop.interleave.count", i32 4} Note that setting ``llvm.loop.interleave.count`` to 1 disables interleaving multiple iterations of the loop. If ``llvm.loop.interleave.count`` is set to 0 @@ -2951,8 +3157,8 @@ is a bit. If the bit operand value is 1 vectorization is enabled. A value of .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.vectorize.enable", i1 0 } - !1 = metadata !{ metadata !"llvm.loop.vectorize.enable", i1 1 } + !0 = !{!"llvm.loop.vectorize.enable", i1 0} + !1 = !{!"llvm.loop.vectorize.enable", i1 1} '``llvm.loop.vectorize.width``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -2963,13 +3169,59 @@ operand is an integer specifying the width. For example: .. code-block:: llvm - !0 = metadata !{ metadata !"llvm.loop.vectorize.width", i32 4 } + !0 = !{!"llvm.loop.vectorize.width", i32 4} Note that setting ``llvm.loop.vectorize.width`` to 1 disables vectorization of the loop. If ``llvm.loop.vectorize.width`` is set to 0 or if the loop does not have this metadata the width will be determined automatically. +'``llvm.loop.unroll``' +^^^^^^^^^^^^^^^^^^^^^^ + +Metadata prefixed with ``llvm.loop.unroll`` are loop unrolling +optimization hints such as the unroll factor. ``llvm.loop.unroll`` +metadata should be used in conjunction with ``llvm.loop`` loop +identification metadata. The ``llvm.loop.unroll`` metadata are only +optimization hints and the unrolling will only be performed if the +optimizer believes it is safe to do so. + +'``llvm.loop.unroll.count``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This metadata suggests an unroll factor to the loop unroller. The +first operand is the string ``llvm.loop.unroll.count`` and the second +operand is a positive integer specifying the unroll factor. For +example: + +.. code-block:: llvm + + !0 = !{!"llvm.loop.unroll.count", i32 4} + +If the trip count of the loop is less than the unroll count the loop +will be partially unrolled. + +'``llvm.loop.unroll.disable``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This metadata either disables loop unrolling. The metadata has a single operand +which is the string ``llvm.loop.unroll.disable``. For example: + +.. code-block:: llvm + + !0 = !{!"llvm.loop.unroll.disable"} + +'``llvm.loop.unroll.full``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This metadata either suggests that the loop should be unrolled fully. The +metadata has a single operand which is the string ``llvm.loop.unroll.disable``. +For example: + +.. code-block:: llvm + + !0 = !{!"llvm.loop.unroll.full"} + '``llvm.mem``' ^^^^^^^^^^^^^^^ @@ -3019,7 +3271,7 @@ metadata types that refer to the same loop identifier metadata. for.end: ... - !0 = metadata !{ metadata !0 } + !0 = !{!0} It is also possible to have nested parallel loops. In that case the memory accesses refer to a list of loop identifier metadata nodes instead of @@ -3049,9 +3301,9 @@ the loop identifier metadata node directly: outer.for.end: ; preds = %for.body ... - !0 = metadata !{ metadata !1, metadata !2 } ; a list of loop identifiers - !1 = metadata !{ metadata !1 } ; an identifier for the inner loop - !2 = metadata !{ metadata !2 } ; an identifier for the outer loop + !0 = !{!1, !2} ; a list of loop identifiers + !1 = !{!1} ; an identifier for the inner loop + !2 = !{!2} ; an identifier for the outer loop Module Flags Metadata ===================== @@ -3135,12 +3387,12 @@ An example of module flags: .. code-block:: llvm - !0 = metadata !{ i32 1, metadata !"foo", i32 1 } - !1 = metadata !{ i32 4, metadata !"bar", i32 37 } - !2 = metadata !{ i32 2, metadata !"qux", i32 42 } - !3 = metadata !{ i32 3, metadata !"qux", - metadata !{ - metadata !"foo", i32 1 + !0 = !{ i32 1, !"foo", i32 1 } + !1 = !{ i32 4, !"bar", i32 37 } + !2 = !{ i32 2, !"qux", i32 42 } + !3 = !{ i32 3, !"qux", + !{ + !"foo", i32 1 } } !llvm.module.flags = !{ !0, !1, !2, !3 } @@ -3161,7 +3413,7 @@ An example of module flags: :: - metadata !{ metadata !"foo", i32 1 } + !{ !"foo", i32 1 } The behavior is to emit an error if the ``llvm.module.flags`` does not contain a flag with the ID ``!"foo"`` that has the value '1' after linking is @@ -3237,10 +3489,10 @@ For example, the following metadata section specifies two separate sets of linker options, presumably to link against ``libz`` and the ``Cocoa`` framework:: - !0 = metadata !{ i32 6, metadata !"Linker Options", - metadata !{ - metadata !{ metadata !"-lz" }, - metadata !{ metadata !"-framework", metadata !"Cocoa" } } } + !0 = !{ i32 6, !"Linker Options", + !{ + !{ !"-lz" }, + !{ !"-framework", !"Cocoa" } } } !llvm.module.flags = !{ !0 } The metadata encoding as lists of lists of options, as opposed to a collapsed @@ -3286,8 +3538,8 @@ compiled with a ``wchar_t`` width of 4 bytes, and the underlying type of an enum is the smallest type which can represent all of its values:: !llvm.module.flags = !{!0, !1} - !0 = metadata !{i32 1, metadata !"short_wchar", i32 1} - !1 = metadata !{i32 1, metadata !"short_enum", i32 0} + !0 = !{i32 1, !"short_wchar", i32 1} + !1 = !{i32 1, !"short_enum", i32 0} .. _intrinsicglobalvariables: @@ -4905,7 +5157,7 @@ Example: %agg1 = insertvalue {i32, float} undef, i32 1, 0 ; yields {i32 1, float undef} %agg2 = insertvalue {i32, float} %agg1, float %val, 1 ; yields {i32 1, float %val} - %agg3 = insertvalue {i32, {float}} %agg1, float %val, 1, 0 ; yields {i32 1, float %val} + %agg3 = insertvalue {i32, {float}} undef, float %val, 1, 0 ; yields {i32 undef, {float %val}} .. _memoryops: @@ -4985,7 +5237,7 @@ Syntax: :: - = load [volatile] * [, align ][, !nontemporal !][, !invariant.load !] + = load [volatile] * [, align ][, !nontemporal !][, !invariant.load !][, !nonnull !] = load atomic [volatile] * [singlethread] , align ! = !{ i32 1 } @@ -5036,10 +5288,19 @@ as the ``MOVNT`` instruction on x86. The optional ``!invariant.load`` metadata must reference a single metadata name ```` corresponding to a metadata node with no entries. The existence of the ``!invariant.load`` metadata on the -instruction tells the optimizer and code generator that this load -address points to memory which does not change value during program -execution. The optimizer may then move this load around, for example, by -hoisting it out of loops using loop invariant code motion. +instruction tells the optimizer and code generator that the address +operand to this load points to memory which can be assumed unchanged. +Being invariant does not imply that a location is dereferenceable, +but it does imply that once the location is known dereferenceable +its value is henceforth unchanging. + +The optional ``!nonnull`` metadata must reference a single +metadata name ```` corresponding to a metadata node with no +entries. The existence of the ``!nonnull`` metadata on the +instruction tells the optimizer that the value loaded is known to +never be null. This is analogous to the ''nonnull'' attribute +on parameters and return values. This metadata can only be applied +to loads of a pointer type. Semantics: """""""""" @@ -6421,6 +6682,9 @@ This instruction requires several arguments: - The calling conventions of the caller and callee must match. - All ABI-impacting function attributes, such as sret, byval, inreg, returned, and inalloca, must match. + - The callee must be varargs iff the caller is varargs. Bitcasting a + non-varargs function to the appropriate varargs type is legal so + long as the non-varargs prefixes obey the other rules. Tail call optimization for calls marked ``tail`` is guaranteed to occur if the following conditions are met: @@ -6701,14 +6965,21 @@ variable argument handling intrinsic functions are used. .. code-block:: llvm + ; This struct is different for every platform. For most platforms, + ; it is merely an i8*. + %struct.va_list = type { i8* } + + ; For Unix x86_64 platforms, va_list is the following struct: + ; %struct.va_list = type { i32, i32, i8*, i8* } + define i32 @test(i32 %X, ...) { ; Initialize variable argument processing - %ap = alloca i8* - %ap2 = bitcast i8** %ap to i8* + %ap = alloca %struct.va_list + %ap2 = bitcast %struct.va_list* %ap to i8* call void @llvm.va_start(i8* %ap2) ; Read a single integer argument - %tmp = va_arg i8** %ap, i32 + %tmp = va_arg i8* %ap2, i32 ; Demonstrate usage of llvm.va_copy and llvm.va_end %aq = alloca i8* @@ -7027,6 +7298,56 @@ Note that calling this intrinsic does not prevent function inlining or other aggressive transformations, so the value returned may not be that of the obvious source-language caller. +'``llvm.frameallocate``' and '``llvm.framerecover``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i8* @llvm.frameallocate(i32 %size) + declare i8* @llvm.framerecover(i8* %func, i8* %fp) + +Overview: +""""""""" + +The '``llvm.frameallocate``' intrinsic allocates stack memory at some fixed +offset from the frame pointer, and the '``llvm.framerecover``' +intrinsic applies that offset to a live frame pointer to recover the address of +the allocation. The offset is computed during frame layout of the caller of +``llvm.frameallocate``. + +Arguments: +"""""""""" + +The ``size`` argument to '``llvm.frameallocate``' must be a constant integer +indicating the amount of stack memory to allocate. As with allocas, allocating +zero bytes is legal, but the result is undefined. + +The ``func`` argument to '``llvm.framerecover``' must be a constant +bitcasted pointer to a function defined in the current module. The code +generator cannot determine the frame allocation offset of functions defined in +other modules. + +The ``fp`` argument to '``llvm.framerecover``' must be a frame +pointer of a call frame that is currently live. The return value of +'``llvm.frameaddress``' is one way to produce such a value, but most platforms +also expose the frame pointer through stack unwinding mechanisms. + +Semantics: +"""""""""" + +These intrinsics allow a group of functions to access one stack memory +allocation in an ancestor stack frame. The memory returned from +'``llvm.frameallocate``' may be allocated prior to stack realignment, so the +memory is only aligned to the ABI-required stack alignment. Each function may +only call '``llvm.frameallocate``' one or zero times from the function entry +block. The frame allocation intrinsic inhibits inlining, as any frame +allocations in the inlined function frame are likely to be at a different +offset from the one used by '``llvm.framerecover``' called with the +uninlined function. + .. _int_read_register: .. _int_write_register: @@ -7042,7 +7363,7 @@ Syntax: declare i64 @llvm.read_register.i64(metadata) declare void @llvm.write_register.i32(metadata, i32 @value) declare void @llvm.write_register.i64(metadata, i64 @value) - !0 = metadata !{metadata !"sp\00"} + !0 = !{!"sp\00"} Overview: """"""""" @@ -7264,6 +7585,50 @@ time library. This instrinsic does *not* empty the instruction pipeline. Modifications of the current function are outside the scope of the intrinsic. +'``llvm.instrprof_increment``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.instrprof_increment(i8* , i64 , + i32 , i32 ) + +Overview: +""""""""" + +The '``llvm.instrprof_increment``' intrinsic can be emitted by a +frontend for use with instrumentation based profiling. These will be +lowered by the ``-instrprof`` pass to generate execution counts of a +program at runtime. + +Arguments: +"""""""""" + +The first argument is a pointer to a global variable containing the +name of the entity being instrumented. This should generally be the +(mangled) function name for a set of counters. + +The second argument is a hash value that can be used by the consumer +of the profile data to detect changes to the instrumented source, and +the third is the number of counters associated with ``name``. It is an +error if ``hash`` or ``num-counters`` differ between two instances of +``instrprof_increment`` that refer to the same name. + +The last argument refers to which of the counters for ``name`` should +be incremented. It should be a value between 0 and ``num-counters``. + +Semantics: +"""""""""" + +This intrinsic represents an increment of a profiling counter. It will +cause the ``-instrprof`` pass to generate the appropriate data +structures and the code to increment the appropriate value, in a +format that can be written out by a compiler runtime and consumed via +the ``llvm-profdata`` tool. + Standard C Library Intrinsics ----------------------------- @@ -7845,9 +8210,9 @@ all types however. declare float @llvm.fabs.f32(float %Val) declare double @llvm.fabs.f64(double %Val) - declare x86_fp80 @llvm.fabs.f80(x86_fp80 %Val) + declare x86_fp80 @llvm.fabs.f80(x86_fp80 %Val) declare fp128 @llvm.fabs.f128(fp128 %Val) - declare ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 %Val) + declare ppc_fp128 @llvm.fabs.ppcf128(ppc_fp128 %Val) Overview: """"""""" @@ -7867,6 +8232,89 @@ Semantics: This function returns the same values as the libm ``fabs`` functions would, and handles error conditions in the same way. +'``llvm.minnum.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.minnum`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.minnum.f32(float %Val0, float %Val1) + declare double @llvm.minnum.f64(double %Val0, double %Val1) + declare x86_fp80 @llvm.minnum.f80(x86_fp80 %Val0, x86_fp80 %Val1) + declare fp128 @llvm.minnum.f128(fp128 %Val0, fp128 %Val1) + declare ppc_fp128 @llvm.minnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1) + +Overview: +""""""""" + +The '``llvm.minnum.*``' intrinsics return the minimum of the two +arguments. + + +Arguments: +"""""""""" + +The arguments and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" + +Follows the IEEE-754 semantics for minNum, which also match for libm's +fmin. + +If either operand is a NaN, returns the other non-NaN operand. Returns +NaN only if both operands are NaN. If the operands compare equal, +returns a value that compares equal to both operands. This means that +fmin(+/-0.0, +/-0.0) could return either -0.0 or 0.0. + +'``llvm.maxnum.*``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +This is an overloaded intrinsic. You can use ``llvm.maxnum`` on any +floating point or vector of floating point type. Not all targets support +all types however. + +:: + + declare float @llvm.maxnum.f32(float %Val0, float %Val1l) + declare double @llvm.maxnum.f64(double %Val0, double %Val1) + declare x86_fp80 @llvm.maxnum.f80(x86_fp80 %Val0, x86_fp80 %Val1) + declare fp128 @llvm.maxnum.f128(fp128 %Val0, fp128 %Val1) + declare ppc_fp128 @llvm.maxnum.ppcf128(ppc_fp128 %Val0, ppc_fp128 %Val1) + +Overview: +""""""""" + +The '``llvm.maxnum.*``' intrinsics return the maximum of the two +arguments. + + +Arguments: +"""""""""" + +The arguments and return value are floating point numbers of the same +type. + +Semantics: +"""""""""" +Follows the IEEE-754 semantics for maxNum, which also match for libm's +fmax. + +If either operand is a NaN, returns the other non-NaN operand. Returns +NaN only if both operands are NaN. If the operands compare equal, +returns a value that compares equal to both operands. This means that +fmax(+/-0.0, +/-0.0) could return either -0.0 or 0.0. + '``llvm.copysign.*``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8226,7 +8674,7 @@ Arguments: """""""""" The first argument is the value to be counted. This argument may be of -any integer type, or a vectory with integer element type. The return +any integer type, or a vector with integer element type. The return type must match the first argument type. The second argument must be a constant and is a flag to indicate whether @@ -8273,7 +8721,7 @@ Arguments: """""""""" The first argument is the value to be counted. This argument may be of -any integer type, or a vectory with integer element type. The return +any integer type, or a vector with integer element type. The return type must match the first argument type. The second argument must be a constant and is a flag to indicate whether @@ -8869,6 +9317,93 @@ intrinsic returns the executable address corresponding to ``tramp`` after performing the required machine specific adjustments. The pointer returned can then be :ref:`bitcast and executed `. +Masked Vector Load and Store Intrinsics +--------------------------------------- + +LLVM provides intrinsics for predicated vector load and store operations. The predicate is specified by a mask operand, which holds one bit per vector element, switching the associated vector lane on or off. The memory addresses corresponding to the "off" lanes are not accessed. When all bits of the mask are on, the intrinsic is identical to a regular vector load or store. When all bits are off, no memory is accessed. + +.. _int_mload: + +'``llvm.masked.load.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. The loaded data is a vector of any integer or floating point data type. + +:: + + declare <16 x float> @llvm.masked.load.v16f32 (<16 x float>* , i32 , <16 x i1> , <16 x float> ) + declare <2 x double> @llvm.masked.load.v2f64 (<2 x double>* , i32 , <2 x i1> , <2 x double> ) + +Overview: +""""""""" + +Reads a vector from memory according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. The masked-off lanes in the result vector are taken from the corresponding lanes in the passthru operand. + + +Arguments: +"""""""""" + +The first operand is the base pointer for the load. The second operand is the alignment of the source location. It must be a constant integer value. The third operand, mask, is a vector of boolean 'i1' values with the same number of elements as the return type. The fourth is a pass-through value that is used to fill the masked-off lanes of the result. The return type, underlying type of the base pointer and the type of passthru operand are the same vector types. + + +Semantics: +"""""""""" + +The '``llvm.masked.load``' intrinsic is designed for conditional reading of selected vector elements in a single IR operation. It is useful for targets that support vector masked loads and allows vectorizing predicated basic blocks on these targets. Other targets may support this intrinsic differently, for example by lowering it into a sequence of branches that guard scalar load operations. +The result of this operation is equivalent to a regular vector load instruction followed by a 'select' between the loaded and the passthru values, predicated on the same mask. However, using this intrinsic prevents exceptions on memory access to masked-off lanes. + + +:: + + %res = call <16 x float> @llvm.masked.load.v16f32 (<16 x float>* %ptr, i32 4, <16 x i1>%mask, <16 x float> %passthru) + + ;; The result of the two following instructions is identical aside from potential memory access exception + %loadlal = load <16 x float>* %ptr, align 4 + %res = select <16 x i1> %mask, <16 x float> %loadlal, <16 x float> %passthru + +.. _int_mstore: + +'``llvm.masked.store.*``' Intrinsics +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" +This is an overloaded intrinsic. The data stored in memory is a vector of any integer or floating point data type. + +:: + + declare void @llvm.masked.store.v8i32 (<8 x i32> , <8 x i32> * , i32 , <8 x i1> ) + declare void @llvm.masked.store.v16f32(<16 x i32> , <16 x i32>* , i32 , <16 x i1> ) + +Overview: +""""""""" + +Writes a vector to memory according to the provided mask. The mask holds a bit for each vector lane, and is used to prevent memory accesses to the masked-off lanes. + +Arguments: +"""""""""" + +The first operand is the vector value to be written to memory. The second operand is the base pointer for the store, it has the same underlying type as the value operand. The third operand is the alignment of the destination location. The fourth operand, mask, is a vector of boolean values. The types of the mask and the value operand must have the same number of vector elements. + + +Semantics: +"""""""""" + +The '``llvm.masked.store``' intrinsics is designed for conditional writing of selected vector elements in a single IR operation. It is useful for targets that support vector masked store and allows vectorizing predicated basic blocks on these targets. Other targets may support this intrinsic differently, for example by lowering it into a sequence of branches that guard scalar store operations. +The result of this operation is equivalent to a load-modify-store sequence. However, using this intrinsic prevents exceptions and data races on memory access to masked-off lanes. + +:: + + call void @llvm.masked.store.v16f32(<16 x float> %value, <16 x float>* %ptr, i32 4, <16 x i1> %mask) + + ;; The result of the following instructions is identical aside from potential data races and memory access exceptions + %oldval = load <16 x float>* %ptr, align 4 + %res = select <16 x i1> %mask, <16 x float> %value, <16 x float> %oldval + store <16 x float> %res, <16 x float>* %ptr, align 4 + + Memory Use Markers ------------------ @@ -9313,6 +9848,46 @@ Semantics: This intrinsic is lowered to the ``val``. +'``llvm.assume``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.assume(i1 %cond) + +Overview: +""""""""" + +The ``llvm.assume`` allows the optimizer to assume that the provided +condition is true. This information can then be used in simplifying other parts +of the code. + +Arguments: +"""""""""" + +The condition which the optimizer may assume is always true. + +Semantics: +"""""""""" + +The intrinsic allows the optimizer to assume that the provided condition is +always true whenever the control flow reaches the intrinsic call. No code is +generated for this intrinsic, and instructions that contribute only to the +provided condition are not used for code generation. If the condition is +violated during execution, the behavior is undefined. + +Note that the optimizer might limit the transformations performed on values +used by the ``llvm.assume`` intrinsic in order to preserve the instructions +only used to form the intrinsic's input argument. This might prove undesirable +if the extra information provided by the ``llvm.assume`` intrinsic does not cause +sufficient overall improvement in code quality. For this reason, +``llvm.assume`` should not be used to document basic mathematical invariants +that the optimizer can otherwise deduce or facts that are of little use to the +optimizer. + '``llvm.donothing``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9326,8 +9901,9 @@ Syntax: Overview: """"""""" -The ``llvm.donothing`` intrinsic doesn't perform any operation. It's the -only intrinsic that can be called with an invoke instruction. +The ``llvm.donothing`` intrinsic doesn't perform any operation. It's one of only +two intrinsics (besides ``llvm.experimental.patchpoint``) that can be called +with an invoke instruction. Arguments: """""""""" diff --git a/docs/Lexicon.rst b/docs/Lexicon.rst index 65b7a3e..9a599da 100644 --- a/docs/Lexicon.rst +++ b/docs/Lexicon.rst @@ -133,6 +133,15 @@ M **MC** Machine Code +N +- + +**NFC** + "No functional change". Used in a commit message to indicate that a patch + is a pure refactoring/cleanup. + Usually used in the first line, so it is visible without opening the + actual commit email. + O - .. _object pointer: diff --git a/docs/LinkTimeOptimization.rst b/docs/LinkTimeOptimization.rst index c15abd3..55a7486 100644 --- a/docs/LinkTimeOptimization.rst +++ b/docs/LinkTimeOptimization.rst @@ -134,7 +134,7 @@ Alternative Approaches Multi-phase communication between ``libLTO`` and linker ======================================================= -The linker collects information about symbol defininitions and uses in various +The linker collects information about symbol definitions and uses in various link objects which is more accurate than any information collected by other tools during typical build cycles. The linker collects this information by looking at the definitions and uses of symbols in native .o files and using diff --git a/docs/MCJITDesignAndImplementation.rst b/docs/MCJITDesignAndImplementation.rst index 2cb6296..237a5be 100644 --- a/docs/MCJITDesignAndImplementation.rst +++ b/docs/MCJITDesignAndImplementation.rst @@ -57,7 +57,7 @@ attempt to retrieve an object image from its ObjectCache member, if one has been set. If a cached object image cannot be retrieved, MCJIT will call its emitObject method. MCJIT::emitObject uses a local PassManager instance and creates a new ObjectBufferStream instance, both of which it -passes to TargetManager::addPassesToEmitMC before calling PassManager::run +passes to TargetMachine::addPassesToEmitMC before calling PassManager::run on the Module with which it was created. .. image:: MCJIT-load.png diff --git a/docs/Makefile b/docs/Makefile index d973af5..690f772 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,10 +1,10 @@ ##===- docs/Makefile ---------------------------------------*- Makefile -*-===## -# +# # The LLVM Compiler Infrastructure # # This file is distributed under the University of Illinois Open Source # License. See LICENSE.TXT for details. -# +# ##===----------------------------------------------------------------------===## LEVEL := .. @@ -121,7 +121,8 @@ regen-ocamldoc: $(Verb) $(MKDIR) $(PROJ_OBJ_DIR)/ocamldoc/html $(Verb) \ $(OCAMLDOC) -d $(PROJ_OBJ_DIR)/ocamldoc/html -sort -colorize-code -html \ - `$(FIND) $(LEVEL)/bindings/ocaml -name "*.odoc" -exec echo -load '{}' ';'` + `$(FIND) $(LEVEL)/bindings/ocaml -name "*.odoc" \ + -path "*/$(BuildMode)/*.odoc" -exec echo -load '{}' ';'` uninstall-local:: $(Echo) Uninstalling Documentation diff --git a/docs/MergeFunctions.rst b/docs/MergeFunctions.rst new file mode 100644 index 0000000..6b8012e --- /dev/null +++ b/docs/MergeFunctions.rst @@ -0,0 +1,802 @@ +================================= +MergeFunctions pass, how it works +================================= + +.. contents:: + :local: + +Introduction +============ +Sometimes code contains equal functions, or functions that does exactly the same +thing even though they are non-equal on the IR level (e.g.: multiplication on 2 +and 'shl 1'). It could happen due to several reasons: mainly, the usage of +templates and automatic code generators. Though, sometimes user itself could +write the same thing twice :-) + +The main purpose of this pass is to recognize such functions and merge them. + +Why would I want to read this document? +--------------------------------------- +Document is the extension to pass comments and describes the pass logic. It +describes algorithm that is used in order to compare functions, it also +explains how we could combine equal functions correctly, keeping module valid. + +Material is brought in top-down form, so reader could start learn pass from +ideas and end up with low-level algorithm details, thus preparing him for +reading the sources. + +So main goal is do describe algorithm and logic here; the concept. This document +is good for you, if you *don't want* to read the source code, but want to +understand pass algorithms. Author tried not to repeat the source-code and +cover only common cases, and thus avoid cases when after minor code changes we +need to update this document. + + +What should I know to be able to follow along with this document? +----------------------------------------------------------------- + +Reader should be familiar with common compile-engineering principles and LLVM +code fundamentals. In this article we suppose reader is familiar with +`Single Static Assingment `_ +concepts. Understanding of +`IR structure `_ is +also important. + +We will use such terms as +"`module `_", +"`function `_", +"`basic block `_", +"`user `_", +"`value `_", +"`instruction `_". + +As a good start point, Kaleidoscope tutorial could be used: + +:doc:`tutorial/index` + +Especially it's important to understand chapter 3 of tutorial: + +:doc:`tutorial/LangImpl3` + +Reader also should know how passes work in LLVM, he could use next article as a +reference and start point here: + +:doc:`WritingAnLLVMPass` + +What else? Well perhaps reader also should have some experience in LLVM pass +debugging and bug-fixing. + +What I gain by reading this document? +------------------------------------- +Main purpose is to provide reader with comfortable form of algorithms +description, namely the human reading text. Since it could be hard to +understand algorithm straight from the source code: pass uses some principles +that have to be explained first. + +Author wishes to everybody to avoid case, when you read code from top to bottom +again and again, and yet you don't understand why we implemented it that way. + +We hope that after this article reader could easily debug and improve +MergeFunctions pass and thus help LLVM project. + +Narrative structure +------------------- +Article consists of three parts. First part explains pass functionality on the +top-level. Second part describes the comparison procedure itself. The third +part describes the merging process. + +In every part author also tried to put the contents into the top-down form. +First, the top-level methods will be described, while the terminal ones will be +at the end, in the tail of each part. If reader will see the reference to the +method that wasn't described yet, he will find its description a bit below. + +Basics +====== + +How to do it? +------------- +Do we need to merge functions? Obvious thing is: yes that's a quite possible +case, since usually we *do* have duplicates. And it would be good to get rid of +them. But how to detect such a duplicates? The idea is next: we split functions +onto small bricks (parts), then we compare "bricks" amount, and if it equal, +compare "bricks" themselves, and then do our conclusions about functions +themselves. + +What the difference it could be? For example, on machine with 64-bit pointers +(let's assume we have only one address space), one function stores 64-bit +integer, while another one stores a pointer. So if the target is a machine +mentioned above, and if functions are identical, except the parameter type (we +could consider it as a part of function type), then we can treat ``uint64_t`` +and``void*`` as equal. + +It was just an example; possible details are described a bit below. + +As another example reader may imagine two more functions. First function +performs multiplication on 2, while the second one performs arithmetic right +shift on 1. + +Possible solutions +^^^^^^^^^^^^^^^^^^ +Let's briefly consider possible options about how and what we have to implement +in order to create full-featured functions merging, and also what it would +meant for us. + +Equal functions detection, obviously supposes "detector" method to be +implemented, latter should answer the question "whether functions are equal". +This "detector" method consists of tiny "sub-detectors", each of them answers +exactly the same question, but for function parts. + +As the second step, we should merge equal functions. So it should be a "merger" +method. "Merger" accepts two functions *F1* and *F2*, and produces *F1F2* +function, the result of merging. + +Having such a routines in our hands, we can process whole module, and merge all +equal functions. + +In this case, we have to compare every function with every another function. As +reader could notice, this way seems to be quite expensive. Of course we could +introduce hashing and other helpers, but it is still just an optimization, and +thus the level of O(N*N) complexity. + +Can we reach another level? Could we introduce logarithmical search, or random +access lookup? The answer is: "yes". + +Random-access +""""""""""""" +How it could be done? Just convert each function to number, and gather all of +them in special hash-table. Functions with equal hash are equal. Good hashing +means, that every function part must be taken into account. That means we have +to convert every function part into some number, and then add it into hash. +Lookup-up time would be small, but such approach adds some delay due to hashing +routine. + +Logarithmical search +"""""""""""""""""""" +We could introduce total ordering among the functions set, once we had it we +could then implement a logarithmical search. Lookup time still depends on N, +but adds a little of delay (*log(N)*). + +Present state +""""""""""""" +Both of approaches (random-access and logarithmical) has been implemented and +tested. And both of them gave a very good improvement. And what was most +surprising, logarithmical search was faster; sometimes up to 15%. Hashing needs +some extra CPU time, and it is the main reason why it works slower; in most of +cases total "hashing" time was greater than total "logarithmical-search" time. + +So, preference has been granted to the "logarithmical search". + +Though in the case of need, *logarithmical-search* (read "total-ordering") could +be used as a milestone on our way to the *random-access* implementation. + +Every comparison is based either on the numbers or on flags comparison. In +*random-access* approach we could use the same comparison algorithm. During +comparison we exit once we find the difference, but here we might have to scan +whole function body every time (note, it could be slower). Like in +"total-ordering", we will track every numbers and flags, but instead of +comparison, we should get numbers sequence and then create the hash number. So, +once again, *total-ordering* could be considered as a milestone for even faster +(in theory) random-access approach. + +MergeFunctions, main fields and runOnModule +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +There are two most important fields in class: + +``FnTree`` – the set of all unique functions. It keeps items that couldn't be +merged with each other. It is defined as: + +``std::set FnTree;`` + +Here ``FunctionNode`` is a wrapper for ``llvm::Function`` class, with +implemented “<†operator among the functions set (below we explain how it works +exactly; this is a key point in fast functions comparison). + +``Deferred`` – merging process can affect bodies of functions that are in +``FnTree`` already. Obviously such functions should be rechecked again. In this +case we remove them from ``FnTree``, and mark them as to be rescanned, namely +put them into ``Deferred`` list. + +runOnModule +""""""""""" +The algorithm is pretty simple: + +1. Put all module's functions into the *worklist*. + +2. Scan *worklist*'s functions twice: first enumerate only strong functions and +then only weak ones: + + 2.1. Loop body: take function from *worklist* (call it *FCur*) and try to + insert it into *FnTree*: check whether *FCur* is equal to one of functions + in *FnTree*. If there *is* equal function in *FnTree* (call it *FExists*): + merge function *FCur* with *FExists*. Otherwise add function from *worklist* + to *FnTree*. + +3. Once *worklist* scanning and merging operations is complete, check *Deferred* +list. If it is not empty: refill *worklist* contents with *Deferred* list and +do step 2 again, if *Deferred* is empty, then exit from method. + +Comparison and logarithmical search +""""""""""""""""""""""""""""""""""" +Let's recall our task: for every function *F* from module *M*, we have to find +equal functions *F`* in shortest time, and merge them into the single function. + +Defining total ordering among the functions set allows to organize functions +into the binary tree. The lookup procedure complexity would be estimated as +O(log(N)) in this case. But how to define *total-ordering*? + +We have to introduce a single rule applicable to every pair of functions, and +following this rule then evaluate which of them is greater. What kind of rule +it could be? Let's declare it as "compare" method, that returns one of 3 +possible values: + +-1, left is *less* than right, + +0, left and right are *equal*, + +1, left is *greater* than right. + +Of course it means, that we have to maintain +*strict and non-strict order relation properties*: + +* reflexivity (``a <= a``, ``a == a``, ``a >= a``), +* antisymmetry (if ``a <= b`` and ``b <= a`` then ``a == b``), +* transitivity (``a <= b`` and ``b <= c``, then ``a <= c``) +* asymmetry (if ``a < b``, then ``a > b`` or ``a == b``). + +As it was mentioned before, comparison routine consists of +"sub-comparison-routines", each of them also consists +"sub-comparison-routines", and so on, finally it ends up with a primitives +comparison. + +Below, we will use the next operations: + +#. ``cmpNumbers(number1, number2)`` is method that returns -1 if left is less + than right; 0, if left and right are equal; and 1 otherwise. + +#. ``cmpFlags(flag1, flag2)`` is hypothetical method that compares two flags. + The logic is the same as in ``cmpNumbers``, where ``true`` is 1, and + ``false`` is 0. + +The rest of article is based on *MergeFunctions.cpp* source code +(*/lib/Transforms/IPO/MergeFunctions.cpp*). We would like to ask +reader to keep this file open nearby, so we could use it as a reference for +further explanations. + +Now we're ready to proceed to the next chapter and see how it works. + +Functions comparison +==================== +At first, let's define how exactly we compare complex objects. + +Complex objects comparison (function, basic-block, etc) is mostly based on its +sub-objects comparison results. So it is similar to the next "tree" objects +comparison: + +#. For two trees *T1* and *T2* we perform *depth-first-traversal* and have + two sequences as a product: "*T1Items*" and "*T2Items*". + +#. Then compare chains "*T1Items*" and "*T2Items*" in + most-significant-item-first order. Result of items comparison would be the + result of *T1* and *T2* comparison itself. + +FunctionComparator::compare(void) +--------------------------------- +Brief look at the source code tells us, that comparison starts in +“``int FunctionComparator::compare(void)``†method. + +1. First parts to be compared are function's attributes and some properties that +outsides “attributes†term, but still could make function different without +changing its body. This part of comparison is usually done within simple +*cmpNumbers* or *cmpFlags* operations (e.g. +``cmpFlags(F1->hasGC(), F2->hasGC())``). Below is full list of function's +properties to be compared on this stage: + + * *Attributes* (those are returned by ``Function::getAttributes()`` + method). + + * *GC*, for equivalence, *RHS* and *LHS* should be both either without + *GC* or with the same one. + + * *Section*, just like a *GC*: *RHS* and *LHS* should be defined in the + same section. + + * *Variable arguments*. *LHS* and *RHS* should be both either with or + without *var-args*. + + * *Calling convention* should be the same. + +2. Function type. Checked by ``FunctionComparator::cmpType(Type*, Type*)`` +method. It checks return type and parameters type; the method itself will be +described later. + +3. Associate function formal parameters with each other. Then comparing function +bodies, if we see the usage of *LHS*'s *i*-th argument in *LHS*'s body, then, +we want to see usage of *RHS*'s *i*-th argument at the same place in *RHS*'s +body, otherwise functions are different. On this stage we grant the preference +to those we met later in function body (value we met first would be *less*). +This is done by “``FunctionComparator::cmpValues(const Value*, const Value*)``†+method (will be described a bit later). + +4. Function body comparison. As it written in method comments: + +“We do a CFG-ordered walk since the actual ordering of the blocks in the linked +list is immaterial. Our walk starts at the entry block for both functions, then +takes each block from each terminator in order. As an artifact, this also means +that unreachable blocks are ignored.†+ +So, using this walk we get BBs from *left* and *right* in the same order, and +compare them by “``FunctionComparator::compare(const BasicBlock*, const +BasicBlock*)``†method. + +We also associate BBs with each other, like we did it with function formal +arguments (see ``cmpValues`` method below). + +FunctionComparator::cmpType +--------------------------- +Consider how types comparison works. + +1. Coerce pointer to integer. If left type is a pointer, try to coerce it to the +integer type. It could be done if its address space is 0, or if address spaces +are ignored at all. Do the same thing for the right type. + +2. If left and right types are equal, return 0. Otherwise we need to give +preference to one of them. So proceed to the next step. + +3. If types are of different kind (different type IDs). Return result of type +IDs comparison, treating them as a numbers (use ``cmpNumbers`` operation). + +4. If types are vectors or integers, return result of their pointers comparison, +comparing them as numbers. + +5. Check whether type ID belongs to the next group (call it equivalent-group): + + * Void + + * Float + + * Double + + * X86_FP80 + + * FP128 + + * PPC_FP128 + + * Label + + * Metadata. + + If ID belongs to group above, return 0. Since it's enough to see that + types has the same ``TypeID``. No additional information is required. + +6. Left and right are pointers. Return result of address space comparison +(numbers comparison). + +7. Complex types (structures, arrays, etc.). Follow complex objects comparison +technique (see the very first paragraph of this chapter). Both *left* and +*right* are to be expanded and their element types will be checked the same +way. If we get -1 or 1 on some stage, return it. Otherwise return 0. + +8. Steps 1-6 describe all the possible cases, if we passed steps 1-6 and didn't +get any conclusions, then invoke ``llvm_unreachable``, since it's quite +unexpectable case. + +cmpValues(const Value*, const Value*) +------------------------------------- +Method that compares local values. + +This method gives us an answer on a very curious quesion: whether we could treat +local values as equal, and which value is greater otherwise. It's better to +start from example: + +Consider situation when we're looking at the same place in left function "*FL*" +and in right function "*FR*". And every part of *left* place is equal to the +corresponding part of *right* place, and (!) both parts use *Value* instances, +for example: + +.. code-block:: llvm + + instr0 i32 %LV ; left side, function FL + instr0 i32 %RV ; right side, function FR + +So, now our conclusion depends on *Value* instances comparison. + +Main purpose of this method is to determine relation between such values. + +What we expect from equal functions? At the same place, in functions "*FL*" and +"*FR*" we expect to see *equal* values, or values *defined* at the same place +in "*FL*" and "*FR*". + +Consider small example here: + +.. code-block:: llvm + + define void %f(i32 %pf0, i32 %pf1) { + instr0 i32 %pf0 instr1 i32 %pf1 instr2 i32 123 + } + +.. code-block:: llvm + + define void %g(i32 %pg0, i32 %pg1) { + instr0 i32 %pg0 instr1 i32 %pg0 instr2 i32 123 + } + +In this example, *pf0* is associated with *pg0*, *pf1* is associated with *pg1*, +and we also declare that *pf0* < *pf1*, and thus *pg0* < *pf1*. + +Instructions with opcode "*instr0*" would be *equal*, since their types and +opcodes are equal, and values are *associated*. + +Instruction with opcode "*instr1*" from *f* is *greater* than instruction with +opcode "*instr1*" from *g*; here we have equal types and opcodes, but "*pf1* is +greater than "*pg0*". + +And instructions with opcode "*instr2*" are equal, because their opcodes and +types are equal, and the same constant is used as a value. + +What we assiciate in cmpValues? +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +* Function arguments. *i*-th argument from left function associated with + *i*-th argument from right function. +* BasicBlock instances. In basic-block enumeration loop we associate *i*-th + BasicBlock from the left function with *i*-th BasicBlock from the right + function. +* Instructions. +* Instruction operands. Note, we can meet *Value* here we have never seen + before. In this case it is not a function argument, nor *BasicBlock*, nor + *Instruction*. It is global value. It is constant, since its the only + supposed global here. Method also compares: +* Constants that are of the same type. +* If right constant could be losslessly bit-casted to the left one, then we + also compare them. + +How to implement cmpValues? +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +*Association* is a case of equality for us. We just treat such values as equal. +But, in general, we need to implement antisymmetric relation. As it was +mentioned above, to understand what is *less*, we can use order in which we +meet values. If both of values has the same order in function (met at the same +time), then treat values as *associated*. Otherwise – it depends on who was +first. + +Every time we run top-level compare method, we initialize two identical maps +(one for the left side, another one for the right side): + +``map sn_mapL, sn_mapR;`` + +The key of the map is the *Value* itself, the *value* – is its order (call it +*serial number*). + +To add value *V* we need to perform the next procedure: + +``sn_map.insert(std::make_pair(V, sn_map.size()));`` + +For the first *Value*, map will return *0*, for second *Value* map will return +*1*, and so on. + +Then we can check whether left and right values met at the same time with simple +comparison: + +``cmpNumbers(sn_mapL[Left], sn_mapR[Right]);`` + +Of course, we can combine insertion and comparison: + +.. code-block:: c++ + + std::pair + LeftRes = sn_mapL.insert(std::make_pair(Left, sn_mapL.size())), RightRes + = sn_mapR.insert(std::make_pair(Right, sn_mapR.size())); + return cmpNumbers(LeftRes.first->second, RightRes.first->second); + +Let's look, how whole method could be implemented. + +1. we have to start from the bad news. Consider function self and +cross-referencing cases: + +.. code-block:: c++ + + // self-reference unsigned fact0(unsigned n) { return n > 1 ? n + * fact0(n-1) : 1; } unsigned fact1(unsigned n) { return n > 1 ? n * + fact1(n-1) : 1; } + + // cross-reference unsigned ping(unsigned n) { return n!= 0 ? pong(n-1) : 0; + } unsigned pong(unsigned n) { return n!= 0 ? ping(n-1) : 0; } + +.. + + This comparison has been implemented in initial *MergeFunctions* pass + version. But, unfortunately, it is not transitive. And this is the only case + we can't convert to less-equal-greater comparison. It is a seldom case, 4-5 + functions of 10000 (checked on test-suite), and, we hope, reader would + forgive us for such a sacrifice in order to get the O(log(N)) pass time. + +2. If left/right *Value* is a constant, we have to compare them. Return 0 if it +is the same constant, or use ``cmpConstants`` method otherwise. + +3. If left/right is *InlineAsm* instance. Return result of *Value* pointers +comparison. + +4. Explicit association of *L* (left value) and *R* (right value). We need to +find out whether values met at the same time, and thus are *associated*. Or we +need to put the rule: when we treat *L* < *R*. Now it is easy: just return +result of numbers comparison: + +.. code-block:: c++ + + std::pair + LeftRes = sn_mapL.insert(std::make_pair(Left, sn_mapL.size())), + RightRes = sn_mapR.insert(std::make_pair(Right, sn_mapR.size())); + if (LeftRes.first->second == RightRes.first->second) return 0; + if (LeftRes.first->second < RightRes.first->second) return -1; + return 1; + +Now when *cmpValues* returns 0, we can proceed comparison procedure. Otherwise, +if we get (-1 or 1), we need to pass this result to the top level, and finish +comparison procedure. + +cmpConstants +------------ +Performs constants comparison as follows: + +1. Compare constant types using ``cmpType`` method. If result is -1 or 1, goto +step 2, otherwise proceed to step 3. + +2. If types are different, we still can check whether constants could be +losslessly bitcasted to each other. The further explanation is modification of +``canLosslesslyBitCastTo`` method. + + 2.1 Check whether constants are of the first class types + (``isFirstClassType`` check): + + 2.1.1. If both constants are *not* of the first class type: return result + of ``cmpType``. + + 2.1.2. Otherwise, if left type is not of the first class, return -1. If + right type is not of the first class, return 1. + + 2.1.3. If both types are of the first class type, proceed to the next step + (2.1.3.1). + + 2.1.3.1. If types are vectors, compare their bitwidth using the + *cmpNumbers*. If result is not 0, return it. + + 2.1.3.2. Different types, but not a vectors: + + * if both of them are pointers, good for us, we can proceed to step 3. + * if one of types is pointer, return result of *isPointer* flags + comparison (*cmpFlags* operation). + * otherwise we have no methods to prove bitcastability, and thus return + result of types comparison (-1 or 1). + +Steps below are for the case when types are equal, or case when constants are +bitcastable: + +3. One of constants is a "*null*" value. Return the result of +``cmpFlags(L->isNullValue, R->isNullValue)`` comparison. + +4. Compare value IDs, and return result if it is not 0: + +.. code-block:: c++ + + if (int Res = cmpNumbers(L->getValueID(), R->getValueID())) + return Res; + +5. Compare the contents of constants. The comparison depends on kind of +constants, but on this stage it is just a lexicographical comparison. Just see +how it was described in the beginning of "*Functions comparison*" paragraph. +Mathematically it is equal to the next case: we encode left constant and right +constant (with similar way *bitcode-writer* does). Then compare left code +sequence and right code sequence. + +compare(const BasicBlock*, const BasicBlock*) +--------------------------------------------- +Compares two *BasicBlock* instances. + +It enumerates instructions from left *BB* and right *BB*. + +1. It assigns serial numbers to the left and right instructions, using +``cmpValues`` method. + +2. If one of left or right is *GEP* (``GetElementPtr``), then treat *GEP* as +greater than other instructions, if both instructions are *GEPs* use ``cmpGEP`` +method for comparison. If result is -1 or 1, pass it to the top-level +comparison (return it). + + 3.1. Compare operations. Call ``cmpOperation`` method. If result is -1 or + 1, return it. + + 3.2. Compare number of operands, if result is -1 or 1, return it. + + 3.3. Compare operands themselves, use ``cmpValues`` method. Return result + if it is -1 or 1. + + 3.4. Compare type of operands, using ``cmpType`` method. Return result if + it is -1 or 1. + + 3.5. Proceed to the next instruction. + +4. We can finish instruction enumeration in 3 cases: + + 4.1. We reached the end of both left and right basic-blocks. We didn't + exit on steps 1-3, so contents is equal, return 0. + + 4.2. We have reached the end of the left basic-block. Return -1. + + 4.3. Return 1 (the end of the right basic block). + +cmpGEP +------ +Compares two GEPs (``getelementptr`` instructions). + +It differs from regular operations comparison with the only thing: possibility +to use ``accumulateConstantOffset`` method. + +So, if we get constant offset for both left and right *GEPs*, then compare it as +numbers, and return comparison result. + +Otherwise treat it like a regular operation (see previous paragraph). + +cmpOperation +------------ +Compares instruction opcodes and some important operation properties. + +1. Compare opcodes, if it differs return the result. + +2. Compare number of operands. If it differs – return the result. + +3. Compare operation types, use *cmpType*. All the same – if types are +different, return result. + +4. Compare *subclassOptionalData*, get it with ``getRawSubclassOptionalData`` +method, and compare it like a numbers. + +5. Compare operand types. + +6. For some particular instructions check equivalence (relation in our case) of +some significant attributes. For example we have to compare alignment for +``load`` instructions. + +O(log(N)) +--------- +Methods described above implement order relationship. And latter, could be used +for nodes comparison in a binary tree. So we can organize functions set into +the binary tree and reduce the cost of lookup procedure from +O(N*N) to O(log(N)). + +Merging process, mergeTwoFunctions +================================== +Once *MergeFunctions* detected that current function (*G*) is equal to one that +were analyzed before (function *F*) it calls ``mergeTwoFunctions(Function*, +Function*)``. + +Operation affects ``FnTree`` contents with next way: *F* will stay in +``FnTree``. *G* being equal to *F* will not be added to ``FnTree``. Calls of +*G* would be replaced with something else. It changes bodies of callers. So, +functions that calls *G* would be put into ``Deferred`` set and removed from +``FnTree``, and analyzed again. + +The approach is next: + +1. Most wished case: when we can use alias and both of *F* and *G* are weak. We +make both of them with aliases to the third strong function *H*. Actually *H* +is *F*. See below how it's made (but it's better to look straight into the +source code). Well, this is a case when we can just replace *G* with *F* +everywhere, we use ``replaceAllUsesWith`` operation here (*RAUW*). + +2. *F* could not be overridden, while *G* could. It would be good to do the +next: after merging the places where overridable function were used, still use +overridable stub. So try to make *G* alias to *F*, or create overridable tail +call wrapper around *F* and replace *G* with that call. + +3. Neither *F* nor *G* could be overridden. We can't use *RAUW*. We can just +change the callers: call *F* instead of *G*. That's what +``replaceDirectCallers`` does. + +Below is detailed body description. + +If “F†may be overridden +------------------------ +As follows from ``mayBeOverridden`` comments: “whether the definition of this +global may be replaced by something non-equivalent at link timeâ€. If so, thats +ok: we can use alias to *F* instead of *G* or change call instructions itself. + +HasGlobalAliases, removeUsers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +First consider the case when we have global aliases of one function name to +another. Our purpose is make both of them with aliases to the third strong +function. Though if we keep *F* alive and without major changes we can leave it +in ``FnTree``. Try to combine these two goals. + +Do stub replacement of *F* itself with an alias to *F*. + +1. Create stub function *H*, with the same name and attributes like function +*F*. It takes maximum alignment of *F* and *G*. + +2. Replace all uses of function *F* with uses of function *H*. It is the two +steps procedure instead. First of all, we must take into account, all functions +from whom *F* is called would be changed: since we change the call argument +(from *F* to *H*). If so we must to review these caller functions again after +this procedure. We remove callers from ``FnTree``, method with name +``removeUsers(F)`` does that (don't confuse with ``replaceAllUsesWith``): + + 2.1. ``Inside removeUsers(Value* + V)`` we go through the all values that use value *V* (or *F* in our context). + If value is instruction, we go to function that holds this instruction and + mark it as to-be-analyzed-again (put to ``Deferred`` set), we also remove + caller from ``FnTree``. + + 2.2. Now we can do the replacement: call ``F->replaceAllUsesWith(H)``. + +3. *H* (that now "officially" plays *F*'s role) is replaced with alias to *F*. +Do the same with *G*: replace it with alias to *F*. So finally everywhere *F* +was used, we use *H* and it is alias to *F*, and everywhere *G* was used we +also have alias to *F*. + +4. Set *F* linkage to private. Make it strong :-) + +No global aliases, replaceDirectCallers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If global aliases are not supported. We call ``replaceDirectCallers`` then. Just +go through all calls of *G* and replace it with calls of *F*. If you look into +method you will see that it scans all uses of *G* too, and if use is callee (if +user is call instruction and *G* is used as what to be called), we replace it +with use of *F*. + +If “F†could not be overridden, fix it! +""""""""""""""""""""""""""""""""""""""" + +We call ``writeThunkOrAlias(Function *F, Function *G)``. Here we try to replace +*G* with alias to *F* first. Next conditions are essential: + +* target should support global aliases, +* the address itself of *G* should be not significant, not named and not + referenced anywhere, +* function should come with external, local or weak linkage. + +Otherwise we write thunk: some wrapper that has *G's* interface and calls *F*, +so *G* could be replaced with this wrapper. + +*writeAlias* + +As follows from *llvm* reference: + +“Aliases act as *second name* for the aliasee valueâ€. So we just want to create +second name for *F* and use it instead of *G*: + +1. create global alias itself (*GA*), + +2. adjust alignment of *F* so it must be maximum of current and *G's* alignment; + +3. replace uses of *G*: + + 3.1. first mark all callers of *G* as to-be-analyzed-again, using + ``removeUsers`` method (see chapter above), + + 3.2. call ``G->replaceAllUsesWith(GA)``. + +4. Get rid of *G*. + +*writeThunk* + +As it written in method comments: + +“Replace G with a simple tail call to bitcast(F). Also replace direct uses of G +with bitcast(F). Deletes G.†+ +In general it does the same as usual when we want to replace callee, except the +first point: + +1. We generate tail call wrapper around *F*, but with interface that allows use +it instead of *G*. + +2. “As-usualâ€: ``removeUsers`` and ``replaceAllUsesWith`` then. + +3. Get rid of *G*. + +That's it. +========== +We have described how to detect equal functions, and how to merge them, and in +first chapter we have described how it works all-together. Author hopes, reader +have some picture from now, and it helps him improve and debug ­this pass. + +Reader is welcomed to send us any questions and proposals ;-) diff --git a/docs/Passes.rst b/docs/Passes.rst index 9f40092..3f95341 100644 --- a/docs/Passes.rst +++ b/docs/Passes.rst @@ -891,17 +891,24 @@ calls, or transforming sets of stores into ``memset``\ s. This pass looks for equivalent functions that are mergable and folds them. -A hash is computed from the function, based on its type and number of basic -blocks. +Total-ordering is introduced among the functions set: we define comparison +that answers for every two functions which of them is greater. It allows to +arrange functions into the binary tree. -Once all hashes are computed, we perform an expensive equality comparison on -each function pair. This takes n^2/2 comparisons per bucket, so it's important -that the hash function be high quality. The equality comparison iterates -through each instruction in each basic block. +For every new function we check for equivalent in tree. -When a match is found the functions are folded. If both functions are -overridable, we move the functionality into a new internal function and leave -two overridable thunks to it. +If equivalent exists we fold such functions. If both functions are overridable, +we move the functionality into a new internal function and leave two +overridable thunks to it. + +If there is no equivalent, then we add this function to tree. + +Lookup routine has O(log(n)) complexity, while whole merging process has +complexity of O(n*log(n)). + +Read +:doc:`this ` +article for more details. ``-mergereturn``: Unify function exit nodes ------------------------------------------- diff --git a/docs/Phabricator.rst b/docs/Phabricator.rst index 8ac9afe..3f4f72a 100644 --- a/docs/Phabricator.rst +++ b/docs/Phabricator.rst @@ -66,7 +66,8 @@ To upload a new patch: * Leave the drop down on *Create a new Revision...* and click *Continue*. * Enter a descriptive title and summary; add reviewers and mailing lists that you want to be included in the review. If your patch is - for LLVM, cc llvm-commits; if your patch is for Clang, cc cfe-commits. + for LLVM, add llvm-commits as a subscriber; if your patch is for Clang, + add cfe-commits. * Click *Save*. To submit an updated patch: diff --git a/docs/ProgrammersManual.rst b/docs/ProgrammersManual.rst index 46ec15f..85a4ad8 100644 --- a/docs/ProgrammersManual.rst +++ b/docs/ProgrammersManual.rst @@ -422,9 +422,12 @@ to specify the debug type for the entire module (if you do this before you because there is no system in place to ensure that names do not conflict. If two different modules use the same string, they will all be turned on when the name is specified. This allows, for example, all debug information for -instruction scheduling to be enabled with ``-debug-type=InstrSched``, even if +instruction scheduling to be enabled with ``-debug-only=InstrSched``, even if the source lives in multiple files. +For performance reasons, -debug-only is not available in optimized build +(``--enable-optimized``) of LLVM. + The ``DEBUG_WITH_TYPE`` macro is also available for situations where you would like to set ``DEBUG_TYPE``, but only for one specific ``DEBUG`` statement. It takes an additional first parameter, which is the type to use. For example, the @@ -873,7 +876,7 @@ variety of customizations. llvm/ADT/ilist_node.h ^^^^^^^^^^^^^^^^^^^^^ -``ilist_node`` implements a the forward and backward links that are expected +``ilist_node`` implements the forward and backward links that are expected by the ``ilist`` (and analogous containers) in the default manner. ``ilist_node``\ s are meant to be embedded in the node type ``T``, usually diff --git a/docs/R600Usage.rst b/docs/R600Usage.rst new file mode 100644 index 0000000..48a30c8 --- /dev/null +++ b/docs/R600Usage.rst @@ -0,0 +1,43 @@ +============================ +User Guide for R600 Back-end +============================ + +Introduction +============ + +The R600 back-end provides ISA code generation for AMD GPUs, starting with +the R600 family up until the current Sea Islands (GCN Gen 2). + + +Assembler +========= + +The assembler is currently a work in progress and not yet complete. Below +are the currently supported features. + +SOPP Instructions +----------------- + +Unless otherwise mentioned, all SOPP instructions that with an operand +accept a integer operand(s) only. No verification is performed on the +operands, so it is up to the programmer to be familiar with the range +or acceptable values. + +s_waitcnt +^^^^^^^^^ + +s_waitcnt accepts named arguments to specify which memory counter(s) to +wait for. + +.. code-block:: nasm + + // Wait for all counters to be 0 + s_waitcnt 0 + + // Equivalent to s_waitcnt 0. Counter names can also be delimited by + // '&' or ','. + s_waitcnt vmcnt(0) expcnt(0) lgkcmt(0) + + // Wait for vmcnt counter to be 1. + s_waitcnt vmcnt(1) + diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst index 87f96a6..dd54d45 100644 --- a/docs/ReleaseNotes.rst +++ b/docs/ReleaseNotes.rst @@ -1,16 +1,21 @@ ====================== -LLVM 3.5 Release Notes +LLVM 3.6 Release Notes ====================== .. contents:: :local: +.. warning:: + These are in-progress notes for the upcoming LLVM 3.6 release. You may + prefer the `LLVM 3.5 Release Notes `_. + Introduction ============ This document contains the release notes for the LLVM Compiler Infrastructure, -release 3.5. Here we describe the status of LLVM, including major improvements +release 3.6. Here we describe the status of LLVM, including major improvements from the previous release, improvements in various subprojects of LLVM, and some of the current users of the code. All LLVM releases may be downloaded from the `LLVM releases web site `_. @@ -21,77 +26,14 @@ have questions or comments, the `LLVM Developer's Mailing List `_ is a good place to send them. +Note that if you are reading this file from a Subversion checkout or the main +LLVM web page, this document applies to the *next* release, not the current +one. To see the release notes for a specific release, please see the `releases +page `_. + Non-comprehensive list of changes in this release ================================================= -Changes to the MIPS Target --------------------------- - -* A large number of bugs have been fixed for big-endian Mips targets using the - N32 and N64 ABI's. Please note that some of these bugs will still affect - LLVM-IR generated by LLVM 3.5 since correct code generation depends on - appropriate usage of the ``inreg``, ``signext``, and ``zeroext`` attributes - on all function arguments and returns. - -* The registers used to return a structure containing a single 128-bit floating - point member on the N32/N64 ABI's have been changed from those specified by - the ABI documentation to match those used by GCC. The documentation specifies - that ``$f0`` and ``$f2`` should be used but GCC has used ``$f0`` and ``$f1`` - for many years. - -* Returning a zero-byte struct no longer causes incorrect code generation when - using the O32 ABI. - -* Passing structures of less than 32-bits using the O32 ABI on a big-endian - target has been fixed. - -* The exception personality has been changed for 64-bit Mips targets to - eliminate warnings about relocations in a read-only section. - -* Incorrect usage of odd-numbered single-precision floating point registers - has been fixed when the fastcc calling convention is used with 64-bit FPU's - and -mno-odd-spreg. - -* For inline assembly, the 'z' print-modifier print modifier can now be used on - non-immediate values. - -* Attempting to disassemble l[wd]c[23], s[wd]c[23], cache, and pref no longer - triggers an assertion. - -Non-comprehensive list of changes in 3.5 -======================================== - -* All backends have been changed to use the MC asm printer and support for the - non MC one has been removed. - -* Clang can now successfully self-host itself on Linux/Sparc64 and on - FreeBSD/Sparc64. - -* LLVM now assumes the assembler supports ``.loc`` for generating debug line - numbers. The old support for printing the debug line info directly was only - used by ``llc`` and has been removed. - -* All inline assembly is parsed by the integrated assembler when it is enabled. - Previously this was only the case for object-file output. It is now the case - for assembly output as well. The integrated assembler can be disabled with - the ``-no-integrated-as`` option. - -* llvm-ar now handles IR files like regular object files. In particular, a - regular symbol table is created for symbols defined in IR files, including - those in file scope inline assembly. - -* LLVM now always uses cfi directives for producing most stack - unwinding information. - -* The prefix for loop vectorizer hint metadata has been changed from - ``llvm.vectorizer`` to ``llvm.loop.vectorize``. In addition, - ``llvm.vectorizer.unroll`` metadata has been renamed - ``llvm.loop.interleave.count``. - -* Some backends previously implemented Atomic NAND(x,y) as ``x & ~y``. Now - all backends implement it as ``~(x & y)``, matching the semantics of GCC 4.4 - and later. - .. NOTE For small 1-3 sentence descriptions, just add an entry at the end of this list. If your description won't fit comfortably in one bullet @@ -99,6 +41,11 @@ Non-comprehensive list of changes in 3.5 functionality, or simply have a lot to talk about), see the `NOTE` below for adding a new subsection. +* Support for AuroraUX has been removed. + +* Added support for a `native object file-based bitcode wrapper format + `_. + * ... next change ... .. NOTE @@ -111,276 +58,186 @@ Non-comprehensive list of changes in 3.5 Makes programs 10x faster by doing Special New Thing. +Prefix data rework +------------------ + +The semantics of the ``prefix`` attribute have been changed. Users +that want the previous ``prefix`` semantics should instead use +``prologue``. To motivate this change, let's examine the primary +usecases that these attributes aim to serve, + + 1. Code sanitization metadata (e.g. Clang's undefined behavior + sanitizer) + + 2. Function hot-patching: Enable the user to insert ``nop`` operations + at the beginning of the function which can later be safely replaced + with a call to some instrumentation facility. + + 3. Language runtime metadata: Allow a compiler to insert data for + use by the runtime during execution. GHC is one example of a + compiler that needs this functionality for its + tables-next-to-code functionality. + +Previously ``prefix`` served cases (1) and (2) quite well by allowing the user +to introduce arbitrary data at the entrypoint but before the function +body. Case (3), however, was poorly handled by this approach as it +required that prefix data was valid executable code. + +In this release the concept of prefix data has been redefined to be +data which occurs immediately before the function entrypoint (i.e. the +symbol address). Since prefix data now occurs before the function +entrypoint, there is no need for the data to be valid code. + +The previous notion of prefix data now goes under the name "prologue +data" to emphasize its duality with the function epilogue. + +The intention here is to handle cases (1) and (2) with prologue data and +case (3) with prefix data. See the language reference for further details +on the semantics of these attributes. + +This refactoring arose out of discussions_ with Reid Kleckner in +response to a proposal to introduce the notion of symbol offsets to +enable handling of case (3). + +.. _discussions: http://lists.cs.uiuc.edu/pipermail/llvmdev/2014-May/073235.html + + Changes to the ARM Backend -------------------------- -Since release 3.3, a lot of new features have been included in the ARM -back-end but weren't production ready (ie. well tested) on release 3.4. -Just after the 3.4 release, we started heavily testing two major parts -of the back-end: the integrated assembler (IAS) and the ARM exception -handling (EHABI), and now they are enabled by default on LLVM/Clang. - -The IAS received a lot of GNU extensions and directives, as well as some -specific pre-UAL instructions. Not all remaining directives will be -implemented, as we made judgement calls on the need versus the complexity, -and have chosen simplicity and future compatibility where hard decisions -had to be made. The major difference is, as stated above, the IAS validates -all inline ASM, not just for object emission, and that cause trouble with -some uses of inline ASM as pre-processor magic. - -So, while the IAS is good enough to compile large projects (including most -of the Linux kernel), there are a few things that we can't (and probably -won't) do. For those cases, please use ``-fno-integrated-as`` in Clang. - -Exception handling is another big change. After extensive testing and -changes to cooperate with Dwarf unwinding, EHABI is enabled by default. -The options ``-arm-enable-ehabi`` and ``-arm-enable-ehabi-descriptors``, -which were used to enable EHABI in the previous releases, are removed now. - -This means all ARM code will emit EH unwind tables, or CFI unwinding (for -debug/profiling), or both. To avoid run-time inconsistencies, C code will -also emit EH tables (in case they interoperate with C++ code), as is the -case for other architectures (ex. x86_64). + During this release ... + Changes to the MIPS Target -------------------------- -There has been a large amount of improvements to the MIPS target which can be -broken down into subtarget, ABI, and Integrated Assembler changes. +During this release the MIPS target has reached a few major milestones. The +compiler has gained support for MIPS-II and MIPS-III; become ABI-compatible +with GCC for big and little endian O32, N32, and N64; and is now able to +compile the Linux kernel for 32-bit targets. Additionally, LLD now supports +microMIPS for the O32 ABI on little endian targets. + +ABI +^^^ -Subtargets -^^^^^^^^^^ +A large number of bugs have been fixed for big-endian MIPS targets using the +N32 and N64 ABI's as well as a small number of bugs affecting other ABI's. +Please note that some of these bugs will still affect LLVM-IR generated by +LLVM 3.5 since correct code generation depends on appropriate usage of the +``inreg``, ``signext``, and ``zeroext`` attributes on all function arguments +and returns. -Added support for Release 6 of the MIPS32 and MIPS64 architecture (MIPS32r6 -and MIPS64r6). Release 6 makes a number of significant changes to the MIPS32 -and MIPS64 architectures. For example, FPU registers are always 64-bits wide, -FPU NaN values conform to IEEE 754 (2008), and the unaligned memory instructions -(such as lwl and lwr) have been replaced with a requirement for ordinary memory -operations to support unaligned operations. Full details of MIPS32 and MIPS64 -Release 6 can be found on the `MIPS64 Architecture page at Imagination -Technologies `_. +There are far too many corrections to provide a complete list but here are a +few notable ones: -This release also adds experimental support for MIPS-IV, cnMIPS, and Cavium -Octeon CPU's. +* Big-endian N32 and N64 now interlinks successfully with GCC compiled code. + Previously this didn't work for the majority of cases. -Support for the MIPS SIMD Architecture (MSA) has been improved to support MSA -on MIPS64. +* The registers used to return a structure containing a single 128-bit floating + point member on the N32/N64 ABI's have been changed from those specified by + the ABI documentation to match those used by GCC. The documentation specifies + that ``$f0`` and ``$f2`` should be used but GCC has used ``$f0`` and ``$f1`` + for many years. -Support for IEEE 754 (2008) NaN values has been added. +* Returning a zero-byte struct no longer causes arguments to be read from the + wrong registers when using the O32 ABI. -ABI and ABI extensions -^^^^^^^^^^^^^^^^^^^^^^ +* The exception personality has been changed for 64-bit MIPS targets to + eliminate warnings about relocations in a read-only section. -There has also been considerable ABI work since the 3.4 release. This release -adds support for the N32 ABI, the O32-FPXX ABI Extension, the O32-FP64 ABI -Extension, and the O32-FP64A ABI Extension. +* Incorrect usage of odd-numbered single-precision floating point registers + has been fixed when the fastcc calling convention is used with 64-bit FPU's + and -mno-odd-spreg. -The N32 ABI is an existing ABI that has now been implemented in LLVM. It is a -64-bit ABI that is similar to N64 but retains 32-bit pointers. N64 remains the -default 64-bit ABI in LLVM. This differs from GCC where N32 is the default -64-bit ABI. +LLVMLinux +^^^^^^^^^ -The O32-FPXX ABI Extension is 100% compatible with the O32-ABI and the O32-FP64 -ABI Extension and may be linked with either but may not be linked with both of -these simultaneously. It extends the O32 ABI to allow the same code to execute -without modification on processors with 32-bit FPU registers as well as 64-bit -FPU registers. The O32-FPXX ABI Extension is enabled by default for the O32 ABI -on mips*-img-linux-gnu and mips*-mti-linux-gnu triples and is selected with --mfpxx. It is expected that future releases of LLVM will enable the FPXX -Extension for O32 on all triples. +It is now possible to compile the Linux kernel. This currently requires a small +number of kernel patches. See the `LLVMLinux project +`_ for details. -The O32-FP64 ABI Extension is an extension to the O32 ABI to fully exploit FPU's -with 64-bit registers and is enabled with -mfp64. This replaces an undocumented -and unsupported O32 extension which was previously enabled with -mfp64. It is -100% compatible with the O32-FPXX ABI Extension. +* Added -mabicalls and -mno-abicalls. The implementation may not be complete + but works sufficiently well for the Linux kernel. -The O32-FP64A ABI Extension is a restricted form of the O32-FP64 ABI Extension -which allows interlinking with unmodified binaries that use the base O32 ABI. +* Fixed multiple compatibility issues between LLVM's inline assembly support + and GCC's. -Integrated Assembler -^^^^^^^^^^^^^^^^^^^^ +* Added support for a number of directives used by Linux to the Integrated + Assembler. -The MIPS Integrated Assembler has undergone a substantial overhaul including a -rewrite of the assembly parser. It's not ready for general use in this release -but adventurous users may wish to enable it using ``-fintegrated-as``. +Miscellaneous +^^^^^^^^^^^^^ -In this release, the integrated assembler supports the majority of MIPS-I, -MIPS-II, MIPS-III, MIPS-IV, MIPS-V, MIPS32, MIPS32r2, MIPS32r6, MIPS64, -MIPS64r2, and MIPS64r6 as well as some of the Application Specific Extensions -such as MSA. It also supports several of the MIPS specific assembler directives -such as ``.set``, ``.module``, ``.cpload``, etc. +* Attempting to disassemble l[wd]c[23], s[wd]c[23], cache, and pref no longer + triggers an assertion. -Changes to the AArch64 Target ------------------------------ +* Added -muclibc and -mglibc to support toolchains that provide both uClibC and + GLibC. -The AArch64 target in LLVM 3.5 is based on substantially different code to the -one in LLVM 3.4, having been created as the result of merging code released by -Apple for targetting iOS with the previously existing backend. +* __SIZEOF_INT128__ is no longer defined for 64-bit targets since 128-bit + integers do not work at this time for this target. -We hope the result is a general improvement in the project. Particularly notable -changes are: +* Using $t4-$t7 with the N32 and N64 ABI is deprecated when ``-fintegrated-as`` + is in use and will be removed in LLVM 3.7. These names have never been + supported by the GNU Assembler for these ABI's. -* We should produce faster code, having combined optimisations and ideas from - both sources in the final backend. -* We have a FastISel for AArch64, which should compile time for debug builds (at - -O0). -* We can now target iOS platforms (using the triple ``arm64-apple-ios7.0``). +Changes to the PowerPC Target +----------------------------- -Background -^^^^^^^^^^ +There are numerous improvements to the PowerPC target in this release: -During the 3.5 release cycle, Apple released the source used to generate 64-bit -ARM programs on iOS platforms. This took the form of a separate backend that had -been developed in parallel to, and largely isolation from, the existing -code. +* LLVM now generates the Vector-Scalar eXtension (VSX) instructions from + version 2.06 of the Power ISA, for both big- and little-endian targets. -We decided that maintaining the two backends indefinitely was not an option, -since their features almost entirely overlapped. However, the implementation -details in both were different enough that any merge had to firmly start with -one backend as the core and cherry-pick the best features and optimisations from -the other. +* LLVM now has a POWER8 instruction scheduling description. -After discussion, we decided to start with the Apple backend (called ARM64 at -the time) since it was older, more thoroughly tested in production use, and had -fewer idiosyncracies in the implementation details. +* Address Sanitizer (ASAN) support is now fully functional. -Many people from across the community worked throughout April and May to ensure -that this merge destination had all the features we wanted, from both -sources. In many cases we could simply copy code across; others needed heavy -modification for the new host; in the most worthwhile, we looked at both -implementations and combined the best features of each in an entirely new way. +* Performance of simple atomic accesses has been greatly improved. -We had also decided that the name of the combined backend should be AArch64, -following ARM's official documentation. So, at the end of May the old -AArch64 directory was removed, and ARM64 renamed into its place. +* Atomic fences now use light-weight syncs where possible, again providing + significant performance benefit. -Changes to the PowerPC Target ------------------------------ +* The PowerPC target now supports PIC levels (-fPIC vs. -fpic). -The PowerPC 64-bit Little Endian subtarget (powerpc64le-unknown-linux-gnu) is -now fully supported. This includes support for the Altivec instruction set. +* PPC32 SVR4 now supports small-model PIC. -The Power Architecture 64-Bit ELFv2 ABI Specification is now supported, and -is the default ABI for Little Endian. The ELFv1 ABI remains the default ABI -for Big Endian. Currently, it is not possible to override these defaults. -That capability will be available (albeit not recommended) in a future release. +* There have been many smaller bug fixes and performance improvements. -Links to the ELFv2 ABI specification and to the Power ISA Version 2.07 -specification may be found `here `_ (free registration required). -Efforts are underway to move this to a location that doesn't require -registration, but the planned site isn't ready yet. +Changes to the OCaml bindings +----------------------------- -Experimental support for the VSX instruction set introduced with ISA 2.06 -is now available using the ``-mvsx`` switch. Work remains on this, so it -is not recommended for production use. VSX is disabled for Little Endian -regardless of this switch setting. +* The bindings now require OCaml >=4.00.0, ocamlfind, + ctypes >=0.3.0 <0.4 and OUnit 2 if tests are enabled. -Load/store cost estimates have been improved. +* The bindings can now be built using cmake as well as autoconf. -Constant hoisting has been enabled. +* LLVM 3.5 has, unfortunately, shipped a broken Llvm_executionengine + implementation. In LLVM 3.6, the bindings now fully support MCJIT, + however the interface is reworked from scratch using ctypes + and is not backwards compatible. -Global named register support has been enabled. +* Llvm_linker.Mode was removed following the changes in LLVM. + This breaks the interface of Llvm_linker. -Initial support for PIC code has been added for the 32-bit ELF subtarget. -Further support will be available in a future release. +* All combinations of ocamlc/ocamlc -custom/ocamlopt and shared/static + builds of LLVM are now supported. +* Absolute paths are not embedded into the OCaml libraries anymore. + Either OCaml >=4.02.2 must be used, which includes an rpath-like $ORIGIN + mechanism, or META file must be updated for out-of-tree installations; + see r221139. -Changes to CMake build system ------------------------------ +* As usual, many more functions have been exposed to OCaml. -* Building and installing LLVM, Clang and lld sphinx documentation can now be - done in CMake builds. If ``LLVM_ENABLE_SPHINX`` is enabled the - "``docs--html``" and "``docs--man``" targets (e.g. - ``docs-llvm-html``) become available which can be invoked directly (e.g. - ``make docs-llvm-html``) to build only the relevant sphinx documentation. If - ``LLVM_BUILD_DOCS`` is enabled then the sphinx documentation will also be - built as part of the normal build. Enabling this variable also means that if - the ``install`` target is invoked then the built documentation will be - installed. See :ref:`LLVM-specific variables`. - -* Both the Autoconf/Makefile and CMake build systems now generate - ``LLVMConfig.cmake`` (and other files) to export installed libraries. This - means that projects using CMake to build against LLVM libraries can now build - against an installed LLVM built by the Autoconf/Makefile system. See - :ref:`Embedding LLVM in your project` for details. - -* Use of ``llvm_map_components_to_libraries()`` by external projects is - deprecated and the new ``llvm_map_components_to_libnames()`` should be used - instead. - -External Open Source Projects Using LLVM 3.5 +External Open Source Projects Using LLVM 3.6 ============================================ An exciting aspect of LLVM is that it is used as an enabling technology for a lot of other language and tools projects. This section lists some of the -projects that have already been updated to work with LLVM 3.5. - -LDC - the LLVM-based D compiler -------------------------------- - -`D `_ is a language with C-like syntax and static typing. It -pragmatically combines efficiency, control, and modeling power, with safety and -programmer productivity. D supports powerful concepts like Compile-Time Function -Execution (CTFE) and Template Meta-Programming, provides an innovative approach -to concurrency and offers many classical paradigms. - -`LDC `_ uses the frontend from the reference compiler -combined with LLVM as backend to produce efficient native code. LDC targets -x86/x86_64 systems like Linux, OS X, FreeBSD and Windows and also Linux/PPC64. -Ports to other architectures like ARM, AArch64 and MIPS64 are underway. - -Portable Computing Language (pocl) ----------------------------------- - -In addition to producing an easily portable open source OpenCL -implementation, another major goal of `pocl `_ -is improving performance portability of OpenCL programs with -compiler optimizations, reducing the need for target-dependent manual -optimizations. An important part of pocl is a set of LLVM passes used to -statically parallelize multiple work-items with the kernel compiler, even in -the presence of work-group barriers. This enables static parallelization of -the fine-grained static concurrency in the work groups in multiple ways. - -TTA-based Co-design Environment (TCE) -------------------------------------- - -`TCE `_ is a toolset for designing new -exposed datapath processors based on the Transport triggered architecture (TTA). -The toolset provides a complete co-design flow from C/C++ -programs down to synthesizable VHDL/Verilog and parallel program binaries. -Processor customization points include the register files, function units, -supported operations, and the interconnection network. - -TCE uses Clang and LLVM for C/C++/OpenCL C language support, target independent -optimizations and also for parts of code generation. It generates -new LLVM-based code generators "on the fly" for the designed processors and -loads them in to the compiler backend as runtime libraries to avoid -per-target recompilation of larger parts of the compiler chain. - -ISPC ----- - -`ISPC `_ is a C-based language based on the SPMD -(single program, multiple data) programming model that generates efficient -SIMD code for modern processors without the need for complex analysis and -autovectorization. The language exploits the concept of “varying†data types, -which ensure vector-friendly data layout, explicit vectorization and compact -representation of the program. The project uses the LLVM infrastructure for -optimization and code generation. - -Likely ------- - -`Likely `_ is an embeddable just-in-time Lisp for -image recognition and heterogenous architectures. Algorithms are just-in-time -compiled using LLVM’s MCJIT infrastructure to execute on single or -multi-threaded CPUs and potentially OpenCL SPIR or CUDA enabled GPUs. Likely -exploits the observation that while image processing and statistical learning -kernels must be written generically to handle any matrix datatype, at runtime -they tend to be executed repeatedly on the same type. Likely also seeks to -explore new optimizations for statistical learning algorithms by moving them -from an offline model generation step to a compile-time simplification of a -function (the learning algorithm) with constant arguments (the training set). +projects that have already been updated to work with LLVM 3.6. + +* A project Additional Information diff --git a/docs/SourceLevelDebugging.rst b/docs/SourceLevelDebugging.rst index 869d3a3..3a5fa6e 100644 --- a/docs/SourceLevelDebugging.rst +++ b/docs/SourceLevelDebugging.rst @@ -186,11 +186,15 @@ the simple data types ``i32``, ``i1``, ``float``, ``double``, ``mdstring`` and ... } -The first field of a descriptor is always an -``i32`` containing a tag value identifying the content of the descriptor. -The remaining fields are specific to the descriptor. The values of tags are -loosely bound to the tag values of DWARF information entries. However, that -does not restrict the use of the information supplied to DWARF targets. +Most of the string and integer fields in descriptors are packed into a single, +null-separated ``mdstring``. The first field of the header is always an +``i32`` containing the DWARF tag value identifying the content of the +descriptor. + +For clarity of definition in this document, these header fields are described +below split inside an imaginary ``DIHeader`` construct. This is invalid +assembly syntax. In valid IR, these fields are stringified and concatenated, +separated by ``\00``. The details of the various descriptors follow. @@ -200,19 +204,22 @@ Compile unit descriptors .. code-block:: llvm !0 = metadata !{ - i32, ;; Tag = 17 (DW_TAG_compile_unit) + DIHeader( + i32, ;; Tag = 17 (DW_TAG_compile_unit) + i32, ;; DWARF language identifier (ex. DW_LANG_C89) + mdstring, ;; Producer (ex. "4.0.1 LLVM (LLVM research group)") + i1, ;; True if this is optimized. + mdstring, ;; Flags + i32, ;; Runtime version + mdstring, ;; Split debug filename + i32 ;; Debug info emission kind (1 = Full Debug Info, 2 = Line Tables Only) + ), metadata, ;; Source directory (including trailing slash) & file pair - i32, ;; DWARF language identifier (ex. DW_LANG_C89) - metadata ;; Producer (ex. "4.0.1 LLVM (LLVM research group)") - i1, ;; True if this is optimized. - metadata, ;; Flags - i32 ;; Runtime version - metadata ;; List of enums types - metadata ;; List of retained types - metadata ;; List of subprograms - metadata ;; List of global variables + metadata, ;; List of enums types + metadata, ;; List of retained types + metadata, ;; List of subprograms + metadata, ;; List of global variables metadata ;; List of imported entities - metadata ;; Split debug filename } These descriptors contain a source language ID for the file (we use the DWARF @@ -235,8 +242,10 @@ File descriptors .. code-block:: llvm !0 = metadata !{ - i32, ;; Tag = 41 (DW_TAG_file_type) - metadata, ;; Source directory (including trailing slash) & file pair + DIHeader( + i32 ;; Tag = 41 (DW_TAG_file_type) + ), + metadata ;; Source directory (including trailing slash) & file pair } These descriptors contain information for a file. Global variables and top @@ -254,17 +263,18 @@ Global variable descriptors .. code-block:: llvm !1 = metadata !{ - i32, ;; Tag = 52 (DW_TAG_variable) - i32, ;; Unused field. + DIHeader( + i32, ;; Tag = 52 (DW_TAG_variable) + mdstring, ;; Name + mdstring, ;; Display name (fully qualified C++ name) + mdstring, ;; MIPS linkage name (for C++) + i32, ;; Line number where defined + i1, ;; True if the global is local to compile unit (static) + i1 ;; True if the global is defined in the compile unit (not extern) + ), metadata, ;; Reference to context descriptor - metadata, ;; Name - metadata, ;; Display name (fully qualified C++ name) - metadata, ;; MIPS linkage name (for C++) metadata, ;; Reference to file where defined - i32, ;; Line number where defined metadata, ;; Reference to type descriptor - i1, ;; True if the global is local to compile unit (static) - i1, ;; True if the global is defined in the compile unit (not extern) {}*, ;; Reference to the global variable metadata, ;; The static member declaration, if any } @@ -281,27 +291,29 @@ Subprogram descriptors .. code-block:: llvm !2 = metadata !{ - i32, ;; Tag = 46 (DW_TAG_subprogram) + DIHeader( + i32, ;; Tag = 46 (DW_TAG_subprogram) + mdstring, ;; Name + mdstring, ;; Display name (fully qualified C++ name) + mdstring, ;; MIPS linkage name (for C++) + i32, ;; Line number where defined + i1, ;; True if the global is local to compile unit (static) + i1, ;; True if the global is defined in the compile unit (not extern) + i32, ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual + i32, ;; Index into a virtual function + i32, ;; Flags - Artificial, Private, Protected, Explicit, Prototyped. + i1, ;; isOptimized + i32 ;; Line number where the scope of the subprogram begins + ), metadata, ;; Source directory (including trailing slash) & file pair metadata, ;; Reference to context descriptor - metadata, ;; Name - metadata, ;; Display name (fully qualified C++ name) - metadata, ;; MIPS linkage name (for C++) - i32, ;; Line number where defined metadata, ;; Reference to type descriptor - i1, ;; True if the global is local to compile unit (static) - i1, ;; True if the global is defined in the compile unit (not extern) - i32, ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual - i32, ;; Index into a virtual function metadata, ;; indicates which base type contains the vtable pointer for the ;; derived class - i32, ;; Flags - Artificial, Private, Protected, Explicit, Prototyped. - i1, ;; isOptimized {}*, ;; Reference to the LLVM function metadata, ;; Lists function template parameters metadata, ;; Function declaration descriptor - metadata, ;; List of function variables - i32 ;; Line number where the scope of the subprogram begins + metadata ;; List of function variables } These descriptors provide debug information about functions, methods and @@ -314,13 +326,14 @@ Block descriptors .. code-block:: llvm !3 = metadata !{ - i32, ;; Tag = 11 (DW_TAG_lexical_block) + DIHeader( + i32, ;; Tag = 11 (DW_TAG_lexical_block) + i32, ;; Line number + i32, ;; Column number + i32 ;; Unique ID to identify blocks from a template function + ), metadata, ;; Source directory (including trailing slash) & file pair - metadata, ;; Reference to context descriptor - i32, ;; Line number - i32, ;; Column number - i32, ;; DWARF path discriminator value - i32 ;; Unique ID to identify blocks from a template function + metadata ;; Reference to context descriptor } This descriptor provides debug information about nested blocks within a @@ -330,7 +343,10 @@ lexical blocks at same depth. .. code-block:: llvm !3 = metadata !{ - i32, ;; Tag = 11 (DW_TAG_lexical_block) + DIHeader( + i32, ;; Tag = 11 (DW_TAG_lexical_block) + i32 ;; DWARF path discriminator value + ), metadata, ;; Source directory (including trailing slash) & file pair metadata ;; Reference to the scope we're annotating with a file change } @@ -346,16 +362,18 @@ Basic type descriptors .. code-block:: llvm !4 = metadata !{ - i32, ;; Tag = 36 (DW_TAG_base_type) + DIHeader( + i32, ;; Tag = 36 (DW_TAG_base_type) + mdstring, ;; Name (may be "" for anonymous types) + i32, ;; Line number where defined (may be 0) + i64, ;; Size in bits + i64, ;; Alignment in bits + i64, ;; Offset in bits + i32, ;; Flags + i32 ;; DWARF type encoding + ), metadata, ;; Source directory (including trailing slash) & file pair (may be null) - metadata, ;; Reference to context - metadata, ;; Name (may be "" for anonymous types) - i32, ;; Line number where defined (may be 0) - i64, ;; Size in bits - i64, ;; Alignment in bits - i64, ;; Offset in bits - i32, ;; Flags - i32 ;; DWARF type encoding + metadata ;; Reference to context } These descriptors define primitive types used in the code. Example ``int``, @@ -389,22 +407,19 @@ Derived type descriptors .. code-block:: llvm !5 = metadata !{ - i32, ;; Tag (see below) + DIHeader( + i32, ;; Tag (see below) + mdstring, ;; Name (may be "" for anonymous types) + i32, ;; Line number where defined (may be 0) + i64, ;; Size in bits + i64, ;; Alignment in bits + i64, ;; Offset in bits + i32 ;; Flags to encode attributes, e.g. private + ), metadata, ;; Source directory (including trailing slash) & file pair (may be null) metadata, ;; Reference to context - metadata, ;; Name (may be "" for anonymous types) - i32, ;; Line number where defined (may be 0) - i64, ;; Size in bits - i64, ;; Alignment in bits - i64, ;; Offset in bits - i32, ;; Flags to encode attributes, e.g. private metadata, ;; Reference to type derived from - metadata, ;; (optional) Name of the Objective C property associated with - ;; Objective-C an ivar, or the type of which this - ;; pointer-to-member is pointing to members of. - metadata, ;; (optional) Name of the Objective C property getter selector. - metadata, ;; (optional) Name of the Objective C property setter selector. - i32 ;; (optional) Objective C property attributes. + metadata ;; (optional) Objective C property node } These descriptors are used to define types derived from other types. The value @@ -452,21 +467,23 @@ Composite type descriptors .. code-block:: llvm !6 = metadata !{ - i32, ;; Tag (see below) + DIHeader( + i32, ;; Tag (see below) + mdstring, ;; Name (may be "" for anonymous types) + i32, ;; Line number where defined (may be 0) + i64, ;; Size in bits + i64, ;; Alignment in bits + i64, ;; Offset in bits + i32, ;; Flags + i32 ;; Runtime languages + ), metadata, ;; Source directory (including trailing slash) & file pair (may be null) metadata, ;; Reference to context - metadata, ;; Name (may be "" for anonymous types) - i32, ;; Line number where defined (may be 0) - i64, ;; Size in bits - i64, ;; Alignment in bits - i64, ;; Offset in bits - i32, ;; Flags metadata, ;; Reference to type derived from metadata, ;; Reference to array of member descriptors - i32, ;; Runtime languages metadata, ;; Base type containing the vtable pointer for this type metadata, ;; Template parameters - metadata ;; A unique identifier for type uniquing purpose (may be null) + mdstring ;; A unique identifier for type uniquing purpose (may be null) } These descriptors are used to define types that are composed of 0 or more @@ -528,9 +545,11 @@ Subrange descriptors .. code-block:: llvm !42 = metadata !{ - i32, ;; Tag = 33 (DW_TAG_subrange_type) - i64, ;; Low value - i64 ;; High value + DIHeader( + i32, ;; Tag = 33 (DW_TAG_subrange_type) + i64, ;; Low value + i64 ;; High value + ) } These descriptors are used to define ranges of array subscripts for an array @@ -547,9 +566,11 @@ Enumerator descriptors .. code-block:: llvm !6 = metadata !{ - i32, ;; Tag = 40 (DW_TAG_enumerator) - metadata, ;; Name - i64 ;; Value + DIHeader( + i32, ;; Tag = 40 (DW_TAG_enumerator) + mdstring, ;; Name + i64 ;; Value + ) } These descriptors are used to define members of an enumeration :ref:`composite @@ -561,16 +582,17 @@ Local variables .. code-block:: llvm !7 = metadata !{ - i32, ;; Tag (see below) + DIHeader( + i32, ;; Tag (see below) + mdstring, ;; Name + i32, ;; 24 bit - Line number where defined + ;; 8 bit - Argument number. 1 indicates 1st argument. + i32 ;; flags + ), metadata, ;; Context - metadata, ;; Name metadata, ;; Reference to file where defined - i32, ;; 24 bit - Line number where defined - ;; 8 bit - Argument number. 1 indicates 1st argument. metadata, ;; Reference to the type descriptor - i32, ;; flags metadata ;; (optional) Reference to inline location - metadata ;; (optional) Reference to a complex expression (see below) } These descriptors are used to define variables local to a sub program. The @@ -589,6 +611,25 @@ The context is either the subprogram or block where the variable is defined. Name the source variable name. Context and line indicate where the variable was defined. Type descriptor defines the declared type of the variable. +Complex Expressions +^^^^^^^^^^^^^^^^^^^ +.. code-block:: llvm + + !8 = metadata !{ + i32, ;; DW_TAG_expression + ... + } + +Complex expressions describe variable storage locations in terms of +prefix-notated DWARF expressions. Currently the only supported +operators are ``DW_OP_plus``, ``DW_OP_deref``, and ``DW_OP_piece``. + +The ``DW_OP_piece`` operator is used for (typically larger aggregate) +variables that are fragmented across several locations. It takes two +i32 arguments, an offset and a size in bytes to describe which piece +of the variable is at this location. + + .. _format_common_intrinsics: Debugger intrinsic functions @@ -726,8 +767,7 @@ Compiled to LLVM, this function would be represented like this: !15 = metadata !{i32 786688, metadata !16, metadata !"Z", metadata !5, i32 5, metadata !11, i32 0, i32 0} ; [ DW_TAG_auto_variable ] [Z] \ [line 5] - !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0, - i32 0} \ + !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0} \ ; [ DW_TAG_lexical_block ] [/private/tmp/t.c] !17 = metadata !{i32 5, i32 0, metadata !16, null} !18 = metadata !{i32 6, i32 0, metadata !16, null} @@ -779,8 +819,7 @@ scope information for the variable ``Z``. .. code-block:: llvm - !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0, - i32 0} + !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 4, i32 0, i32 0} \ ; [ DW_TAG_lexical_block ] [/private/tmp/t.c] !17 = metadata !{i32 5, i32 0, metadata !16, null} @@ -810,73 +849,15 @@ to provide completely different forms if they don't fit into the DWARF model. As support for debugging information gets added to the various LLVM source-language front-ends, the information used should be documented here. -The following sections provide examples of various C/C++ constructs and the -debug information that would best describe those constructs. +The following sections provide examples of a few C/C++ constructs and the debug +information that would best describe those constructs. The canonical +references are the ``DIDescriptor`` classes defined in +``include/llvm/IR/DebugInfo.h`` and the implementations of the helper functions +in ``lib/IR/DIBuilder.cpp``. C/C++ source file information ----------------------------- -Given the source files ``MySource.cpp`` and ``MyHeader.h`` located in the -directory ``/Users/mine/sources``, the following code: - -.. code-block:: c - - #include "MyHeader.h" - - int main(int argc, char *argv[]) { - return 0; - } - -a C/C++ front-end would generate the following descriptors: - -.. code-block:: llvm - - ... - ;; - ;; Define the compile unit for the main source file "/Users/mine/sources/MySource.cpp". - ;; - !0 = metadata !{ - i32 786449, ;; Tag - metadata !1, ;; File/directory name - i32 4, ;; Language Id - metadata !"clang version 3.4 ", - i1 false, ;; Optimized compile unit - metadata !"", ;; Compiler flags - i32 0, ;; Runtime version - metadata !2, ;; Enumeration types - metadata !2, ;; Retained types - metadata !3, ;; Subprograms - metadata !2, ;; Global variables - metadata !2, ;; Imported entities (declarations and namespaces) - metadata !"" ;; Split debug filename - } - - ;; - ;; Define the file for the file "/Users/mine/sources/MySource.cpp". - ;; - !1 = metadata !{ - metadata !"MySource.cpp", - metadata !"/Users/mine/sources" - } - !5 = metadata !{ - i32 786473, ;; Tag - metadata !1 - } - - ;; - ;; Define the file for the file "/Users/mine/sources/Myheader.h" - ;; - !14 = metadata !{ - i32 786473, ;; Tag - metadata !15 - } - !15 = metadata !{ - metadata !"./MyHeader.h", - metadata !"/Users/mine/sources", - } - - ... - ``llvm::Instruction`` provides easy access to metadata attached with an instruction. One can extract line number information encoded in LLVM IR using ``Instruction::getMetadata()`` and ``DILocation::getLineNumber()``. @@ -906,7 +887,7 @@ a C/C++ front-end would generate the following descriptors: ;; ;; Define the global itself. ;; - %MyGlobal = global int 100 + @MyGlobal = global i32 100, align 4 ... ;; ;; List of debug info of globals @@ -915,24 +896,35 @@ a C/C++ front-end would generate the following descriptors: ;; Define the compile unit. !0 = metadata !{ - i32 786449, ;; Tag - i32 0, ;; Context - i32 4, ;; Language - metadata !"foo.cpp", ;; File - metadata !"/Volumes/Data/tmp", ;; Directory - metadata !"clang version 3.1 ", ;; Producer - i1 true, ;; Deprecated field - i1 false, ;; "isOptimized"? - metadata !"", ;; Flags - i32 0, ;; Runtime Version - metadata !1, ;; Enum Types - metadata !1, ;; Retained Types - metadata !1, ;; Subprograms - metadata !3, ;; Global Variables - metadata !1, ;; Imported entities - "", ;; Split debug filename + ; Header( + ; i32 17, ;; Tag + ; i32 0, ;; Context + ; i32 4, ;; Language + ; metadata !"clang version 3.6.0 ", ;; Producer + ; i1 false, ;; "isOptimized"? + ; metadata !"", ;; Flags + ; i32 0, ;; Runtime Version + ; "", ;; Split debug filename + ; 1 ;; Full debug info + ; ) + metadata !"0x11\0012\00clang version 3.6.0 \000\00\000\00\001", + metadata !1, ;; File + metadata !2, ;; Enum Types + metadata !2, ;; Retained Types + metadata !2, ;; Subprograms + metadata !3, ;; Global Variables + metadata !2 ;; Imported entities } ; [ DW_TAG_compile_unit ] + ;; The file/directory pair. + !1 = metadata !{ + metadata !"foo.c", ;; Filename + metadata !"/Users/dexonsmith/data/llvm/debug-info" ;; Directory + } + + ;; An empty array. + !2 = metadata !{} + ;; The Array of Global Variables !3 = metadata !{ metadata !4 @@ -942,17 +934,19 @@ a C/C++ front-end would generate the following descriptors: ;; Define the global variable itself. ;; !4 = metadata !{ - i32 786484, ;; Tag - i32 0, ;; Unused + ; Header( + ; i32 52, ;; Tag + ; metadata !"MyGlobal", ;; Name + ; metadata !"MyGlobal", ;; Display Name + ; metadata !"", ;; Linkage Name + ; i32 1, ;; Line + ; i32 0, ;; IsLocalToUnit + ; i32 1 ;; IsDefinition + ; ) + metadata !"0x34\00MyGlobal\00MyGlobal\00\001\000\001", null, ;; Unused - metadata !"MyGlobal", ;; Name - metadata !"MyGlobal", ;; Display Name - metadata !"", ;; Linkage Name - metadata !6, ;; File - i32 1, ;; Line - metadata !7, ;; Type - i32 0, ;; IsLocalToUnit - i32 1, ;; IsDefinition + metadata !5, ;; File + metadata !6, ;; Type i32* @MyGlobal, ;; LLVM-IR Value null ;; Static member declaration } ; [ DW_TAG_variable ] @@ -961,28 +955,30 @@ a C/C++ front-end would generate the following descriptors: ;; Define the file ;; !5 = metadata !{ - metadata !"foo.cpp", ;; File - metadata !"/Volumes/Data/tmp", ;; Directory - } - !6 = metadata !{ - i32 786473, ;; Tag - metadata !5 ;; Unused + ; Header( + ; i32 41 ;; Tag + ; ) + metadata !"0x29", + metadata !1 ;; File/directory pair } ; [ DW_TAG_file_type ] ;; ;; Define the type ;; - !7 = metadata !{ - i32 786468, ;; Tag - null, ;; Unused - null, ;; Unused - metadata !"int", ;; Name - i32 0, ;; Line - i64 32, ;; Size in Bits - i64 32, ;; Align in Bits - i64 0, ;; Offset - i32 0, ;; Flags - i32 5 ;; Encoding + !6 = metadata !{ + ; Header( + ; i32 36, ;; Tag + ; metadata !"int", ;; Name + ; i32 0, ;; Line + ; i64 32, ;; Size in Bits + ; i64 32, ;; Align in Bits + ; i64 0, ;; Offset + ; i32 0, ;; Flags + ; i32 5 ;; Encoding + ; ) + metadata !"0x24\00int\000\0032\0032\000\000\005", + null, ;; Unused + null ;; Unused } ; [ DW_TAG_base_type ] C/C++ function information @@ -1004,26 +1000,31 @@ a C/C++ front-end would generate the following descriptors: ;; Define the anchor for subprograms. ;; !6 = metadata !{ - i32 786484, ;; Tag - metadata !1, ;; File - metadata !1, ;; Context - metadata !"main", ;; Name - metadata !"main", ;; Display name - metadata !"main", ;; Linkage name - i32 1, ;; Line number - metadata !4, ;; Type - i1 false, ;; Is local - i1 true, ;; Is definition - i32 0, ;; Virtuality attribute, e.g. pure virtual function - i32 0, ;; Index into virtual table for C++ methods - i32 0, ;; Type that holds virtual table. - i32 0, ;; Flags - i1 false, ;; True if this function is optimized - Function *, ;; Pointer to llvm::Function - null, ;; Function template parameters - null, ;; List of function variables (emitted when optimizing) - 1 ;; Line number of the opening '{' of the function + ; Header( + ; i32 46, ;; Tag + ; metadata !"main", ;; Name + ; metadata !"main", ;; Display name + ; metadata !"", ;; Linkage name + ; i32 1, ;; Line number + ; i1 false, ;; Is local + ; i1 true, ;; Is definition + ; i32 0, ;; Virtuality attribute, e.g. pure virtual function + ; i32 0, ;; Index into virtual table for C++ methods + ; i32 256, ;; Flags + ; i1 0, ;; True if this function is optimized + ; 1 ;; Line number of the opening '{' of the function + ; ) + metadata !"0x2e\00main\00main\00\001\000\001\000\000\00256\000\001", + metadata !1, ;; File + metadata !5, ;; Context + metadata !6, ;; Type + null, ;; Containing type + i32 (i32, i8**)* @main, ;; Pointer to llvm::Function + null, ;; Function template parameters + null, ;; Function declaration + metadata !2 ;; List of function variables (emitted when optimizing) } + ;; ;; Define the subprogram itself. ;; @@ -1031,443 +1032,6 @@ a C/C++ front-end would generate the following descriptors: ... } -C/C++ basic types ------------------ - -The following are the basic type descriptors for C/C++ core types: - -bool -^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"bool", ;; Name - i32 0, ;; Line number - i64 8, ;; Size in Bits - i64 8, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 2 ;; Encoding - } - -char -^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"char", ;; Name - i32 0, ;; Line number - i64 8, ;; Size in Bits - i64 8, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 6 ;; Encoding - } - -unsigned char -^^^^^^^^^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"unsigned char", - i32 0, ;; Line number - i64 8, ;; Size in Bits - i64 8, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 8 ;; Encoding - } - -short -^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"short int", - i32 0, ;; Line number - i64 16, ;; Size in Bits - i64 16, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 5 ;; Encoding - } - -unsigned short -^^^^^^^^^^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"short unsigned int", - i32 0, ;; Line number - i64 16, ;; Size in Bits - i64 16, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 7 ;; Encoding - } - -int -^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"int", ;; Name - i32 0, ;; Line number - i64 32, ;; Size in Bits - i64 32, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 5 ;; Encoding - } - -unsigned int -^^^^^^^^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"unsigned int", - i32 0, ;; Line number - i64 32, ;; Size in Bits - i64 32, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 7 ;; Encoding - } - -long long -^^^^^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"long long int", - i32 0, ;; Line number - i64 64, ;; Size in Bits - i64 64, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 5 ;; Encoding - } - -unsigned long long -^^^^^^^^^^^^^^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"long long unsigned int", - i32 0, ;; Line number - i64 64, ;; Size in Bits - i64 64, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 7 ;; Encoding - } - -float -^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"float", - i32 0, ;; Line number - i64 32, ;; Size in Bits - i64 32, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 4 ;; Encoding - } - -double -^^^^^^ - -.. code-block:: llvm - - !2 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"double",;; Name - i32 0, ;; Line number - i64 64, ;; Size in Bits - i64 64, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 4 ;; Encoding - } - -C/C++ derived types -------------------- - -Given the following as an example of C/C++ derived type: - -.. code-block:: c - - typedef const int *IntPtr; - -a C/C++ front-end would generate the following descriptors: - -.. code-block:: llvm - - ;; - ;; Define the typedef "IntPtr". - ;; - !2 = metadata !{ - i32 786454, ;; Tag - metadata !3, ;; File - metadata !1, ;; Context - metadata !"IntPtr", ;; Name - i32 0, ;; Line number - i64 0, ;; Size in bits - i64 0, ;; Align in bits - i64 0, ;; Offset in bits - i32 0, ;; Flags - metadata !4 ;; Derived From type - } - ;; - ;; Define the pointer type. - ;; - !4 = metadata !{ - i32 786447, ;; Tag - null, ;; File - null, ;; Context - metadata !"", ;; Name - i32 0, ;; Line number - i64 64, ;; Size in bits - i64 64, ;; Align in bits - i64 0, ;; Offset in bits - i32 0, ;; Flags - metadata !5 ;; Derived From type - } - ;; - ;; Define the const type. - ;; - !5 = metadata !{ - i32 786470, ;; Tag - null, ;; File - null, ;; Context - metadata !"", ;; Name - i32 0, ;; Line number - i64 0, ;; Size in bits - i64 0, ;; Align in bits - i64 0, ;; Offset in bits - i32 0, ;; Flags - metadata !6 ;; Derived From type - } - ;; - ;; Define the int type. - ;; - !6 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"int", ;; Name - i32 0, ;; Line number - i64 32, ;; Size in bits - i64 32, ;; Align in bits - i64 0, ;; Offset in bits - i32 0, ;; Flags - i32 5 ;; Encoding - } - -C/C++ struct/union types ------------------------- - -Given the following as an example of C/C++ struct type: - -.. code-block:: c - - struct Color { - unsigned Red; - unsigned Green; - unsigned Blue; - }; - -a C/C++ front-end would generate the following descriptors: - -.. code-block:: llvm - - ;; - ;; Define basic type for unsigned int. - ;; - !5 = metadata !{ - i32 786468, ;; Tag - null, ;; File - null, ;; Context - metadata !"unsigned int", - i32 0, ;; Line number - i64 32, ;; Size in Bits - i64 32, ;; Align in Bits - i64 0, ;; Offset in Bits - i32 0, ;; Flags - i32 7 ;; Encoding - } - ;; - ;; Define composite type for struct Color. - ;; - !2 = metadata !{ - i32 786451, ;; Tag - metadata !1, ;; Compile unit - null, ;; Context - metadata !"Color", ;; Name - i32 1, ;; Line number - i64 96, ;; Size in bits - i64 32, ;; Align in bits - i64 0, ;; Offset in bits - i32 0, ;; Flags - null, ;; Derived From - metadata !3, ;; Elements - i32 0, ;; Runtime Language - null, ;; Base type containing the vtable pointer for this type - null ;; Template parameters - } - - ;; - ;; Define the Red field. - ;; - !4 = metadata !{ - i32 786445, ;; Tag - metadata !1, ;; File - metadata !1, ;; Context - metadata !"Red", ;; Name - i32 2, ;; Line number - i64 32, ;; Size in bits - i64 32, ;; Align in bits - i64 0, ;; Offset in bits - i32 0, ;; Flags - metadata !5 ;; Derived From type - } - - ;; - ;; Define the Green field. - ;; - !6 = metadata !{ - i32 786445, ;; Tag - metadata !1, ;; File - metadata !1, ;; Context - metadata !"Green", ;; Name - i32 3, ;; Line number - i64 32, ;; Size in bits - i64 32, ;; Align in bits - i64 32, ;; Offset in bits - i32 0, ;; Flags - metadata !5 ;; Derived From type - } - - ;; - ;; Define the Blue field. - ;; - !7 = metadata !{ - i32 786445, ;; Tag - metadata !1, ;; File - metadata !1, ;; Context - metadata !"Blue", ;; Name - i32 4, ;; Line number - i64 32, ;; Size in bits - i64 32, ;; Align in bits - i64 64, ;; Offset in bits - i32 0, ;; Flags - metadata !5 ;; Derived From type - } - - ;; - ;; Define the array of fields used by the composite type Color. - ;; - !3 = metadata !{metadata !4, metadata !6, metadata !7} - -C/C++ enumeration types ------------------------ - -Given the following as an example of C/C++ enumeration type: - -.. code-block:: c - - enum Trees { - Spruce = 100, - Oak = 200, - Maple = 300 - }; - -a C/C++ front-end would generate the following descriptors: - -.. code-block:: llvm - - ;; - ;; Define composite type for enum Trees - ;; - !2 = metadata !{ - i32 786436, ;; Tag - metadata !1, ;; File - metadata !1, ;; Context - metadata !"Trees", ;; Name - i32 1, ;; Line number - i64 32, ;; Size in bits - i64 32, ;; Align in bits - i64 0, ;; Offset in bits - i32 0, ;; Flags - null, ;; Derived From type - metadata !3, ;; Elements - i32 0 ;; Runtime language - } - - ;; - ;; Define the array of enumerators used by composite type Trees. - ;; - !3 = metadata !{metadata !4, metadata !5, metadata !6} - - ;; - ;; Define Spruce enumerator. - ;; - !4 = metadata !{i32 786472, metadata !"Spruce", i64 100} - - ;; - ;; Define Oak enumerator. - ;; - !5 = metadata !{i32 786472, metadata !"Oak", i64 200} - - ;; - ;; Define Maple enumerator. - ;; - !6 = metadata !{i32 786472, metadata !"Maple", i64 300} - Debugging information format ============================ @@ -1650,21 +1214,33 @@ New DWARF Attributes New DWARF Constants ^^^^^^^^^^^^^^^^^^^ -+--------------------------------+-------+ -| Name | Value | -+================================+=======+ -| DW_AT_APPLE_PROPERTY_readonly | 0x1 | -+--------------------------------+-------+ -| DW_AT_APPLE_PROPERTY_readwrite | 0x2 | -+--------------------------------+-------+ -| DW_AT_APPLE_PROPERTY_assign | 0x4 | -+--------------------------------+-------+ -| DW_AT_APPLE_PROPERTY_retain | 0x8 | -+--------------------------------+-------+ -| DW_AT_APPLE_PROPERTY_copy | 0x10 | -+--------------------------------+-------+ -| DW_AT_APPLE_PROPERTY_nonatomic | 0x20 | -+--------------------------------+-------+ ++--------------------------------------+-------+ +| Name | Value | ++======================================+=======+ +| DW_APPLE_PROPERTY_readonly | 0x01 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_getter | 0x02 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_assign | 0x04 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_readwrite | 0x08 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_retain | 0x10 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_copy | 0x20 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_nonatomic | 0x40 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_setter | 0x80 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_atomic | 0x100 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_weak | 0x200 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_strong | 0x400 | ++--------------------------------------+-------+ +| DW_APPLE_PROPERTY_unsafe_unretained | 0x800 | ++--------------------------------+-----+-------+ Name Accelerator Tables ----------------------- diff --git a/docs/StackMaps.rst b/docs/StackMaps.rst index bd0fb94..5bb0554 100644 --- a/docs/StackMaps.rst +++ b/docs/StackMaps.rst @@ -221,6 +221,12 @@ lowered according to the calling convention specified at the intrinsic's callsite. Variants of the intrinsic with non-void return type also return a value according to calling convention. +On PowerPC, note that the ```` must be the actual intended target of +the indirect call, not the function-descriptor address normally used as the +C/C++ function-pointer representation. As a result, the call target must be +local because no adjustment or restoration of the TOC pointer (in register r2) +will be performed. + Requesting zero patch point arguments is valid. In this case, all variable operands are handled just like ``llvm.experimental.stackmap.*``. The difference is that space will diff --git a/docs/Statepoints.rst b/docs/Statepoints.rst new file mode 100644 index 0000000..53643b1 --- /dev/null +++ b/docs/Statepoints.rst @@ -0,0 +1,411 @@ +===================================== +Garbage Collection Safepoints in LLVM +===================================== + +.. contents:: + :local: + :depth: 2 + +Status +======= + +This document describes a set of experimental extensions to LLVM. Use +with caution. Because the intrinsics have experimental status, +compatibility across LLVM releases is not guaranteed. + +LLVM currently supports an alternate mechanism for conservative +garbage collection support using the gc_root intrinsic. The mechanism +described here shares little in common with the alternate +implementation and it is hoped that this mechanism will eventually +replace the gc_root mechanism. + +Overview +======== + +To collect dead objects, garbage collectors must be able to identify +any references to objects contained within executing code, and, +depending on the collector, potentially update them. The collector +does not need this information at all points in code - that would make +the problem much harder - but only at well-defined points in the +execution known as 'safepoints' For most collectors, it is sufficient +to track at least one copy of each unique pointer value. However, for +a collector which wishes to relocate objects directly reachable from +running code, a higher standard is required. + +One additional challenge is that the compiler may compute intermediate +results ("derived pointers") which point outside of the allocation or +even into the middle of another allocation. The eventual use of this +intermediate value must yield an address within the bounds of the +allocation, but such "exterior derived pointers" may be visible to the +collector. Given this, a garbage collector can not safely rely on the +runtime value of an address to indicate the object it is associated +with. If the garbage collector wishes to move any object, the +compiler must provide a mapping, for each pointer, to an indication of +its allocation. + +To simplify the interaction between a collector and the compiled code, +most garbage collectors are organized in terms of three abstractions: +load barriers, store barriers, and safepoints. + +#. A load barrier is a bit of code executed immediately after the + machine load instruction, but before any use of the value loaded. + Depending on the collector, such a barrier may be needed for all + loads, merely loads of a particular type (in the original source + language), or none at all. + +#. Analogously, a store barrier is a code fragement that runs + immediately before the machine store instruction, but after the + computation of the value stored. The most common use of a store + barrier is to update a 'card table' in a generational garbage + collector. + +#. A safepoint is a location at which pointers visible to the compiled + code (i.e. currently in registers or on the stack) are allowed to + change. After the safepoint completes, the actual pointer value + may differ, but the 'object' (as seen by the source language) + pointed to will not. + + Note that the term 'safepoint' is somewhat overloaded. It refers to + both the location at which the machine state is parsable and the + coordination protocol involved in bring application threads to a + point at which the collector can safely use that information. The + term "statepoint" as used in this document refers exclusively to the + former. + +This document focuses on the last item - compiler support for +safepoints in generated code. We will assume that an outside +mechanism has decided where to place safepoints. From our +perspective, all safepoints will be function calls. To support +relocation of objects directly reachable from values in compiled code, +the collector must be able to: + +#. identify every copy of a pointer (including copies introduced by + the compiler itself) at the safepoint, +#. identify which object each pointer relates to, and +#. potentially update each of those copies. + +This document describes the mechanism by which an LLVM based compiler +can provide this information to a language runtime/collector, and +ensure that all pointers can be read and updated if desired. The +heart of the approach is to construct (or rewrite) the IR in a manner +where the possible updates performed by the garbage collector are +explicitly visible in the IR. Doing so requires that we: + +#. create a new SSA value for each potentially relocated pointer, and + ensure that no uses of the original (non relocated) value is + reachable after the safepoint, +#. specify the relocation in a way which is opaque to the compiler to + ensure that the optimizer can not introduce new uses of an + unrelocated value after a statepoint. This prevents the optimizer + from performing unsound optimizations. +#. recording a mapping of live pointers (and the allocation they're + associated with) for each statepoint. + +At the most abstract level, inserting a safepoint can be thought of as +replacing a call instruction with a call to a multiple return value +function which both calls the original target of the call, returns +it's result, and returns updated values for any live pointers to +garbage collected objects. + + Note that the task of identifying all live pointers to garbage + collected values, transforming the IR to expose a pointer giving the + base object for every such live pointer, and inserting all the + intrinsics correctly is explicitly out of scope for this document. + The recommended approach is described in the section of Late + Safepoint Placement below. + +This abstract function call is concretely represented by a sequence of +intrinsic calls known as a 'statepoint sequence'. + + +Let's consider a simple call in LLVM IR: + todo + +Depending on our language we may need to allow a safepoint during the +execution of the function called from this site. If so, we need to +let the collector update local values in the current frame. + +Let's say we need to relocate SSA values 'a', 'b', and 'c' at this +safepoint. To represent this, we would generate the statepoint +sequence: + + todo + +Ideally, this sequence would have been represented as a M argument, N +return value function (where M is the number of values being +relocated + the original call arguments and N is the original return +value + each relocated value), but LLVM does not easily support such a +representation. + +Instead, the statepoint intrinsic marks the actual site of the +safepoint or statepoint. The statepoint returns a token value (which +exists only at compile time). To get back the original return value +of the call, we use the 'gc.result' intrinsic. To get the relocation +of each pointer in turn, we use the 'gc.relocate' intrinsic with the +appropriate index. Note that both the gc.relocate and gc.result are +tied to the statepoint. The combination forms a "statepoint sequence" +and represents the entitety of a parseable call or 'statepoint'. + +When lowered, this example would generate the following x86 assembly:: + put assembly here + +Each of the potentially relocated values has been spilled to the +stack, and a record of that location has been recorded to the +:ref:`Stack Map section `. If the garbage collector +needs to update any of these pointers during the call, it knows +exactly what to change. + +Intrinsics +=========== + +'''gc.statepoint''' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare i32 + @gc.statepoint(func_type , i64 <#call args>. + i64 , ... (call parameters), + i64 <# deopt args>, ... (deopt parameters), + ... (gc parameters)) + +Overview: +""""""""" + +The statepoint intrinsic represents a call which is parse-able by the +runtime. + +Operands: +""""""""" + +The 'target' operand is the function actually being called. The +target can be specified as either a symbolic LLVM function, or as an +arbitrary Value of appropriate function type. Note that the function +type must match the signature of the callee and the types of the 'call +parameters' arguments. + +The '#call args' operand is the number of arguments to the actual +call. It must exactly match the number of arguments passed in the +'call parameters' variable length section. + +The 'unused' operand is unused and likely to be removed. Please do +not use. + +The 'call parameters' arguments are simply the arguments which need to +be passed to the call target. They will be lowered according to the +specified calling convention and otherwise handled like a normal call +instruction. The number of arguments must exactly match what is +specified in '# call args'. The types must match the signature of +'target'. + +The 'deopt parameters' arguments contain an arbitrary list of Values +which is meaningful to the runtime. The runtime may read any of these +values, but is assumed not to modify them. If the garbage collector +might need to modify one of these values, it must also be listed in +the 'gc pointer' argument list. The '# deopt args' field indicates +how many operands are to be interpreted as 'deopt parameters'. + +The 'gc parameters' arguments contain every pointer to a garbage +collector object which potentially needs to be updated by the garbage +collector. Note that the argument list must explicitly contain a base +pointer for every derived pointer listed. The order of arguments is +unimportant. Unlike the other variable length parameter sets, this +list is not length prefixed. + +Semantics: +"""""""""" + +A statepoint is assumed to read and write all memory. As a result, +memory operations can not be reordered past a statepoint. It is +illegal to mark a statepoint as being either 'readonly' or 'readnone'. + +Note that legal IR can not perform any memory operation on a 'gc +pointer' argument of the statepoint in a location statically reachable +from the statepoint. Instead, the explicitly relocated value (from a +''gc.relocate'') must be used. + +'''gc.result''' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare type* + @gc.result_ptr(i32 %statepoint_token) + + declare fX + @gc.result_float(i32 %statepoint_token) + + declare iX + @gc.result_int(i32 %statepoint_token) + +Overview: +""""""""" + +'''gc.result''' extracts the result of the original call instruction +which was replaced by the '''gc.statepoint'''. The '''gc.result''' +intrinsic is actually a family of three intrinsics due to an +implementation limitation. Other than the type of the return value, +the semantics are the same. + +Operands: +""""""""" + +The first and only argument is the '''gc.statepoint''' which starts +the safepoint sequence of which this '''gc.result'' is a part. +Despite the typing of this as a generic i32, *only* the value defined +by a '''gc.statepoint''' is legal here. + +Semantics: +"""""""""" + +The ''gc.result'' represents the return value of the call target of +the ''statepoint''. The type of the ''gc.result'' must exactly match +the type of the target. If the call target returns void, there will +be no ''gc.result''. + +A ''gc.result'' is modeled as a 'readnone' pure function. It has no +side effects since it is just a projection of the return value of the +previous call represented by the ''gc.statepoint''. + +'''gc.relocate''' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare addrspace(1)* + @gc.relocate(i32 %statepoint_token, i32 %base_offset, i32 %pointer_offset) + +Overview: +""""""""" + +A ''gc.relocate'' returns the potentially relocated value of a pointer +at the safepoint. + +Operands: +""""""""" + +The first argument is the '''gc.statepoint''' which starts the +safepoint sequence of which this '''gc.relocation'' is a part. +Despite the typing of this as a generic i32, *only* the value defined +by a '''gc.statepoint''' is legal here. + +The second argument is an index into the statepoints list of arguments +which specifies the base pointer for the pointer being relocated. +This index must land within the 'gc parameter' section of the +statepoint's argument list. + +The third argument is an index into the statepoint's list of arguments +which specify the (potentially) derived pointer being relocated. It +is legal for this index to be the same as the second argument +if-and-only-if a base pointer is being relocated. This index must land +within the 'gc parameter' section of the statepoint's argument list. + +Semantics: +"""""""""" + +The return value of ''gc.relocate'' is the potentially relocated value +of the pointer specified by it's arguments. It is unspecified how the +value of the returned pointer relates to the argument to the +''gc.statepoint'' other than that a) it points to the same source +language object with the same offset, and b) the 'based-on' +relationship of the newly relocated pointers is a projection of the +unrelocated pointers. In particular, the integer value of the pointer +returned is unspecified. + +A ''gc.relocate'' is modeled as a 'readnone' pure function. It has no +side effects since it is just a way to extract information about work +done during the actual call modeled by the ''gc.statepoint''. + + +Stack Map Format +================ + +Locations for each pointer value which may need read and/or updated by +the runtime or collector are provided via the :ref:`Stack Map format +` specified in the PatchPoint documentation. + +Each statepoint generates the following Locations: + +* Constant which describes number of following deopt *Locations* (not + operands) +* Variable number of Locations, one for each deopt parameter listed in + the IR statepoint (same number as described by previous Constant) +* Variable number of Locations pairs, one pair for each unique pointer + which needs relocated. The first Location in each pair describes + the base pointer for the object. The second is the derived pointer + actually being relocated. It is guaranteed that the base pointer + must also appear explicitly as a relocation pair if used after the + statepoint. There may be fewer pairs then gc parameters in the IR + statepoint. Each *unique* pair will occur at least once; duplicates + are possible. + +Note that the Locations used in each section may describe the same +physical location. e.g. A stack slot may appear as a deopt location, +a gc base pointer, and a gc derived pointer. + +The ID field of the 'StkMapRecord' for a statepoint is meaningless and +it's value is explicitly unspecified. + +The LiveOut section of the StkMapRecord will be empty for a statepoint +record. + +Safepoint Semantics & Verification +================================== + +The fundamental correctness property for the compiled code's +correctness w.r.t. the garbage collector is a dynamic one. It must be +the case that there is no dynamic trace such that a operation +involving a potentially relocated pointer is observably-after a +safepoint which could relocate it. 'observably-after' is this usage +means that an outside observer could observe this sequence of events +in a way which precludes the operation being performed before the +safepoint. + +To understand why this 'observable-after' property is required, +consider a null comparison performed on the original copy of a +relocated pointer. Assuming that control flow follows the safepoint, +there is no way to observe externally whether the null comparison is +performed before or after the safepoint. (Remember, the original +Value is unmodified by the safepoint.) The compiler is free to make +either scheduling choice. + +The actual correctness property implemented is slightly stronger than +this. We require that there be no *static path* on which a +potentially relocated pointer is 'observably-after' it may have been +relocated. This is slightly stronger than is strictly necessary (and +thus may disallow some otherwise valid programs), but greatly +simplifies reasoning about correctness of the compiled code. + +By construction, this property will be upheld by the optimizer if +correctly established in the source IR. This is a key invariant of +the design. + +The existing IR Verifier pass has been extended to check most of the +local restrictions on the intrinsics mentioned in their respective +documentation. The current implementation in LLVM does not check the +key relocation invariant, but this is ongoing work on developing such +a verifier. Please ask on llvmdev if you're interested in +experimenting with the current version. + +Bugs and Enhancements +===================== + +Currently known bugs and enhancements under consideration can be +tracked by performing a `bugzilla search +`_ +for [Statepoint] in the summary field. When filing new bugs, please +use this tag so that interested parties see the newly filed bug. As +with most LLVM features, design discussions take place on `llvmdev +`_, and patches +should be sent to `llvm-commits +`_ for review. + diff --git a/docs/TableGen/BackEnds.rst b/docs/TableGen/BackEnds.rst index 42de41d..e8544b6 100644 --- a/docs/TableGen/BackEnds.rst +++ b/docs/TableGen/BackEnds.rst @@ -78,8 +78,7 @@ returns the (currently, 32-bit unsigned) value of the instruction. **Output**: C++ code, implementing the target's CodeEmitter class by overriding the virtual functions as ``CodeEmitter::function()``. -**Usage**: Used to include directly at the end of ``CodeEmitter.cpp``, and -with option `-mc-emitter` to be included in ``MCCodeEmitter.cpp``. +**Usage**: Used to include directly at the end of ``MCCodeEmitter.cpp``. RegisterInfo ------------ diff --git a/docs/TableGen/LangIntro.rst b/docs/TableGen/LangIntro.rst index 54d8873..85c74a5 100644 --- a/docs/TableGen/LangIntro.rst +++ b/docs/TableGen/LangIntro.rst @@ -94,7 +94,9 @@ supported include: uninitialized field ``0b1001011`` - binary integer value + binary integer value. + Note that this is sized by the number of bits given and will not be + silently extended/truncated. ``07654321`` octal integer value (indicated by a leading 0) @@ -116,8 +118,9 @@ supported include: In rare cases, TableGen is unable to deduce the element type in which case the user must specify it explicitly. -``{ a, b, c }`` - initializer for a "bits<3>" value +``{ a, b, 0b10 }`` + initializer for a "bits<4>" value. + 1-bit from "a", 1-bit from "b", 2-bits from 0b10. ``value`` value reference @@ -208,8 +211,8 @@ supported include: on string, int and bit objects. Use !cast to compare other types of objects. -``!shl(a,b)`` ``!srl(a,b)`` ``!sra(a,b)`` ``!add(a,b)`` - The usual logical and arithmetic operators. +``!shl(a,b)`` ``!srl(a,b)`` ``!sra(a,b)`` ``!add(a,b)`` ``!and(a,b)`` + The usual binary and arithmetic operators. Note that all of the values have rules specifying how they convert to values for different types. These rules allow you to assign a value like "``7``" diff --git a/docs/TableGen/LangRef.rst b/docs/TableGen/LangRef.rst index 9b074be..134afed 100644 --- a/docs/TableGen/LangRef.rst +++ b/docs/TableGen/LangRef.rst @@ -55,6 +55,10 @@ One aspect to note is that the :token:`DecimalInteger` token *includes* the ``+`` or ``-``, as opposed to having ``+`` and ``-`` be unary operators as most languages do. +Also note that :token:`BinInteger` creates a value of type ``bits`` +(where ``n`` is the number of bits). This will implicitly convert to +integers when needed. + TableGen has identifier-like tokens: .. productionlist:: @@ -92,7 +96,7 @@ wide variety of meanings: .. productionlist:: BangOperator: one of :!eq !if !head !tail !con - :!add !shl !sra !srl + :!add !shl !sra !srl !and :!cast !empty !subst !foreach !listconcat !strconcat Syntax diff --git a/docs/TableGen/index.rst b/docs/TableGen/index.rst index 0860afa..9526240 100644 --- a/docs/TableGen/index.rst +++ b/docs/TableGen/index.rst @@ -123,7 +123,6 @@ this (at the time of this writing): bit hasCtrlDep = 0; bit isNotDuplicable = 0; bit hasSideEffects = 0; - bit neverHasSideEffects = 0; InstrItinClass Itinerary = NoItinerary; string Constraints = ""; string DisableEncoding = ""; @@ -273,7 +272,7 @@ that's only useful for debugging of the TableGen files themselves. The power in TableGen is, however, to interpret the source files into an internal representation that can be generated into anything you want. -Current usage of TableGen is to create include huge files with tables that you +Current usage of TableGen is to create huge include files with tables that you can either include directly (if the output is in the language you're coding), or be used in pre-processing via macros surrounding the include of the file. @@ -292,7 +291,7 @@ Despite being very generic, TableGen has some deficiencies that have been pointed out numerous times. The common theme is that, while TableGen allows you to build Domain-Specific-Languages, the final languages that you create lack the power of other DSLs, which in turn increase considerably the size -and complecity of TableGen files. +and complexity of TableGen files. At the same time, TableGen allows you to create virtually any meaning of the basic concepts via custom-made back-ends, which can pervert the original diff --git a/docs/TestingGuide.rst b/docs/TestingGuide.rst index 481be55..3463156 100644 --- a/docs/TestingGuide.rst +++ b/docs/TestingGuide.rst @@ -22,7 +22,7 @@ Requirements ============ In order to use the LLVM testing infrastructure, you will need all of the -software required to build LLVM, as well as `Python `_ 2.5 or +software required to build LLVM, as well as `Python `_ 2.7 or later. LLVM testing infrastructure organization @@ -240,6 +240,58 @@ The recommended way to examine output to figure out if the test passes is using the :doc:`FileCheck tool `. *[The usage of grep in RUN lines is deprecated - please do not send or commit patches that use it.]* +Extra files +----------- + +If your test requires extra files besides the file containing the ``RUN:`` +lines, the idiomatic place to put them is in a subdirectory ``Inputs``. +You can then refer to the extra files as ``%S/Inputs/foo.bar``. + +For example, consider ``test/Linker/ident.ll``. The directory structure is +as follows:: + + test/ + Linker/ + ident.ll + Inputs/ + ident.a.ll + ident.b.ll + +For convenience, these are the contents: + +.. code-block:: llvm + + ;;;;; ident.ll: + + ; RUN: llvm-link %S/Inputs/ident.a.ll %S/Inputs/ident.b.ll -S | FileCheck %s + + ; Verify that multiple input llvm.ident metadata are linked together. + + ; CHECK-DAG: !llvm.ident = !{!0, !1, !2} + ; CHECK-DAG: "Compiler V1" + ; CHECK-DAG: "Compiler V2" + ; CHECK-DAG: "Compiler V3" + + ;;;;; Inputs/ident.a.ll: + + !llvm.ident = !{!0, !1} + !0 = metadata !{metadata !"Compiler V1"} + !1 = metadata !{metadata !"Compiler V2"} + + ;;;;; Inputs/ident.b.ll: + + !llvm.ident = !{!0} + !0 = metadata !{metadata !"Compiler V3"} + +For symmetry reasons, ``ident.ll`` is just a dummy file that doesn't +actually participate in the test besides holding the ``RUN:`` lines. + +.. note:: + + Some existing tests use ``RUN: true`` in extra files instead of just + putting the extra files in an ``Inputs/`` directory. This pattern is + deprecated. + Fragile tests ------------- diff --git a/docs/WritingAnLLVMBackend.rst b/docs/WritingAnLLVMBackend.rst index fb7c16f..fdadbb0 100644 --- a/docs/WritingAnLLVMBackend.rst +++ b/docs/WritingAnLLVMBackend.rst @@ -161,7 +161,7 @@ To get LLVM to actually build and link your target, you need to add it to the know about your target when parsing the ``--enable-targets`` option. Search the configure script for ``TARGETS_TO_BUILD``, add your target to the lists there (some creativity required), and then reconfigure. Alternatively, you can -change ``autotools/configure.ac`` and regenerate configure by running +change ``autoconf/configure.ac`` and regenerate configure by running ``./autoconf/AutoRegen.sh``. Target Machine diff --git a/docs/WritingAnLLVMPass.rst b/docs/WritingAnLLVMPass.rst index cfbda04..ef2b953 100644 --- a/docs/WritingAnLLVMPass.rst +++ b/docs/WritingAnLLVMPass.rst @@ -146,7 +146,7 @@ to avoid using expensive C++ runtime information. .. code-block:: c++ - virtual bool runOnFunction(Function &F) { + bool runOnFunction(Function &F) override { errs() << "Hello: "; errs().write_escaped(F.getName()) << "\n"; return false; @@ -194,7 +194,7 @@ As a whole, the ``.cpp`` file looks like: static char ID; Hello() : FunctionPass(ID) {} - virtual bool runOnFunction(Function &F) { + bool runOnFunction(Function &F) override { errs() << "Hello: "; errs().write_escaped(F.getName()) << '\n'; return false; @@ -434,9 +434,8 @@ The ``doFinalization(CallGraph &)`` method virtual bool doFinalization(CallGraph &CG); The ``doFinalization`` method is an infrequently used method that is called -when the pass framework has finished calling :ref:`runOnFunction -` for every function in the program being -compiled. +when the pass framework has finished calling :ref:`runOnSCC +` for every SCC in the program being compiled. .. _writing-an-llvm-pass-FunctionPass: @@ -456,7 +455,7 @@ To be explicit, ``FunctionPass`` subclasses are not allowed to: #. Inspect or modify a ``Function`` other than the one currently being processed. #. Add or remove ``Function``\ s from the current ``Module``. #. Add or remove global variables from the current ``Module``. -#. Maintain state across invocations of:ref:`runOnFunction +#. Maintain state across invocations of :ref:`runOnFunction ` (including global data). Implementing a ``FunctionPass`` is usually straightforward (See the :ref:`Hello @@ -1163,7 +1162,7 @@ all! To fix this, we need to add the following :ref:`getAnalysisUsage .. code-block:: c++ // We don't modify the program, so we preserve all analyses - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } diff --git a/docs/conf.py b/docs/conf.py index e061574..659c3e0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,9 +47,9 @@ copyright = u'2003-2014, LLVM Project' # built documents. # # The short X.Y version. -version = '3.5' +version = '3.6' # The full version, including alpha/beta/rc tags. -release = '3.5' +release = '3.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/index.rst b/docs/index.rst index 1d4fbd9..dd6ea18 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -199,6 +199,8 @@ For developers of applications which use LLVM as a library. (`classes `_) (`tarball `_) +`Documentation for Go bindings `_ + `ViewVC Repository Browser `_ .. @@ -235,9 +237,13 @@ For API clients and LLVM developers. WritingAnLLVMPass HowToUseAttributes NVPTXUsage + R600Usage StackMaps InAlloca BigEndianNEON + CoverageMappingFormat + Statepoints + MergeFunctions :doc:`WritingAnLLVMPass` Information on how to write LLVM transformations and analyses. @@ -316,6 +322,9 @@ For API clients and LLVM developers. :doc:`NVPTXUsage` This document describes using the NVPTX back-end to compile GPU kernels. +:doc:`R600Usage` + This document describes how to use the R600 back-end. + :doc:`StackMaps` LLVM support for mapping instruction addresses to the location of values and allowing code to be patched. @@ -324,6 +333,15 @@ For API clients and LLVM developers. LLVM's support for generating NEON instructions on big endian ARM targets is somewhat nonintuitive. This document explains the implementation and rationale. +:doc:`CoverageMappingFormat` + This describes the format and encoding used for LLVM’s code coverage mapping. + +:doc:`Statepoints` + This describes a set of experimental extensions for garbage + collection support. + +:doc:`MergeFunctions` + Describes functions merging optimization. Development Process Documentation ================================= @@ -340,6 +358,7 @@ Information about LLVM's development process. HowToReleaseLLVM Packaging ReleaseProcess + Phabricator :doc:`DeveloperPolicy` The LLVM project's policy towards developers and their contributions. @@ -361,11 +380,15 @@ Information about LLVM's development process. This is a guide to preparing LLVM releases. Most developers can ignore it. :doc:`ReleaseProcess` - This is a validate a new release, during the release process. Most developers can ignore it. + This is a guide to validate a new release, during the release process. Most developers can ignore it. :doc:`Packaging` Advice on packaging LLVM into a distribution. +:doc:`Phabricator` + Describes how to use the Phabricator code review tool hosted on + http://reviews.llvm.org/ and its command line interface, Arcanist. + Community ========= diff --git a/docs/tutorial/LangImpl3.rst b/docs/tutorial/LangImpl3.rst index 7174c09..b7418cc 100644 --- a/docs/tutorial/LangImpl3.rst +++ b/docs/tutorial/LangImpl3.rst @@ -581,7 +581,7 @@ our makefile/command line about which options to use: .. code-block:: bash # Compile - clang++ -g -O3 toy.cpp `llvm-config --cppflags --ldflags --libs core` -o toy + clang++ -g -O3 toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core` -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl4.rst b/docs/tutorial/LangImpl4.rst index 44e0cc1..cdaac63 100644 --- a/docs/tutorial/LangImpl4.rst +++ b/docs/tutorial/LangImpl4.rst @@ -428,7 +428,7 @@ the LLVM JIT and optimizer. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl5.rst b/docs/tutorial/LangImpl5.rst index ed5b652..72e34b1 100644 --- a/docs/tutorial/LangImpl5.rst +++ b/docs/tutorial/LangImpl5.rst @@ -736,7 +736,7 @@ the if/then/else and for expressions.. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl6.rst b/docs/tutorial/LangImpl6.rst index 42839fb..bf78bde 100644 --- a/docs/tutorial/LangImpl6.rst +++ b/docs/tutorial/LangImpl6.rst @@ -729,7 +729,7 @@ the if/then/else and for expressions.. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl7.rst b/docs/tutorial/LangImpl7.rst index 849ce50..141f138 100644 --- a/docs/tutorial/LangImpl7.rst +++ b/docs/tutorial/LangImpl7.rst @@ -847,7 +847,7 @@ mutable variables and var/in support. To build this example, use: .. code-block:: bash # Compile - clang++ -g toy.cpp `llvm-config --cppflags --ldflags --libs core jit native` -O3 -o toy + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy # Run ./toy diff --git a/docs/tutorial/LangImpl8.rst b/docs/tutorial/LangImpl8.rst index 6f69493..7b02468 100644 --- a/docs/tutorial/LangImpl8.rst +++ b/docs/tutorial/LangImpl8.rst @@ -1,267 +1,459 @@ -====================================================== -Kaleidoscope: Conclusion and other useful LLVM tidbits -====================================================== +======================================================= +Kaleidoscope: Extending the Language: Debug Information +======================================================= .. contents:: :local: -Tutorial Conclusion -=================== - -Welcome to the final chapter of the "`Implementing a language with -LLVM `_" tutorial. In the course of this tutorial, we have -grown our little Kaleidoscope language from being a useless toy, to -being a semi-interesting (but probably still useless) toy. :) - -It is interesting to see how far we've come, and how little code it has -taken. We built the entire lexer, parser, AST, code generator, and an -interactive run-loop (with a JIT!) by-hand in under 700 lines of -(non-comment/non-blank) code. - -Our little language supports a couple of interesting features: it -supports user defined binary and unary operators, it uses JIT -compilation for immediate evaluation, and it supports a few control flow -constructs with SSA construction. - -Part of the idea of this tutorial was to show you how easy and fun it -can be to define, build, and play with languages. Building a compiler -need not be a scary or mystical process! Now that you've seen some of -the basics, I strongly encourage you to take the code and hack on it. -For example, try adding: - -- **global variables** - While global variables have questional value - in modern software engineering, they are often useful when putting - together quick little hacks like the Kaleidoscope compiler itself. - Fortunately, our current setup makes it very easy to add global - variables: just have value lookup check to see if an unresolved - variable is in the global variable symbol table before rejecting it. - To create a new global variable, make an instance of the LLVM - ``GlobalVariable`` class. -- **typed variables** - Kaleidoscope currently only supports variables - of type double. This gives the language a very nice elegance, because - only supporting one type means that you never have to specify types. - Different languages have different ways of handling this. The easiest - way is to require the user to specify types for every variable - definition, and record the type of the variable in the symbol table - along with its Value\*. -- **arrays, structs, vectors, etc** - Once you add types, you can start - extending the type system in all sorts of interesting ways. Simple - arrays are very easy and are quite useful for many different - applications. Adding them is mostly an exercise in learning how the - LLVM `getelementptr <../LangRef.html#i_getelementptr>`_ instruction - works: it is so nifty/unconventional, it `has its own - FAQ <../GetElementPtr.html>`_! If you add support for recursive types - (e.g. linked lists), make sure to read the `section in the LLVM - Programmer's Manual <../ProgrammersManual.html#TypeResolve>`_ that - describes how to construct them. -- **standard runtime** - Our current language allows the user to access - arbitrary external functions, and we use it for things like "printd" - and "putchard". As you extend the language to add higher-level - constructs, often these constructs make the most sense if they are - lowered to calls into a language-supplied runtime. For example, if - you add hash tables to the language, it would probably make sense to - add the routines to a runtime, instead of inlining them all the way. -- **memory management** - Currently we can only access the stack in - Kaleidoscope. It would also be useful to be able to allocate heap - memory, either with calls to the standard libc malloc/free interface - or with a garbage collector. If you would like to use garbage - collection, note that LLVM fully supports `Accurate Garbage - Collection <../GarbageCollection.html>`_ including algorithms that - move objects and need to scan/update the stack. -- **debugger support** - LLVM supports generation of `DWARF Debug - info <../SourceLevelDebugging.html>`_ which is understood by common - debuggers like GDB. Adding support for debug info is fairly - straightforward. The best way to understand it is to compile some - C/C++ code with "``clang -g -O0``" and taking a look at what it - produces. -- **exception handling support** - LLVM supports generation of `zero - cost exceptions <../ExceptionHandling.html>`_ which interoperate with - code compiled in other languages. You could also generate code by - implicitly making every function return an error value and checking - it. You could also make explicit use of setjmp/longjmp. There are - many different ways to go here. -- **object orientation, generics, database access, complex numbers, - geometric programming, ...** - Really, there is no end of crazy - features that you can add to the language. -- **unusual domains** - We've been talking about applying LLVM to a - domain that many people are interested in: building a compiler for a - specific language. However, there are many other domains that can use - compiler technology that are not typically considered. For example, - LLVM has been used to implement OpenGL graphics acceleration, - translate C++ code to ActionScript, and many other cute and clever - things. Maybe you will be the first to JIT compile a regular - expression interpreter into native code with LLVM? - -Have fun - try doing something crazy and unusual. Building a language -like everyone else always has, is much less fun than trying something a -little crazy or off the wall and seeing how it turns out. If you get -stuck or want to talk about it, feel free to email the `llvmdev mailing -list `_: it has lots -of people who are interested in languages and are often willing to help -out. - -Before we end this tutorial, I want to talk about some "tips and tricks" -for generating LLVM IR. These are some of the more subtle things that -may not be obvious, but are very useful if you want to take advantage of -LLVM's capabilities. - -Properties of the LLVM IR -========================= - -We have a couple common questions about code in the LLVM IR form - lets -just get these out of the way right now, shall we? - -Target Independence -------------------- - -Kaleidoscope is an example of a "portable language": any program written -in Kaleidoscope will work the same way on any target that it runs on. -Many other languages have this property, e.g. lisp, java, haskell, -javascript, python, etc (note that while these languages are portable, -not all their libraries are). - -One nice aspect of LLVM is that it is often capable of preserving target -independence in the IR: you can take the LLVM IR for a -Kaleidoscope-compiled program and run it on any target that LLVM -supports, even emitting C code and compiling that on targets that LLVM -doesn't support natively. You can trivially tell that the Kaleidoscope -compiler generates target-independent code because it never queries for -any target-specific information when generating code. - -The fact that LLVM provides a compact, target-independent, -representation for code gets a lot of people excited. Unfortunately, -these people are usually thinking about C or a language from the C -family when they are asking questions about language portability. I say -"unfortunately", because there is really no way to make (fully general) -C code portable, other than shipping the source code around (and of -course, C source code is not actually portable in general either - ever -port a really old application from 32- to 64-bits?). - -The problem with C (again, in its full generality) is that it is heavily -laden with target specific assumptions. As one simple example, the -preprocessor often destructively removes target-independence from the -code when it processes the input text: - -.. code-block:: c - - #ifdef __i386__ - int X = 1; - #else - int X = 42; - #endif - -While it is possible to engineer more and more complex solutions to -problems like this, it cannot be solved in full generality in a way that -is better than shipping the actual source code. - -That said, there are interesting subsets of C that can be made portable. -If you are willing to fix primitive types to a fixed size (say int = -32-bits, and long = 64-bits), don't care about ABI compatibility with -existing binaries, and are willing to give up some other minor features, -you can have portable code. This can make sense for specialized domains -such as an in-kernel language. - -Safety Guarantees ------------------ - -Many of the languages above are also "safe" languages: it is impossible -for a program written in Java to corrupt its address space and crash the -process (assuming the JVM has no bugs). Safety is an interesting -property that requires a combination of language design, runtime -support, and often operating system support. - -It is certainly possible to implement a safe language in LLVM, but LLVM -IR does not itself guarantee safety. The LLVM IR allows unsafe pointer -casts, use after free bugs, buffer over-runs, and a variety of other -problems. Safety needs to be implemented as a layer on top of LLVM and, -conveniently, several groups have investigated this. Ask on the `llvmdev -mailing list `_ if -you are interested in more details. - -Language-Specific Optimizations -------------------------------- - -One thing about LLVM that turns off many people is that it does not -solve all the world's problems in one system (sorry 'world hunger', -someone else will have to solve you some other day). One specific -complaint is that people perceive LLVM as being incapable of performing -high-level language-specific optimization: LLVM "loses too much -information". - -Unfortunately, this is really not the place to give you a full and -unified version of "Chris Lattner's theory of compiler design". Instead, -I'll make a few observations: - -First, you're right that LLVM does lose information. For example, as of -this writing, there is no way to distinguish in the LLVM IR whether an -SSA-value came from a C "int" or a C "long" on an ILP32 machine (other -than debug info). Both get compiled down to an 'i32' value and the -information about what it came from is lost. The more general issue -here, is that the LLVM type system uses "structural equivalence" instead -of "name equivalence". Another place this surprises people is if you -have two types in a high-level language that have the same structure -(e.g. two different structs that have a single int field): these types -will compile down into a single LLVM type and it will be impossible to -tell what it came from. - -Second, while LLVM does lose information, LLVM is not a fixed target: we -continue to enhance and improve it in many different ways. In addition -to adding new features (LLVM did not always support exceptions or debug -info), we also extend the IR to capture important information for -optimization (e.g. whether an argument is sign or zero extended, -information about pointers aliasing, etc). Many of the enhancements are -user-driven: people want LLVM to include some specific feature, so they -go ahead and extend it. - -Third, it is *possible and easy* to add language-specific optimizations, -and you have a number of choices in how to do it. As one trivial -example, it is easy to add language-specific optimization passes that -"know" things about code compiled for a language. In the case of the C -family, there is an optimization pass that "knows" about the standard C -library functions. If you call "exit(0)" in main(), it knows that it is -safe to optimize that into "return 0;" because C specifies what the -'exit' function does. - -In addition to simple library knowledge, it is possible to embed a -variety of other language-specific information into the LLVM IR. If you -have a specific need and run into a wall, please bring the topic up on -the llvmdev list. At the very worst, you can always treat LLVM as if it -were a "dumb code generator" and implement the high-level optimizations -you desire in your front-end, on the language-specific AST. - -Tips and Tricks -=============== - -There is a variety of useful tips and tricks that you come to know after -working on/with LLVM that aren't obvious at first glance. Instead of -letting everyone rediscover them, this section talks about some of these -issues. - -Implementing portable offsetof/sizeof -------------------------------------- - -One interesting thing that comes up, if you are trying to keep the code -generated by your compiler "target independent", is that you often need -to know the size of some LLVM type or the offset of some field in an -llvm structure. For example, you might need to pass the size of a type -into a function that allocates memory. - -Unfortunately, this can vary widely across targets: for example the -width of a pointer is trivially target-specific. However, there is a -`clever way to use the getelementptr -instruction `_ -that allows you to compute this in a portable way. - -Garbage Collected Stack Frames ------------------------------- - -Some languages want to explicitly manage their stack frames, often so -that they are garbage collected or to allow easy implementation of -closures. There are often better ways to implement these features than -explicit stack frames, but `LLVM does support -them, `_ -if you want. It requires your front-end to convert the code into -`Continuation Passing -Style `_ and -the use of tail calls (which LLVM also supports). +Chapter 8 Introduction +====================== + +Welcome to Chapter 8 of the "`Implementing a language with +LLVM `_" tutorial. In chapters 1 through 7, we've built a +decent little programming language with functions and variables. +What happens if something goes wrong though, how do you debug your +program? + +Source level debugging uses formatted data that helps a debugger +translate from binary and the state of the machine back to the +source that the programmer wrote. In LLVM we generally use a format +called `DWARF `_. DWARF is a compact encoding +that represents types, source locations, and variable locations. + +The short summary of this chapter is that we'll go through the +various things you have to add to a programming language to +support debug info, and how you translate that into DWARF. + +Caveat: For now we can't debug via the JIT, so we'll need to compile +our program down to something small and standalone. As part of this +we'll make a few modifications to the running of the language and +how programs are compiled. This means that we'll have a source file +with a simple program written in Kaleidoscope rather than the +interactive JIT. It does involve a limitation that we can only +have one "top level" command at a time to reduce the number of +changes necessary. + +Here's the sample program we'll be compiling: + +.. code-block:: python + + def fib(x) + if x < 3 then + 1 + else + fib(x-1)+fib(x-2); + + fib(10) + + +Why is this a hard problem? +=========================== + +Debug information is a hard problem for a few different reasons - mostly +centered around optimized code. First, optimization makes keeping source +locations more difficult. In LLVM IR we keep the original source location +for each IR level instruction on the instruction. Optimization passes +should keep the source locations for newly created instructions, but merged +instructions only get to keep a single location - this can cause jumping +around when stepping through optimized programs. Secondly, optimization +can move variables in ways that are either optimized out, shared in memory +with other variables, or difficult to track. For the purposes of this +tutorial we're going to avoid optimization (as you'll see with one of the +next sets of patches). + +Ahead-of-Time Compilation Mode +============================== + +To highlight only the aspects of adding debug information to a source +language without needing to worry about the complexities of JIT debugging +we're going to make a few changes to Kaleidoscope to support compiling +the IR emitted by the front end into a simple standalone program that +you can execute, debug, and see results. + +First we make our anonymous function that contains our top level +statement be our "main": + +.. code-block:: udiff + + - PrototypeAST *Proto = new PrototypeAST("", std::vector()); + + PrototypeAST *Proto = new PrototypeAST("main", std::vector()); + +just with the simple change of giving it a name. + +Then we're going to remove the command line code wherever it exists: + +.. code-block:: udiff + + @@ -1129,7 +1129,6 @@ static void HandleTopLevelExpression() { + /// top ::= definition | external | expression | ';' + static void MainLoop() { + while (1) { + - fprintf(stderr, "ready> "); + switch (CurTok) { + case tok_eof: + return; + @@ -1184,7 +1183,6 @@ int main() { + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + - fprintf(stderr, "ready> "); + getNextToken(); + +Lastly we're going to disable all of the optimization passes and the JIT so +that the only thing that happens after we're done parsing and generating +code is that the llvm IR goes to standard error: + +.. code-block:: udiff + + @@ -1108,17 +1108,8 @@ static void HandleExtern() { + static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + - if (Function *LF = F->Codegen()) { + - // We're just doing this to make sure it executes. + - TheExecutionEngine->finalizeObject(); + - // JIT the function, returning a function pointer. + - void *FPtr = TheExecutionEngine->getPointerToFunction(LF); + - + - // Cast it to the right type (takes no arguments, returns a double) so we + - // can call it as a native function. + - double (*FP)() = (double (*)())(intptr_t)FPtr; + - // Ignore the return value for this. + - (void)FP; + + if (!F->Codegen()) { + + fprintf(stderr, "Error generating code for top level expr"); + } + } else { + // Skip token for error recovery. + @@ -1439,11 +1459,11 @@ int main() { + // target lays out data structures. + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); + OurFPM.add(new DataLayoutPass()); + +#if 0 + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + @@ -1218,7 +1210,7 @@ int main() { + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + - + + #endif + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + +This relatively small set of changes get us to the point that we can compile +our piece of Kaleidoscope language down to an executable program via this +command line: + +.. code-block:: bash + + Kaleidoscope-Ch8 < fib.ks | & clang -x ir - + +which gives an a.out/a.exe in the current working directory. + +Compile Unit +============ + +The top level container for a section of code in DWARF is a compile unit. +This contains the type and function data for an individual translation unit +(read: one file of source code). So the first thing we need to do is +construct one for our fib.ks file. + +DWARF Emission Setup +==================== + +Similar to the ``IRBuilder`` class we have a +```DIBuilder`` `_ class +that helps in constructing debug metadata for an llvm IR file. It +corresponds 1:1 similarly to ``IRBuilder`` and llvm IR, but with nicer names. +Using it does require that you be more familiar with DWARF terminology than +you needed to be with ``IRBuilder`` and ``Instruction`` names, but if you +read through the general documentation on the +```Metadata Format`` `_ it +should be a little more clear. We'll be using this class to construct all +of our IR level descriptions. Construction for it takes a module so we +need to construct it shortly after we construct our module. We've left it +as a global static variable to make it a bit easier to use. + +Next we're going to create a small container to cache some of our frequent +data. The first will be our compile unit, but we'll also write a bit of +code for our one type since we won't have to worry about multiple typed +expressions: + +.. code-block:: c++ + + static DIBuilder *DBuilder; + + struct DebugInfo { + DICompileUnit TheCU; + DIType DblTy; + + DIType getDoubleTy(); + } KSDbgInfo; + + DIType DebugInfo::getDoubleTy() { + if (DblTy.isValid()) + return DblTy; + + DblTy = DBuilder->createBasicType("double", 64, 64, dwarf::DW_ATE_float); + return DblTy; + } + +And then later on in ``main`` when we're constructing our module: + +.. code-block:: c++ + + DBuilder = new DIBuilder(*TheModule); + + KSDbgInfo.TheCU = DBuilder->createCompileUnit( + dwarf::DW_LANG_C, "fib.ks", ".", "Kaleidoscope Compiler", 0, "", 0); + +There are a couple of things to note here. First, while we're producing a +compile unit for a language called Kaleidoscope we used the language +constant for C. This is because a debugger wouldn't necessarily understand +the calling conventions or default ABI for a language it doesn't recognize +and we follow the C ABI in our llvm code generation so it's the closest +thing to accurate. This ensures we can actually call functions from the +debugger and have them execute. Secondly, you'll see the "fib.ks" in the +call to ``createCompileUnit``. This is a default hard coded value since +we're using shell redirection to put our source into the Kaleidoscope +compiler. In a usual front end you'd have an input file name and it would +go there. + +One last thing as part of emitting debug information via DIBuilder is that +we need to "finalize" the debug information. The reasons are part of the +underlying API for DIBuilder, but make sure you do this near the end of +main: + +.. code-block:: c++ + + DBuilder->finalize(); + +before you dump out the module. + +Functions +========= + +Now that we have our ``Compile Unit`` and our source locations, we can add +function definitions to the debug info. So in ``PrototypeAST::Codegen`` we +add a few lines of code to describe a context for our subprogram, in this +case the "File", and the actual definition of the function itself. + +So the context: + +.. code-block:: c++ + + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + +giving us a DIFile and asking the ``Compile Unit`` we created above for the +directory and filename where we are currently. Then, for now, we use some +source locations of 0 (since our AST doesn't currently have source location +information) and construct our function definition: + +.. code-block:: c++ + + DIDescriptor FContext(Unit); + unsigned LineNo = 0; + unsigned ScopeLine = 0; + DISubprogram SP = DBuilder->createFunction( + FContext, Name, StringRef(), Unit, LineNo, + CreateFunctionType(Args.size(), Unit), false /* internal linkage */, + true /* definition */, ScopeLine, DIDescriptor::FlagPrototyped, false, F); + +and we now have a DISubprogram that contains a reference to all of our metadata +for the function. + +Source Locations +================ + +The most important thing for debug information is accurate source location - +this makes it possible to map your source code back. We have a problem though, +Kaleidoscope really doesn't have any source location information in the lexer +or parser so we'll need to add it. + +.. code-block:: c++ + + struct SourceLocation { + int Line; + int Col; + }; + static SourceLocation CurLoc; + static SourceLocation LexLoc = {1, 0}; + + static int advance() { + int LastChar = getchar(); + + if (LastChar == '\n' || LastChar == '\r') { + LexLoc.Line++; + LexLoc.Col = 0; + } else + LexLoc.Col++; + return LastChar; + } + +In this set of code we've added some functionality on how to keep track of the +line and column of the "source file". As we lex every token we set our current +current "lexical location" to the assorted line and column for the beginning +of the token. We do this by overriding all of the previous calls to +``getchar()`` with our new ``advance()`` that keeps track of the information +and then we have added to all of our AST classes a source location: + +.. code-block:: c++ + + class ExprAST { + SourceLocation Loc; + + public: + int getLine() const { return Loc.Line; } + int getCol() const { return Loc.Col; } + ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + return out << ':' << getLine() << ':' << getCol() << '\n'; + } + +that we pass down through when we create a new expression: + +.. code-block:: c++ + + LHS = new BinaryExprAST(BinLoc, BinOp, LHS, RHS); + +giving us locations for each of our expressions and variables. + +From this we can make sure to tell ``DIBuilder`` when we're at a new source +location so it can use that when we generate the rest of our code and make +sure that each instruction has source location information. We do this +by constructing another small function: + +.. code-block:: c++ + + void DebugInfo::emitLocation(ExprAST *AST) { + DIScope *Scope; + if (LexicalBlocks.empty()) + Scope = &TheCU; + else + Scope = LexicalBlocks.back(); + Builder.SetCurrentDebugLocation( + DebugLoc::get(AST->getLine(), AST->getCol(), DIScope(*Scope))); + } + +that both tells the main ``IRBuilder`` where we are, but also what scope +we're in. Since we've just created a function above we can either be in +the main file scope (like when we created our function), or now we can be +in the function scope we just created. To represent this we create a stack +of scopes: + +.. code-block:: c++ + + std::vector LexicalBlocks; + std::map FnScopeMap; + +and keep a map of each function to the scope that it represents (a DISubprogram +is also a DIScope). + +Then we make sure to: + +.. code-block:: c++ + + KSDbgInfo.emitLocation(this); + +emit the location every time we start to generate code for a new AST, and +also: + +.. code-block:: c++ + + KSDbgInfo.FnScopeMap[this] = SP; + +store the scope (function) when we create it and use it: + + KSDbgInfo.LexicalBlocks.push_back(&KSDbgInfo.FnScopeMap[Proto]); + +when we start generating the code for each function. + +also, don't forget to pop the scope back off of your scope stack at the +end of the code generation for the function: + +.. code-block:: c++ + + // Pop off the lexical block for the function since we added it + // unconditionally. + KSDbgInfo.LexicalBlocks.pop_back(); + +Variables +========= + +Now that we have functions, we need to be able to print out the variables +we have in scope. Let's get our function arguments set up so we can get +decent backtraces and see how our functions are being called. It isn't +a lot of code, and we generally handle it when we're creating the +argument allocas in ``PrototypeAST::CreateArgumentAllocas``. + +.. code-block:: c++ + + DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIVariable D = DBuilder->createLocalVariable(dwarf::DW_TAG_arg_variable, + *Scope, Args[Idx], Unit, Line, + KSDbgInfo.getDoubleTy(), Idx); + + Instruction *Call = DBuilder->insertDeclare( + Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock()); + Call->setDebugLoc(DebugLoc::get(Line, 0, *Scope)); + +Here we're doing a few things. First, we're grabbing our current scope +for the variable so we can say what range of code our variable is valid +through. Second, we're creating the variable, giving it the scope, +the name, source location, type, and since it's an argument, the argument +index. Third, we create an ``lvm.dbg.declare`` call to indicate at the IR +level that we've got a variable in an alloca (and it gives a starting +location for the variable). Lastly, we set a source location for the +beginning of the scope on the declare. + +One interesting thing to note at this point is that various debuggers have +assumptions based on how code and debug information was generated for them +in the past. In this case we need to do a little bit of a hack to avoid +generating line information for the function prologue so that the debugger +knows to skip over those instructions when setting a breakpoint. So in +``FunctionAST::CodeGen`` we add a couple of lines: + +.. code-block:: c++ + + // Unset the location for the prologue emission (leading instructions with no + // location in a function are considered part of the prologue and the debugger + // will run past them when breaking on a function) + KSDbgInfo.emitLocation(nullptr); + +and then emit a new location when we actually start generating code for the +body of the function: + +.. code-block:: c++ + + KSDbgInfo.emitLocation(Body); + +With this we have enough debug information to set breakpoints in functions, +print out argument variables, and call functions. Not too bad for just a +few simple lines of code! + +Full Code Listing +================= + +Here is the complete code listing for our running example, enhanced with +debug information. To build this example, use: + +.. code-block:: bash + + # Compile + clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core mcjit native` -O3 -o toy + # Run + ./toy + +Here is the code: + +.. literalinclude:: ../../examples/Kaleidoscope/Chapter8/toy.cpp + :language: c++ + +`Next: Conclusion and other useful LLVM tidbits `_ diff --git a/docs/tutorial/LangImpl9.rst b/docs/tutorial/LangImpl9.rst new file mode 100644 index 0000000..6f69493 --- /dev/null +++ b/docs/tutorial/LangImpl9.rst @@ -0,0 +1,267 @@ +====================================================== +Kaleidoscope: Conclusion and other useful LLVM tidbits +====================================================== + +.. contents:: + :local: + +Tutorial Conclusion +=================== + +Welcome to the final chapter of the "`Implementing a language with +LLVM `_" tutorial. In the course of this tutorial, we have +grown our little Kaleidoscope language from being a useless toy, to +being a semi-interesting (but probably still useless) toy. :) + +It is interesting to see how far we've come, and how little code it has +taken. We built the entire lexer, parser, AST, code generator, and an +interactive run-loop (with a JIT!) by-hand in under 700 lines of +(non-comment/non-blank) code. + +Our little language supports a couple of interesting features: it +supports user defined binary and unary operators, it uses JIT +compilation for immediate evaluation, and it supports a few control flow +constructs with SSA construction. + +Part of the idea of this tutorial was to show you how easy and fun it +can be to define, build, and play with languages. Building a compiler +need not be a scary or mystical process! Now that you've seen some of +the basics, I strongly encourage you to take the code and hack on it. +For example, try adding: + +- **global variables** - While global variables have questional value + in modern software engineering, they are often useful when putting + together quick little hacks like the Kaleidoscope compiler itself. + Fortunately, our current setup makes it very easy to add global + variables: just have value lookup check to see if an unresolved + variable is in the global variable symbol table before rejecting it. + To create a new global variable, make an instance of the LLVM + ``GlobalVariable`` class. +- **typed variables** - Kaleidoscope currently only supports variables + of type double. This gives the language a very nice elegance, because + only supporting one type means that you never have to specify types. + Different languages have different ways of handling this. The easiest + way is to require the user to specify types for every variable + definition, and record the type of the variable in the symbol table + along with its Value\*. +- **arrays, structs, vectors, etc** - Once you add types, you can start + extending the type system in all sorts of interesting ways. Simple + arrays are very easy and are quite useful for many different + applications. Adding them is mostly an exercise in learning how the + LLVM `getelementptr <../LangRef.html#i_getelementptr>`_ instruction + works: it is so nifty/unconventional, it `has its own + FAQ <../GetElementPtr.html>`_! If you add support for recursive types + (e.g. linked lists), make sure to read the `section in the LLVM + Programmer's Manual <../ProgrammersManual.html#TypeResolve>`_ that + describes how to construct them. +- **standard runtime** - Our current language allows the user to access + arbitrary external functions, and we use it for things like "printd" + and "putchard". As you extend the language to add higher-level + constructs, often these constructs make the most sense if they are + lowered to calls into a language-supplied runtime. For example, if + you add hash tables to the language, it would probably make sense to + add the routines to a runtime, instead of inlining them all the way. +- **memory management** - Currently we can only access the stack in + Kaleidoscope. It would also be useful to be able to allocate heap + memory, either with calls to the standard libc malloc/free interface + or with a garbage collector. If you would like to use garbage + collection, note that LLVM fully supports `Accurate Garbage + Collection <../GarbageCollection.html>`_ including algorithms that + move objects and need to scan/update the stack. +- **debugger support** - LLVM supports generation of `DWARF Debug + info <../SourceLevelDebugging.html>`_ which is understood by common + debuggers like GDB. Adding support for debug info is fairly + straightforward. The best way to understand it is to compile some + C/C++ code with "``clang -g -O0``" and taking a look at what it + produces. +- **exception handling support** - LLVM supports generation of `zero + cost exceptions <../ExceptionHandling.html>`_ which interoperate with + code compiled in other languages. You could also generate code by + implicitly making every function return an error value and checking + it. You could also make explicit use of setjmp/longjmp. There are + many different ways to go here. +- **object orientation, generics, database access, complex numbers, + geometric programming, ...** - Really, there is no end of crazy + features that you can add to the language. +- **unusual domains** - We've been talking about applying LLVM to a + domain that many people are interested in: building a compiler for a + specific language. However, there are many other domains that can use + compiler technology that are not typically considered. For example, + LLVM has been used to implement OpenGL graphics acceleration, + translate C++ code to ActionScript, and many other cute and clever + things. Maybe you will be the first to JIT compile a regular + expression interpreter into native code with LLVM? + +Have fun - try doing something crazy and unusual. Building a language +like everyone else always has, is much less fun than trying something a +little crazy or off the wall and seeing how it turns out. If you get +stuck or want to talk about it, feel free to email the `llvmdev mailing +list `_: it has lots +of people who are interested in languages and are often willing to help +out. + +Before we end this tutorial, I want to talk about some "tips and tricks" +for generating LLVM IR. These are some of the more subtle things that +may not be obvious, but are very useful if you want to take advantage of +LLVM's capabilities. + +Properties of the LLVM IR +========================= + +We have a couple common questions about code in the LLVM IR form - lets +just get these out of the way right now, shall we? + +Target Independence +------------------- + +Kaleidoscope is an example of a "portable language": any program written +in Kaleidoscope will work the same way on any target that it runs on. +Many other languages have this property, e.g. lisp, java, haskell, +javascript, python, etc (note that while these languages are portable, +not all their libraries are). + +One nice aspect of LLVM is that it is often capable of preserving target +independence in the IR: you can take the LLVM IR for a +Kaleidoscope-compiled program and run it on any target that LLVM +supports, even emitting C code and compiling that on targets that LLVM +doesn't support natively. You can trivially tell that the Kaleidoscope +compiler generates target-independent code because it never queries for +any target-specific information when generating code. + +The fact that LLVM provides a compact, target-independent, +representation for code gets a lot of people excited. Unfortunately, +these people are usually thinking about C or a language from the C +family when they are asking questions about language portability. I say +"unfortunately", because there is really no way to make (fully general) +C code portable, other than shipping the source code around (and of +course, C source code is not actually portable in general either - ever +port a really old application from 32- to 64-bits?). + +The problem with C (again, in its full generality) is that it is heavily +laden with target specific assumptions. As one simple example, the +preprocessor often destructively removes target-independence from the +code when it processes the input text: + +.. code-block:: c + + #ifdef __i386__ + int X = 1; + #else + int X = 42; + #endif + +While it is possible to engineer more and more complex solutions to +problems like this, it cannot be solved in full generality in a way that +is better than shipping the actual source code. + +That said, there are interesting subsets of C that can be made portable. +If you are willing to fix primitive types to a fixed size (say int = +32-bits, and long = 64-bits), don't care about ABI compatibility with +existing binaries, and are willing to give up some other minor features, +you can have portable code. This can make sense for specialized domains +such as an in-kernel language. + +Safety Guarantees +----------------- + +Many of the languages above are also "safe" languages: it is impossible +for a program written in Java to corrupt its address space and crash the +process (assuming the JVM has no bugs). Safety is an interesting +property that requires a combination of language design, runtime +support, and often operating system support. + +It is certainly possible to implement a safe language in LLVM, but LLVM +IR does not itself guarantee safety. The LLVM IR allows unsafe pointer +casts, use after free bugs, buffer over-runs, and a variety of other +problems. Safety needs to be implemented as a layer on top of LLVM and, +conveniently, several groups have investigated this. Ask on the `llvmdev +mailing list `_ if +you are interested in more details. + +Language-Specific Optimizations +------------------------------- + +One thing about LLVM that turns off many people is that it does not +solve all the world's problems in one system (sorry 'world hunger', +someone else will have to solve you some other day). One specific +complaint is that people perceive LLVM as being incapable of performing +high-level language-specific optimization: LLVM "loses too much +information". + +Unfortunately, this is really not the place to give you a full and +unified version of "Chris Lattner's theory of compiler design". Instead, +I'll make a few observations: + +First, you're right that LLVM does lose information. For example, as of +this writing, there is no way to distinguish in the LLVM IR whether an +SSA-value came from a C "int" or a C "long" on an ILP32 machine (other +than debug info). Both get compiled down to an 'i32' value and the +information about what it came from is lost. The more general issue +here, is that the LLVM type system uses "structural equivalence" instead +of "name equivalence". Another place this surprises people is if you +have two types in a high-level language that have the same structure +(e.g. two different structs that have a single int field): these types +will compile down into a single LLVM type and it will be impossible to +tell what it came from. + +Second, while LLVM does lose information, LLVM is not a fixed target: we +continue to enhance and improve it in many different ways. In addition +to adding new features (LLVM did not always support exceptions or debug +info), we also extend the IR to capture important information for +optimization (e.g. whether an argument is sign or zero extended, +information about pointers aliasing, etc). Many of the enhancements are +user-driven: people want LLVM to include some specific feature, so they +go ahead and extend it. + +Third, it is *possible and easy* to add language-specific optimizations, +and you have a number of choices in how to do it. As one trivial +example, it is easy to add language-specific optimization passes that +"know" things about code compiled for a language. In the case of the C +family, there is an optimization pass that "knows" about the standard C +library functions. If you call "exit(0)" in main(), it knows that it is +safe to optimize that into "return 0;" because C specifies what the +'exit' function does. + +In addition to simple library knowledge, it is possible to embed a +variety of other language-specific information into the LLVM IR. If you +have a specific need and run into a wall, please bring the topic up on +the llvmdev list. At the very worst, you can always treat LLVM as if it +were a "dumb code generator" and implement the high-level optimizations +you desire in your front-end, on the language-specific AST. + +Tips and Tricks +=============== + +There is a variety of useful tips and tricks that you come to know after +working on/with LLVM that aren't obvious at first glance. Instead of +letting everyone rediscover them, this section talks about some of these +issues. + +Implementing portable offsetof/sizeof +------------------------------------- + +One interesting thing that comes up, if you are trying to keep the code +generated by your compiler "target independent", is that you often need +to know the size of some LLVM type or the offset of some field in an +llvm structure. For example, you might need to pass the size of a type +into a function that allocates memory. + +Unfortunately, this can vary widely across targets: for example the +width of a pointer is trivially target-specific. However, there is a +`clever way to use the getelementptr +instruction `_ +that allows you to compute this in a portable way. + +Garbage Collected Stack Frames +------------------------------ + +Some languages want to explicitly manage their stack frames, often so +that they are garbage collected or to allow easy implementation of +closures. There are often better ways to implement these features than +explicit stack frames, but `LLVM does support +them, `_ +if you want. It requires your front-end to convert the code into +`Continuation Passing +Style `_ and +the use of tail calls (which LLVM also supports). + diff --git a/examples/BrainF/BrainFDriver.cpp b/examples/BrainF/BrainFDriver.cpp index e2de6bc..99c8ff3 100644 --- a/examples/BrainF/BrainFDriver.cpp +++ b/examples/BrainF/BrainFDriver.cpp @@ -26,8 +26,8 @@ #include "BrainF.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" @@ -107,9 +107,8 @@ int main(int argc, char **argv) { OutputFilename = base+".bc"; } if (OutputFilename != "-") { - std::string ErrInfo; - out = new raw_fd_ostream(OutputFilename.c_str(), ErrInfo, - sys::fs::F_None); + std::error_code EC; + out = new raw_fd_ostream(OutputFilename, EC, sys::fs::F_None); } } @@ -125,13 +124,13 @@ int main(int argc, char **argv) { //Read the BrainF program BrainF bf; - Module *mod = bf.parse(in, 65536, cf, Context); //64 KiB + std::unique_ptr Mod(bf.parse(in, 65536, cf, Context)); // 64 KiB if (in != &std::cin) delete in; - addMainFunction(mod); + addMainFunction(Mod.get()); //Verify generated code - if (verifyModule(*mod)) { + if (verifyModule(*Mod)) { errs() << "Error: module failed verification. This shouldn't happen.\n"; abort(); } @@ -141,18 +140,18 @@ int main(int argc, char **argv) { InitializeNativeTarget(); outs() << "------- Running JIT -------\n"; - ExecutionEngine *ee = EngineBuilder(mod).create(); + Module &M = *Mod; + ExecutionEngine *ee = EngineBuilder(std::move(Mod)).create(); std::vector args; - Function *brainf_func = mod->getFunction("brainf"); + Function *brainf_func = M.getFunction("brainf"); GenericValue gv = ee->runFunction(brainf_func, args); } else { - WriteBitcodeToFile(mod, *out); + WriteBitcodeToFile(Mod.get(), *out); } //Clean up if (out != &outs()) delete out; - delete mod; llvm_shutdown(); diff --git a/examples/BrainF/CMakeLists.txt b/examples/BrainF/CMakeLists.txt index 65589d9..cf1cf1b 100644 --- a/examples/BrainF/CMakeLists.txt +++ b/examples/BrainF/CMakeLists.txt @@ -2,7 +2,6 @@ set(LLVM_LINK_COMPONENTS BitWriter Core ExecutionEngine - JIT MC Support nativecodegen diff --git a/examples/BrainF/Makefile b/examples/BrainF/Makefile index 2c3e066..3e36e07 100644 --- a/examples/BrainF/Makefile +++ b/examples/BrainF/Makefile @@ -10,6 +10,6 @@ LEVEL = ../.. TOOLNAME = BrainF EXAMPLE_TOOL = 1 -LINK_COMPONENTS := jit bitwriter nativecodegen interpreter +LINK_COMPONENTS := mcjit bitwriter nativecodegen interpreter include $(LEVEL)/Makefile.common diff --git a/examples/ExceptionDemo/CMakeLists.txt b/examples/ExceptionDemo/CMakeLists.txt index a08a7c3..9cadd94 100644 --- a/examples/ExceptionDemo/CMakeLists.txt +++ b/examples/ExceptionDemo/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine + MC MCJIT Support nativecodegen diff --git a/examples/ExceptionDemo/ExceptionDemo.cpp b/examples/ExceptionDemo/ExceptionDemo.cpp index 24e538c..d50c776 100644 --- a/examples/ExceptionDemo/ExceptionDemo.cpp +++ b/examples/ExceptionDemo/ExceptionDemo.cpp @@ -1957,17 +1957,17 @@ int main(int argc, char *argv[]) { llvm::IRBuilder<> theBuilder(context); // Make the module, which holds all the code. - llvm::Module *module = new llvm::Module("my cool jit", context); + std::unique_ptr Owner = + llvm::make_unique("my cool jit", context); + llvm::Module *module = Owner.get(); - llvm::RTDyldMemoryManager *MemMgr = new llvm::SectionMemoryManager(); + std::unique_ptr MemMgr(new llvm::SectionMemoryManager()); // Build engine with JIT - llvm::EngineBuilder factory(module); + llvm::EngineBuilder factory(std::move(Owner)); factory.setEngineKind(llvm::EngineKind::JIT); - factory.setAllocateGVsWithCode(false); factory.setTargetOptions(Opts); - factory.setMCJITMemoryManager(MemMgr); - factory.setUseMCJIT(true); + factory.setMCJITMemoryManager(std::move(MemMgr)); llvm::ExecutionEngine *executionEngine = factory.create(); { @@ -1977,7 +1977,7 @@ int main(int argc, char *argv[]) { // Start with registering info about how the // target lays out data structures. module->setDataLayout(executionEngine->getDataLayout()); - fpm.add(new llvm::DataLayoutPass(module)); + fpm.add(new llvm::DataLayoutPass()); // Optimizations turned on #ifdef ADD_OPT_PASSES diff --git a/examples/ExceptionDemo/Makefile b/examples/ExceptionDemo/Makefile index 58d9def..895b61d 100644 --- a/examples/ExceptionDemo/Makefile +++ b/examples/ExceptionDemo/Makefile @@ -11,6 +11,6 @@ TOOLNAME = ExceptionDemo EXAMPLE_TOOL = 1 REQUIRES_EH = 1 -LINK_COMPONENTS := jit mcjit nativecodegen +LINK_COMPONENTS := mcjit nativecodegen include $(LEVEL)/Makefile.common diff --git a/examples/Fibonacci/CMakeLists.txt b/examples/Fibonacci/CMakeLists.txt index c015e50..087ccdd7 100644 --- a/examples/Fibonacci/CMakeLists.txt +++ b/examples/Fibonacci/CMakeLists.txt @@ -2,7 +2,6 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine Interpreter - JIT MC Support nativecodegen diff --git a/examples/Fibonacci/Makefile b/examples/Fibonacci/Makefile index 71f6ba0..c99110a 100644 --- a/examples/Fibonacci/Makefile +++ b/examples/Fibonacci/Makefile @@ -12,6 +12,6 @@ TOOLNAME = Fibonacci EXAMPLE_TOOL = 1 # Link in JIT support -LINK_COMPONENTS := jit interpreter nativecodegen +LINK_COMPONENTS := interpreter mcjit nativecodegen include $(LEVEL)/Makefile.common diff --git a/examples/Fibonacci/fibonacci.cpp b/examples/Fibonacci/fibonacci.cpp index ba8e953..8092e19 100644 --- a/examples/Fibonacci/fibonacci.cpp +++ b/examples/Fibonacci/fibonacci.cpp @@ -26,7 +26,6 @@ #include "llvm/IR/Verifier.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" @@ -96,15 +95,16 @@ int main(int argc, char **argv) { LLVMContext Context; // Create some module to put our function into it. - std::unique_ptr M(new Module("test", Context)); + std::unique_ptr Owner(new Module("test", Context)); + Module *M = Owner.get(); // We are about to create the "fib" function: - Function *FibF = CreateFibFunction(M.get(), Context); + Function *FibF = CreateFibFunction(M, Context); // Now we going to create JIT std::string errStr; ExecutionEngine *EE = - EngineBuilder(M.get()) + EngineBuilder(std::move(Owner)) .setErrorStr(&errStr) .setEngineKind(EngineKind::JIT) .create(); diff --git a/examples/HowToUseJIT/CMakeLists.txt b/examples/HowToUseJIT/CMakeLists.txt index 237cbea..a344ad0 100644 --- a/examples/HowToUseJIT/CMakeLists.txt +++ b/examples/HowToUseJIT/CMakeLists.txt @@ -2,7 +2,6 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine Interpreter - JIT MC Support nativecodegen diff --git a/examples/HowToUseJIT/HowToUseJIT.cpp b/examples/HowToUseJIT/HowToUseJIT.cpp index 7125a15..9552240 100644 --- a/examples/HowToUseJIT/HowToUseJIT.cpp +++ b/examples/HowToUseJIT/HowToUseJIT.cpp @@ -36,7 +36,6 @@ #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -56,7 +55,8 @@ int main() { LLVMContext Context; // Create some module to put our function into it. - Module *M = new Module("test", Context); + std::unique_ptr Owner = make_unique("test", Context); + Module *M = Owner.get(); // Create the add1 function entry and insert this entry into module M. The // function will have a return type of "int" and take an argument of "int". @@ -114,7 +114,7 @@ int main() { builder.CreateRet(Add1CallRes); // Now we create the JIT. - ExecutionEngine* EE = EngineBuilder(M).create(); + ExecutionEngine* EE = EngineBuilder(std::move(Owner)).create(); outs() << "We just constructed this LLVM module:\n\n" << *M; outs() << "\n\nRunning foo: "; @@ -126,7 +126,6 @@ int main() { // Import result of execution: outs() << "Result: " << gv.IntVal << "\n"; - EE->freeMachineCodeForFunction(FooF); delete EE; llvm_shutdown(); return 0; diff --git a/examples/HowToUseJIT/Makefile b/examples/HowToUseJIT/Makefile index c8919db..26a25a1 100644 --- a/examples/HowToUseJIT/Makefile +++ b/examples/HowToUseJIT/Makefile @@ -10,6 +10,6 @@ LEVEL = ../.. TOOLNAME = HowToUseJIT EXAMPLE_TOOL = 1 -LINK_COMPONENTS := jit interpreter nativecodegen +LINK_COMPONENTS := mcjit interpreter nativecodegen include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/CMakeLists.txt b/examples/Kaleidoscope/CMakeLists.txt index 8c87ac5..b93cc76 100644 --- a/examples/Kaleidoscope/CMakeLists.txt +++ b/examples/Kaleidoscope/CMakeLists.txt @@ -1,6 +1,15 @@ +add_custom_target(Kaleidoscope) +set_target_properties(Kaleidoscope PROPERTIES FOLDER Examples) + +macro(add_kaleidoscope_chapter name) + add_dependencies(Kaleidoscope ${name}) + add_llvm_example(${name} ${ARGN}) +endmacro(add_kaleidoscope_chapter name) + add_subdirectory(Chapter2) add_subdirectory(Chapter3) add_subdirectory(Chapter4) add_subdirectory(Chapter5) add_subdirectory(Chapter6) add_subdirectory(Chapter7) +add_subdirectory(Chapter8) diff --git a/examples/Kaleidoscope/Chapter2/CMakeLists.txt b/examples/Kaleidoscope/Chapter2/CMakeLists.txt index 79f2b17..fed3f4b 100644 --- a/examples/Kaleidoscope/Chapter2/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter2/CMakeLists.txt @@ -1,3 +1,3 @@ -add_llvm_example(Kaleidoscope-Ch2 +add_kaleidoscope_chapter(Kaleidoscope-Ch2 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter3/CMakeLists.txt b/examples/Kaleidoscope/Chapter3/CMakeLists.txt index a98d7df..8053c96 100644 --- a/examples/Kaleidoscope/Chapter3/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter3/CMakeLists.txt @@ -3,6 +3,6 @@ set(LLVM_LINK_COMPONENTS Support ) -add_llvm_example(Kaleidoscope-Ch3 +add_kaleidoscope_chapter(Kaleidoscope-Ch3 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter4/CMakeLists.txt b/examples/Kaleidoscope/Chapter4/CMakeLists.txt index 2b87e86..45e92e4 100644 --- a/examples/Kaleidoscope/Chapter4/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter4/CMakeLists.txt @@ -3,13 +3,13 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - JIT MC ScalarOpts Support - nativecodegen + native + mcjit ) -add_llvm_example(Kaleidoscope-Ch4 +add_kaleidoscope_chapter(Kaleidoscope-Ch4 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter4/Makefile b/examples/Kaleidoscope/Chapter4/Makefile index 30162d9..6d6a670 100644 --- a/examples/Kaleidoscope/Chapter4/Makefile +++ b/examples/Kaleidoscope/Chapter4/Makefile @@ -10,6 +10,6 @@ LEVEL = ../../.. TOOLNAME = Kaleidoscope-Ch4 EXAMPLE_TOOL = 1 -LINK_COMPONENTS := core jit native +LINK_COMPONENTS := core mcjit native include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter4/toy.cpp b/examples/Kaleidoscope/Chapter4/toy.cpp index a8f5942..3a97332 100644 --- a/examples/Kaleidoscope/Chapter4/toy.cpp +++ b/examples/Kaleidoscope/Chapter4/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -27,14 +28,16 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5 + tok_identifier = -4, + tok_number = -5 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -49,12 +52,14 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -67,13 +72,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -98,6 +104,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -106,6 +113,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); @@ -115,19 +123,21 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector Args; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; @@ -137,10 +147,11 @@ public: class PrototypeAST { std::string Name; std::vector Args; + public: PrototypeAST(const std::string &name, const std::vector &args) - : Name(name), Args(args) {} - + : Name(name), Args(args) {} + Function *Codegen(); }; @@ -148,10 +159,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -164,9 +175,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -176,17 +185,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -195,22 +214,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -220,7 +241,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -233,13 +254,14 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } @@ -249,10 +271,14 @@ static ExprAST *ParseParenExpr() { /// ::= parenexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); } } @@ -262,28 +288,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the primary expression after the binary operator. ExprAST *RHS = ParsePrimary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -294,8 +322,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -307,27 +336,28 @@ static PrototypeAST *ParsePrototype() { std::string FnName = IdentifierStr; getNextToken(); - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -346,7 +376,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -356,10 +386,13 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; +static std::map NamedValues; static FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -374,18 +407,23 @@ Value *VariableExprAST::Codegen() { Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: return ErrorV("invalid binary operator"); + default: + return ErrorV("invalid binary operator"); } } @@ -394,73 +432,75 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector ArgsV; + std::vector ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); - + // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } - + return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); @@ -470,10 +510,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); return 0; @@ -513,9 +553,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // JIT the function, returning a function pointer. void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -532,11 +573,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -546,8 +596,7 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } @@ -558,6 +607,8 @@ double putchard(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -565,18 +616,23 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); // Make the module, which holds all the code. - TheModule = new Module("my cool jit", Context); + std::unique_ptr Owner = make_unique("my cool jit", Context); + TheModule = Owner.get(); // Create the JIT. This takes ownership of the module. std::string ErrStr; - TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + TheExecutionEngine = + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); @@ -587,7 +643,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); - OurFPM.add(new DataLayoutPass(TheModule)); + OurFPM.add(new DataLayoutPass()); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. diff --git a/examples/Kaleidoscope/Chapter5/CMakeLists.txt b/examples/Kaleidoscope/Chapter5/CMakeLists.txt index c3e7c43..5aac674 100644 --- a/examples/Kaleidoscope/Chapter5/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter5/CMakeLists.txt @@ -3,13 +3,13 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - JIT MC ScalarOpts Support - nativecodegen + native + mcjit ) -add_llvm_example(Kaleidoscope-Ch5 +add_kaleidoscope_chapter(Kaleidoscope-Ch5 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter5/Makefile b/examples/Kaleidoscope/Chapter5/Makefile index d1f5e20..d780967 100644 --- a/examples/Kaleidoscope/Chapter5/Makefile +++ b/examples/Kaleidoscope/Chapter5/Makefile @@ -10,6 +10,6 @@ LEVEL = ../../.. TOOLNAME = Kaleidoscope-Ch5 EXAMPLE_TOOL = 1 -LINK_COMPONENTS := core jit native +LINK_COMPONENTS := core mcjit native include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter5/toy.cpp b/examples/Kaleidoscope/Chapter5/toy.cpp index a31b5b4..ab2d525 100644 --- a/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/examples/Kaleidoscope/Chapter5/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -27,18 +28,23 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10 + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -53,17 +59,24 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; - if (IdentifierStr == "if") return tok_if; - if (IdentifierStr == "then") return tok_then; - if (IdentifierStr == "else") return tok_else; - if (IdentifierStr == "for") return tok_for; - if (IdentifierStr == "in") return tok_in; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -76,13 +89,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -107,6 +121,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -115,6 +130,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); @@ -124,28 +140,31 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector Args; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; + public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) - : Cond(cond), Then(then), Else(_else) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -153,10 +172,11 @@ public: class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; + public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) - : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; @@ -166,10 +186,11 @@ public: class PrototypeAST { std::string Name; std::vector Args; + public: PrototypeAST(const std::string &name, const std::vector &args) - : Name(name), Args(args) {} - + : Name(name), Args(args) {} + Function *Codegen(); }; @@ -177,10 +198,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -193,9 +214,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -205,17 +224,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -224,22 +253,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -249,7 +280,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -262,80 +293,87 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + if (!Else) + return 0; + return new IfExprAST(Cond, Then, Else); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { - getNextToken(); // eat the for. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } @@ -348,12 +386,18 @@ static ExprAST *ParseForExpr() { /// ::= forexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); - case tok_if: return ParseIfExpr(); - case tok_for: return ParseForExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); } } @@ -363,28 +407,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the primary expression after the binary operator. ExprAST *RHS = ParsePrimary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -395,8 +441,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParsePrimary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -408,27 +455,28 @@ static PrototypeAST *ParsePrototype() { std::string FnName = IdentifierStr; getNextToken(); - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + return new PrototypeAST(FnName, ArgNames); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -447,7 +495,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -457,10 +505,13 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; +static std::map NamedValues; static FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -475,18 +526,23 @@ Value *VariableExprAST::Codegen() { Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: return ErrorV("invalid binary operator"); + default: + return ErrorV("invalid binary operator"); } } @@ -495,66 +551,70 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector ArgsV; + std::vector ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + if (CondV == 0) + return 0; + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "ifcond"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); - if (ThenV == 0) return 0; - + if (ThenV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); - if (ElseV == 0) return 0; - + if (ElseV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, - "iftmp"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -565,7 +625,7 @@ Value *ForExprAST::Codegen() { // ... // start = startexpr // goto loop - // loop: + // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr @@ -576,136 +636,141 @@ Value *ForExprAST::Codegen() { // endcond = endexpr // br endcond, loop, endloop // outloop: - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); - if (StartVal == 0) return 0; - + if (StartVal == 0) + return 0; + // Make the new basic block for the loop header, inserting after current // block. Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Start the PHI node with an entry for Start. - PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), + 2, VarName.c_str()); Variable->addIncoming(StartVal, PreheaderBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); - if (StepVal == 0) return 0; + if (StepVal == 0) + return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); // Compute the end condition. Value *EndCond = End->Codegen(); - if (EndCond == 0) return EndCond; - + if (EndCond == 0) + return EndCond; + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "loopcond"); - + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. BasicBlock *LoopEndBB = Builder.GetInsertBlock(); - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Add a new entry to the PHI node for the backedge. Variable->addIncoming(NextVar, LoopEndBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); - + // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } - + return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); @@ -715,10 +780,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); return 0; @@ -758,9 +823,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // JIT the function, returning a function pointer. void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -777,11 +843,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -791,8 +866,7 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } @@ -803,6 +877,8 @@ double putchard(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -810,18 +886,23 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); // Make the module, which holds all the code. - TheModule = new Module("my cool jit", Context); + std::unique_ptr Owner = make_unique("my cool jit", Context); + TheModule = Owner.get(); // Create the JIT. This takes ownership of the module. std::string ErrStr; - TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + TheExecutionEngine = + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); @@ -832,7 +913,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); - OurFPM.add(new DataLayoutPass(TheModule)); + OurFPM.add(new DataLayoutPass()); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. diff --git a/examples/Kaleidoscope/Chapter6/CMakeLists.txt b/examples/Kaleidoscope/Chapter6/CMakeLists.txt index cd61cec..c5a737a 100644 --- a/examples/Kaleidoscope/Chapter6/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter6/CMakeLists.txt @@ -3,13 +3,13 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - JIT MC ScalarOpts Support - nativecodegen + native + mcjit ) -add_llvm_example(Kaleidoscope-Ch6 +add_kaleidoscope_chapter(Kaleidoscope-Ch6 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter6/Makefile b/examples/Kaleidoscope/Chapter6/Makefile index a5fbcbd..8f47ea0 100644 --- a/examples/Kaleidoscope/Chapter6/Makefile +++ b/examples/Kaleidoscope/Chapter6/Makefile @@ -10,6 +10,6 @@ LEVEL = ../../.. TOOLNAME = Kaleidoscope-Ch6 EXAMPLE_TOOL = 1 -LINK_COMPONENTS := core jit native +LINK_COMPONENTS := core mcjit native include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter6/toy.cpp b/examples/Kaleidoscope/Chapter6/toy.cpp index 5a3bd2e..732f075 100644 --- a/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/examples/Kaleidoscope/Chapter6/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -27,21 +28,27 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10, - + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + // operators - tok_binary = -11, tok_unary = -12 + tok_binary = -11, + tok_unary = -12 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -56,19 +63,28 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; - if (IdentifierStr == "if") return tok_if; - if (IdentifierStr == "then") return tok_then; - if (IdentifierStr == "else") return tok_else; - if (IdentifierStr == "for") return tok_for; - if (IdentifierStr == "in") return tok_in; - if (IdentifierStr == "binary") return tok_binary; - if (IdentifierStr == "unary") return tok_unary; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; + if (IdentifierStr == "binary") + return tok_binary; + if (IdentifierStr == "unary") + return tok_unary; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -81,13 +97,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -112,6 +129,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -120,6 +138,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} virtual Value *Codegen(); @@ -129,9 +148,10 @@ public: class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; + public: - UnaryExprAST(char opcode, ExprAST *operand) - : Opcode(opcode), Operand(operand) {} + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -139,28 +159,31 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector Args; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; + public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) - : Cond(cond), Then(then), Else(_else) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -168,10 +191,11 @@ public: class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; + public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) - : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; @@ -182,22 +206,22 @@ class PrototypeAST { std::string Name; std::vector Args; bool isOperator; - unsigned Precedence; // Precedence if a binary op. + unsigned Precedence; // Precedence if a binary op. public: PrototypeAST(const std::string &name, const std::vector &args, bool isoperator = false, unsigned prec = 0) - : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} - + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + bool isUnaryOp() const { return isOperator && Args.size() == 1; } bool isBinaryOp() const { return isOperator && Args.size() == 2; } - + char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); - return Name[Name.size()-1]; + return Name[Name.size() - 1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); }; @@ -205,10 +229,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -221,9 +245,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -233,17 +255,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -252,22 +284,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -277,7 +311,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -290,80 +324,87 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + if (!Else) + return 0; + return new IfExprAST(Cond, Then, Else); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { - getNextToken(); // eat the for. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } @@ -376,12 +417,18 @@ static ExprAST *ParseForExpr() { /// ::= forexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); - case tok_if: return ParseIfExpr(); - case tok_for: return ParseForExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); } } @@ -392,7 +439,7 @@ static ExprAST *ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); - + // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); @@ -407,28 +454,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -439,8 +488,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -450,10 +500,10 @@ static ExprAST *ParseExpression() { /// ::= unary LETTER (id) static PrototypeAST *ParsePrototype() { std::string FnName; - + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. unsigned BinaryPrecedence = 30; - + switch (CurTok) { default: return ErrorP("Expected function name in prototype"); @@ -479,7 +529,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -489,31 +539,32 @@ static PrototypeAST *ParsePrototype() { } break; } - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + // Verify right number of names for operator. if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -532,7 +583,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -542,10 +593,13 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; +static std::map NamedValues; static FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} Value *NumberExprAST::Codegen() { return ConstantFP::get(getGlobalContext(), APFloat(Val)); @@ -559,37 +613,43 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); - if (OperandV == 0) return 0; - - Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (OperandV == 0) + return 0; + + Function *F = TheModule->getFunction(std::string("unary") + Opcode); if (F == 0) return ErrorV("Unknown unary operator"); - + return Builder.CreateCall(F, OperandV, "unop"); } Value *BinaryExprAST::Codegen() { Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: break; + default: + break; } - + // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. - Function *F = TheModule->getFunction(std::string("binary")+Op); + Function *F = TheModule->getFunction(std::string("binary") + Op); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -599,66 +659,70 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector ArgsV; + std::vector ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + if (CondV == 0) + return 0; + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "ifcond"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); - if (ThenV == 0) return 0; - + if (ThenV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); - if (ElseV == 0) return 0; - + if (ElseV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, - "iftmp"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -669,7 +733,7 @@ Value *ForExprAST::Codegen() { // ... // start = startexpr // goto loop - // loop: + // loop: // variable = phi [start, loopheader], [nextvariable, loopend] // ... // bodyexpr @@ -680,140 +744,145 @@ Value *ForExprAST::Codegen() { // endcond = endexpr // br endcond, loop, endloop // outloop: - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); - if (StartVal == 0) return 0; - + if (StartVal == 0) + return 0; + // Make the new basic block for the loop header, inserting after current // block. Function *TheFunction = Builder.GetInsertBlock()->getParent(); BasicBlock *PreheaderBB = Builder.GetInsertBlock(); - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Start the PHI node with an entry for Start. - PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, VarName.c_str()); + PHINode *Variable = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), + 2, VarName.c_str()); Variable->addIncoming(StartVal, PreheaderBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. Value *OldVal = NamedValues[VarName]; NamedValues[VarName] = Variable; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); - if (StepVal == 0) return 0; + if (StepVal == 0) + return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar"); // Compute the end condition. Value *EndCond = End->Codegen(); - if (EndCond == 0) return EndCond; - + if (EndCond == 0) + return EndCond; + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "loopcond"); - + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. BasicBlock *LoopEndBB = Builder.GetInsertBlock(); - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Add a new entry to the PHI node for the backedge. Variable->addIncoming(NextVar, LoopEndBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) { AI->setName(Args[Idx]); - + // Add arguments to variable symbol table. NamedValues[Args[Idx]] = AI; } - + return F; } Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + if (Value *RetVal = Body->Codegen()) { // Finish off the function. Builder.CreateRet(RetVal); @@ -823,10 +892,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -869,9 +938,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // JIT the function, returning a function pointer. void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -888,11 +958,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -902,15 +981,13 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" -double printd(double X) { +extern "C" double printd(double X) { printf("%f\n", X); return 0; } @@ -921,6 +998,8 @@ double printd(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -928,18 +1007,23 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); // Make the module, which holds all the code. - TheModule = new Module("my cool jit", Context); + std::unique_ptr Owner = make_unique("my cool jit", Context); + TheModule = Owner.get(); // Create the JIT. This takes ownership of the module. std::string ErrStr; - TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + TheExecutionEngine = + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); @@ -950,7 +1034,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); - OurFPM.add(new DataLayoutPass(TheModule)); + OurFPM.add(new DataLayoutPass()); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Do simple "peephole" optimizations and bit-twiddling optzns. diff --git a/examples/Kaleidoscope/Chapter7/CMakeLists.txt b/examples/Kaleidoscope/Chapter7/CMakeLists.txt index cdb13c4..19fdb95 100644 --- a/examples/Kaleidoscope/Chapter7/CMakeLists.txt +++ b/examples/Kaleidoscope/Chapter7/CMakeLists.txt @@ -3,16 +3,16 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine InstCombine - JIT MC ScalarOpts Support TransformUtils - nativecodegen + native + mcjit ) set(LLVM_REQUIRES_RTTI 1) -add_llvm_example(Kaleidoscope-Ch7 +add_kaleidoscope_chapter(Kaleidoscope-Ch7 toy.cpp ) diff --git a/examples/Kaleidoscope/Chapter7/Makefile b/examples/Kaleidoscope/Chapter7/Makefile index 6cec323..7abeb3e 100644 --- a/examples/Kaleidoscope/Chapter7/Makefile +++ b/examples/Kaleidoscope/Chapter7/Makefile @@ -11,6 +11,6 @@ TOOLNAME = Kaleidoscope-Ch7 EXAMPLE_TOOL = 1 REQUIRES_RTTI := 1 -LINK_COMPONENTS := core jit native +LINK_COMPONENTS := core mcjit native include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter7/toy.cpp b/examples/Kaleidoscope/Chapter7/toy.cpp index c2c337c..e63738f 100644 --- a/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/examples/Kaleidoscope/Chapter7/toy.cpp @@ -1,6 +1,7 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" @@ -27,24 +28,30 @@ enum Token { tok_eof = -1, // commands - tok_def = -2, tok_extern = -3, + tok_def = -2, + tok_extern = -3, // primary - tok_identifier = -4, tok_number = -5, - + tok_identifier = -4, + tok_number = -5, + // control - tok_if = -6, tok_then = -7, tok_else = -8, - tok_for = -9, tok_in = -10, - + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + // operators - tok_binary = -11, tok_unary = -12, - + tok_binary = -11, + tok_unary = -12, + // var definition tok_var = -13 }; -static std::string IdentifierStr; // Filled in if tok_identifier -static double NumVal; // Filled in if tok_number +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number /// gettok - Return the next token from standard input. static int gettok() { @@ -59,20 +66,30 @@ static int gettok() { while (isalnum((LastChar = getchar()))) IdentifierStr += LastChar; - if (IdentifierStr == "def") return tok_def; - if (IdentifierStr == "extern") return tok_extern; - if (IdentifierStr == "if") return tok_if; - if (IdentifierStr == "then") return tok_then; - if (IdentifierStr == "else") return tok_else; - if (IdentifierStr == "for") return tok_for; - if (IdentifierStr == "in") return tok_in; - if (IdentifierStr == "binary") return tok_binary; - if (IdentifierStr == "unary") return tok_unary; - if (IdentifierStr == "var") return tok_var; + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; + if (IdentifierStr == "binary") + return tok_binary; + if (IdentifierStr == "unary") + return tok_unary; + if (IdentifierStr == "var") + return tok_var; return tok_identifier; } - if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ std::string NumStr; do { NumStr += LastChar; @@ -85,13 +102,14 @@ static int gettok() { if (LastChar == '#') { // Comment until end of line. - do LastChar = getchar(); + do + LastChar = getchar(); while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); - + if (LastChar != EOF) return gettok(); } - + // Check for end of file. Don't eat the EOF. if (LastChar == EOF) return tok_eof; @@ -116,6 +134,7 @@ public: /// NumberExprAST - Expression class for numeric literals like "1.0". class NumberExprAST : public ExprAST { double Val; + public: NumberExprAST(double val) : Val(val) {} virtual Value *Codegen(); @@ -124,6 +143,7 @@ public: /// VariableExprAST - Expression class for referencing a variable, like "a". class VariableExprAST : public ExprAST { std::string Name; + public: VariableExprAST(const std::string &name) : Name(name) {} const std::string &getName() const { return Name; } @@ -134,9 +154,10 @@ public: class UnaryExprAST : public ExprAST { char Opcode; ExprAST *Operand; + public: - UnaryExprAST(char opcode, ExprAST *operand) - : Opcode(opcode), Operand(operand) {} + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} virtual Value *Codegen(); }; @@ -144,28 +165,31 @@ public: class BinaryExprAST : public ExprAST { char Op; ExprAST *LHS, *RHS; + public: - BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) - : Op(op), LHS(lhs), RHS(rhs) {} + BinaryExprAST(char op, ExprAST *lhs, ExprAST *rhs) + : Op(op), LHS(lhs), RHS(rhs) {} virtual Value *Codegen(); }; /// CallExprAST - Expression class for function calls. class CallExprAST : public ExprAST { std::string Callee; - std::vector Args; + std::vector Args; + public: - CallExprAST(const std::string &callee, std::vector &args) - : Callee(callee), Args(args) {} + CallExprAST(const std::string &callee, std::vector &args) + : Callee(callee), Args(args) {} virtual Value *Codegen(); }; /// IfExprAST - Expression class for if/then/else. class IfExprAST : public ExprAST { ExprAST *Cond, *Then, *Else; + public: IfExprAST(ExprAST *cond, ExprAST *then, ExprAST *_else) - : Cond(cond), Then(then), Else(_else) {} + : Cond(cond), Then(then), Else(_else) {} virtual Value *Codegen(); }; @@ -173,22 +197,24 @@ public: class ForExprAST : public ExprAST { std::string VarName; ExprAST *Start, *End, *Step, *Body; + public: ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, ExprAST *step, ExprAST *body) - : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} virtual Value *Codegen(); }; /// VarExprAST - Expression class for var/in class VarExprAST : public ExprAST { - std::vector > VarNames; + std::vector > VarNames; ExprAST *Body; + public: - VarExprAST(const std::vector > &varnames, + VarExprAST(const std::vector > &varnames, ExprAST *body) - : VarNames(varnames), Body(body) {} - + : VarNames(varnames), Body(body) {} + virtual Value *Codegen(); }; @@ -198,24 +224,24 @@ class PrototypeAST { std::string Name; std::vector Args; bool isOperator; - unsigned Precedence; // Precedence if a binary op. + unsigned Precedence; // Precedence if a binary op. public: PrototypeAST(const std::string &name, const std::vector &args, bool isoperator = false, unsigned prec = 0) - : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} - + : Name(name), Args(args), isOperator(isoperator), Precedence(prec) {} + bool isUnaryOp() const { return isOperator && Args.size() == 1; } bool isBinaryOp() const { return isOperator && Args.size() == 2; } - + char getOperatorName() const { assert(isUnaryOp() || isBinaryOp()); - return Name[Name.size()-1]; + return Name[Name.size() - 1]; } - + unsigned getBinaryPrecedence() const { return Precedence; } - + Function *Codegen(); - + void CreateArgumentAllocas(Function *F); }; @@ -223,10 +249,10 @@ public: class FunctionAST { PrototypeAST *Proto; ExprAST *Body; + public: - FunctionAST(PrototypeAST *proto, ExprAST *body) - : Proto(proto), Body(body) {} - + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + Function *Codegen(); }; } // end anonymous namespace @@ -239,9 +265,7 @@ public: /// token the parser is looking at. getNextToken reads another token from the /// lexer and updates CurTok with its results. static int CurTok; -static int getNextToken() { - return CurTok = gettok(); -} +static int getNextToken() { return CurTok = gettok(); } /// BinopPrecedence - This holds the precedence for each binary operator that is /// defined. @@ -251,17 +275,27 @@ static std::map BinopPrecedence; static int GetTokPrecedence() { if (!isascii(CurTok)) return -1; - + // Make sure it's a declared binop. int TokPrec = BinopPrecedence[CurTok]; - if (TokPrec <= 0) return -1; + if (TokPrec <= 0) + return -1; return TokPrec; } /// Error* - These are little helper functions for error handling. -ExprAST *Error(const char *Str) { fprintf(stderr, "Error: %s\n", Str);return 0;} -PrototypeAST *ErrorP(const char *Str) { Error(Str); return 0; } -FunctionAST *ErrorF(const char *Str) { Error(Str); return 0; } +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} static ExprAST *ParseExpression(); @@ -270,22 +304,24 @@ static ExprAST *ParseExpression(); /// ::= identifier '(' expression* ')' static ExprAST *ParseIdentifierExpr() { std::string IdName = IdentifierStr; - - getNextToken(); // eat identifier. - + + getNextToken(); // eat identifier. + if (CurTok != '(') // Simple variable ref. return new VariableExprAST(IdName); - + // Call. - getNextToken(); // eat ( - std::vector Args; + getNextToken(); // eat ( + std::vector Args; if (CurTok != ')') { while (1) { ExprAST *Arg = ParseExpression(); - if (!Arg) return 0; + if (!Arg) + return 0; Args.push_back(Arg); - if (CurTok == ')') break; + if (CurTok == ')') + break; if (CurTok != ',') return Error("Expected ')' or ',' in argument list"); @@ -295,7 +331,7 @@ static ExprAST *ParseIdentifierExpr() { // Eat the ')'. getNextToken(); - + return new CallExprAST(IdName, Args); } @@ -308,126 +344,136 @@ static ExprAST *ParseNumberExpr() { /// parenexpr ::= '(' expression ')' static ExprAST *ParseParenExpr() { - getNextToken(); // eat (. + getNextToken(); // eat (. ExprAST *V = ParseExpression(); - if (!V) return 0; - + if (!V) + return 0; + if (CurTok != ')') return Error("expected ')'"); - getNextToken(); // eat ). + getNextToken(); // eat ). return V; } /// ifexpr ::= 'if' expression 'then' expression 'else' expression static ExprAST *ParseIfExpr() { - getNextToken(); // eat the if. - + getNextToken(); // eat the if. + // condition. ExprAST *Cond = ParseExpression(); - if (!Cond) return 0; - + if (!Cond) + return 0; + if (CurTok != tok_then) return Error("expected then"); - getNextToken(); // eat the then - + getNextToken(); // eat the then + ExprAST *Then = ParseExpression(); - if (Then == 0) return 0; - + if (Then == 0) + return 0; + if (CurTok != tok_else) return Error("expected else"); - + getNextToken(); - + ExprAST *Else = ParseExpression(); - if (!Else) return 0; - + if (!Else) + return 0; + return new IfExprAST(Cond, Then, Else); } /// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression static ExprAST *ParseForExpr() { - getNextToken(); // eat the for. + getNextToken(); // eat the for. if (CurTok != tok_identifier) return Error("expected identifier after for"); - + std::string IdName = IdentifierStr; - getNextToken(); // eat identifier. - + getNextToken(); // eat identifier. + if (CurTok != '=') return Error("expected '=' after for"); - getNextToken(); // eat '='. - - + getNextToken(); // eat '='. + ExprAST *Start = ParseExpression(); - if (Start == 0) return 0; + if (Start == 0) + return 0; if (CurTok != ',') return Error("expected ',' after for start value"); getNextToken(); - + ExprAST *End = ParseExpression(); - if (End == 0) return 0; - + if (End == 0) + return 0; + // The step value is optional. ExprAST *Step = 0; if (CurTok == ',') { getNextToken(); Step = ParseExpression(); - if (Step == 0) return 0; + if (Step == 0) + return 0; } - + if (CurTok != tok_in) return Error("expected 'in' after for"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; + if (Body == 0) + return 0; return new ForExprAST(IdName, Start, End, Step, Body); } -/// varexpr ::= 'var' identifier ('=' expression)? +/// varexpr ::= 'var' identifier ('=' expression)? // (',' identifier ('=' expression)?)* 'in' expression static ExprAST *ParseVarExpr() { - getNextToken(); // eat the var. + getNextToken(); // eat the var. - std::vector > VarNames; + std::vector > VarNames; // At least one variable name is required. if (CurTok != tok_identifier) return Error("expected identifier after var"); - + while (1) { std::string Name = IdentifierStr; - getNextToken(); // eat identifier. + getNextToken(); // eat identifier. // Read the optional initializer. ExprAST *Init = 0; if (CurTok == '=') { getNextToken(); // eat the '='. - + Init = ParseExpression(); - if (Init == 0) return 0; + if (Init == 0) + return 0; } - + VarNames.push_back(std::make_pair(Name, Init)); - + // End of var list, exit loop. - if (CurTok != ',') break; + if (CurTok != ',') + break; getNextToken(); // eat the ','. - + if (CurTok != tok_identifier) return Error("expected identifier list after var"); } - + // At this point, we have to have 'in'. if (CurTok != tok_in) return Error("expected 'in' keyword after 'var'"); - getNextToken(); // eat 'in'. - + getNextToken(); // eat 'in'. + ExprAST *Body = ParseExpression(); - if (Body == 0) return 0; - + if (Body == 0) + return 0; + return new VarExprAST(VarNames, Body); } @@ -440,13 +486,20 @@ static ExprAST *ParseVarExpr() { /// ::= varexpr static ExprAST *ParsePrimary() { switch (CurTok) { - default: return Error("unknown token when expecting an expression"); - case tok_identifier: return ParseIdentifierExpr(); - case tok_number: return ParseNumberExpr(); - case '(': return ParseParenExpr(); - case tok_if: return ParseIfExpr(); - case tok_for: return ParseForExpr(); - case tok_var: return ParseVarExpr(); + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); + case tok_var: + return ParseVarExpr(); } } @@ -457,7 +510,7 @@ static ExprAST *ParseUnary() { // If the current token is not an operator, it must be a primary expr. if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') return ParsePrimary(); - + // If this is a unary operator, read it. int Opc = CurTok; getNextToken(); @@ -472,28 +525,30 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { // If this is a binop, find its precedence. while (1) { int TokPrec = GetTokPrecedence(); - + // If this is a binop that binds at least as tightly as the current binop, // consume it, otherwise we are done. if (TokPrec < ExprPrec) return LHS; - + // Okay, we know this is a binop. int BinOp = CurTok; - getNextToken(); // eat binop - + getNextToken(); // eat binop + // Parse the unary expression after the binary operator. ExprAST *RHS = ParseUnary(); - if (!RHS) return 0; - + if (!RHS) + return 0; + // If BinOp binds less tightly with RHS than the operator after RHS, let // the pending operator take RHS as its LHS. int NextPrec = GetTokPrecedence(); if (TokPrec < NextPrec) { - RHS = ParseBinOpRHS(TokPrec+1, RHS); - if (RHS == 0) return 0; + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; } - + // Merge LHS/RHS. LHS = new BinaryExprAST(BinOp, LHS, RHS); } @@ -504,8 +559,9 @@ static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { /// static ExprAST *ParseExpression() { ExprAST *LHS = ParseUnary(); - if (!LHS) return 0; - + if (!LHS) + return 0; + return ParseBinOpRHS(0, LHS); } @@ -515,10 +571,10 @@ static ExprAST *ParseExpression() { /// ::= unary LETTER (id) static PrototypeAST *ParsePrototype() { std::string FnName; - + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. unsigned BinaryPrecedence = 30; - + switch (CurTok) { default: return ErrorP("Expected function name in prototype"); @@ -544,7 +600,7 @@ static PrototypeAST *ParsePrototype() { FnName += (char)CurTok; Kind = 2; getNextToken(); - + // Read the precedence if present. if (CurTok == tok_number) { if (NumVal < 1 || NumVal > 100) @@ -554,31 +610,32 @@ static PrototypeAST *ParsePrototype() { } break; } - + if (CurTok != '(') return ErrorP("Expected '(' in prototype"); - + std::vector ArgNames; while (getNextToken() == tok_identifier) ArgNames.push_back(IdentifierStr); if (CurTok != ')') return ErrorP("Expected ')' in prototype"); - + // success. - getNextToken(); // eat ')'. - + getNextToken(); // eat ')'. + // Verify right number of names for operator. if (Kind && ArgNames.size() != Kind) return ErrorP("Invalid number of operands for operator"); - + return new PrototypeAST(FnName, ArgNames, Kind != 0, BinaryPrecedence); } /// definition ::= 'def' prototype expression static FunctionAST *ParseDefinition() { - getNextToken(); // eat def. + getNextToken(); // eat def. PrototypeAST *Proto = ParsePrototype(); - if (Proto == 0) return 0; + if (Proto == 0) + return 0; if (ExprAST *E = ParseExpression()) return new FunctionAST(Proto, E); @@ -597,7 +654,7 @@ static FunctionAST *ParseTopLevelExpr() { /// external ::= 'extern' prototype static PrototypeAST *ParseExtern() { - getNextToken(); // eat extern. + getNextToken(); // eat extern. return ParsePrototype(); } @@ -607,17 +664,20 @@ static PrototypeAST *ParseExtern() { static Module *TheModule; static IRBuilder<> Builder(getGlobalContext()); -static std::map NamedValues; +static std::map NamedValues; static FunctionPassManager *TheFPM; -Value *ErrorV(const char *Str) { Error(Str); return 0; } +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} /// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of /// the function. This is used for mutable variables etc. static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) { IRBuilder<> TmpB(&TheFunction->getEntryBlock(), - TheFunction->getEntryBlock().begin()); + TheFunction->getEntryBlock().begin()); return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, VarName.c_str()); } @@ -629,7 +689,8 @@ Value *NumberExprAST::Codegen() { Value *VariableExprAST::Codegen() { // Look this variable up in the function. Value *V = NamedValues[Name]; - if (V == 0) return ErrorV("Unknown variable name"); + if (V == 0) + return ErrorV("Unknown variable name"); // Load the value. return Builder.CreateLoad(V, Name.c_str()); @@ -637,12 +698,13 @@ Value *VariableExprAST::Codegen() { Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); - if (OperandV == 0) return 0; - - Function *F = TheModule->getFunction(std::string("unary")+Opcode); + if (OperandV == 0) + return 0; + + Function *F = TheModule->getFunction(std::string("unary") + Opcode); if (F == 0) return ErrorV("Unknown unary operator"); - + return Builder.CreateCall(F, OperandV, "unop"); } @@ -650,42 +712,49 @@ Value *BinaryExprAST::Codegen() { // Special case '=' because we don't want to emit the LHS as an expression. if (Op == '=') { // Assignment requires the LHS to be an identifier. - VariableExprAST *LHSE = dynamic_cast(LHS); + VariableExprAST *LHSE = dynamic_cast(LHS); if (!LHSE) return ErrorV("destination of '=' must be a variable"); // Codegen the RHS. Value *Val = RHS->Codegen(); - if (Val == 0) return 0; + if (Val == 0) + return 0; // Look up the name. Value *Variable = NamedValues[LHSE->getName()]; - if (Variable == 0) return ErrorV("Unknown variable name"); + if (Variable == 0) + return ErrorV("Unknown variable name"); Builder.CreateStore(Val, Variable); return Val; } - + Value *L = LHS->Codegen(); Value *R = RHS->Codegen(); - if (L == 0 || R == 0) return 0; - + if (L == 0 || R == 0) + return 0; + switch (Op) { - case '+': return Builder.CreateFAdd(L, R, "addtmp"); - case '-': return Builder.CreateFSub(L, R, "subtmp"); - case '*': return Builder.CreateFMul(L, R, "multmp"); + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); case '<': L = Builder.CreateFCmpULT(L, R, "cmptmp"); // Convert bool 0/1 to double 0.0 or 1.0 return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), "booltmp"); - default: break; + default: + break; } - + // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. - Function *F = TheModule->getFunction(std::string("binary")+Op); + Function *F = TheModule->getFunction(std::string("binary") + Op); assert(F && "binary operator not found!"); - + Value *Ops[] = { L, R }; return Builder.CreateCall(F, Ops, "binop"); } @@ -695,66 +764,70 @@ Value *CallExprAST::Codegen() { Function *CalleeF = TheModule->getFunction(Callee); if (CalleeF == 0) return ErrorV("Unknown function referenced"); - + // If argument mismatch error. if (CalleeF->arg_size() != Args.size()) return ErrorV("Incorrect # arguments passed"); - std::vector ArgsV; + std::vector ArgsV; for (unsigned i = 0, e = Args.size(); i != e; ++i) { ArgsV.push_back(Args[i]->Codegen()); - if (ArgsV.back() == 0) return 0; + if (ArgsV.back() == 0) + return 0; } - + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); } Value *IfExprAST::Codegen() { Value *CondV = Cond->Codegen(); - if (CondV == 0) return 0; - + if (CondV == 0) + return 0; + // Convert condition to a bool by comparing equal to 0.0. - CondV = Builder.CreateFCmpONE(CondV, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "ifcond"); - + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + Function *TheFunction = Builder.GetInsertBlock()->getParent(); - + // Create blocks for the then and else cases. Insert the 'then' block at the // end of the function. - BasicBlock *ThenBB = BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); - + Builder.CreateCondBr(CondV, ThenBB, ElseBB); - + // Emit then value. Builder.SetInsertPoint(ThenBB); - + Value *ThenV = Then->Codegen(); - if (ThenV == 0) return 0; - + if (ThenV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Then' can change the current block, update ThenBB for the PHI. ThenBB = Builder.GetInsertBlock(); - + // Emit else block. TheFunction->getBasicBlockList().push_back(ElseBB); Builder.SetInsertPoint(ElseBB); - + Value *ElseV = Else->Codegen(); - if (ElseV == 0) return 0; - + if (ElseV == 0) + return 0; + Builder.CreateBr(MergeBB); // Codegen of 'Else' can change the current block, update ElseBB for the PHI. ElseBB = Builder.GetInsertBlock(); - + // Emit merge block. TheFunction->getBasicBlockList().push_back(MergeBB); Builder.SetInsertPoint(MergeBB); - PHINode *PN = Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, - "iftmp"); - + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + PN->addIncoming(ThenV, ThenBB); PN->addIncoming(ElseV, ElseBB); return PN; @@ -767,7 +840,7 @@ Value *ForExprAST::Codegen() { // start = startexpr // store start -> var // goto loop - // loop: + // loop: // ... // bodyexpr // ... @@ -780,95 +853,98 @@ Value *ForExprAST::Codegen() { // store nextvar -> var // br endcond, loop, endloop // outloop: - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Create an alloca for the variable in the entry block. AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); - + // Emit the start code first, without 'variable' in scope. Value *StartVal = Start->Codegen(); - if (StartVal == 0) return 0; - + if (StartVal == 0) + return 0; + // Store the value into the alloca. Builder.CreateStore(StartVal, Alloca); - + // Make the new basic block for the loop header, inserting after current // block. - BasicBlock *LoopBB = BasicBlock::Create(getGlobalContext(), "loop", TheFunction); - + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + // Insert an explicit fall through from the current block to the LoopBB. Builder.CreateBr(LoopBB); // Start insertion in LoopBB. Builder.SetInsertPoint(LoopBB); - + // Within the loop, the variable is defined equal to the PHI node. If it // shadows an existing variable, we have to restore it, so save it now. AllocaInst *OldVal = NamedValues[VarName]; NamedValues[VarName] = Alloca; - + // Emit the body of the loop. This, like any other expr, can change the // current BB. Note that we ignore the value computed by the body, but don't // allow an error. if (Body->Codegen() == 0) return 0; - + // Emit the step value. Value *StepVal; if (Step) { StepVal = Step->Codegen(); - if (StepVal == 0) return 0; + if (StepVal == 0) + return 0; } else { // If not specified, use 1.0. StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); } - + // Compute the end condition. Value *EndCond = End->Codegen(); - if (EndCond == 0) return EndCond; - + if (EndCond == 0) + return EndCond; + // Reload, increment, and restore the alloca. This handles the case where // the body of the loop mutates the variable. Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); Builder.CreateStore(NextVar, Alloca); - + // Convert condition to a bool by comparing equal to 0.0. - EndCond = Builder.CreateFCmpONE(EndCond, - ConstantFP::get(getGlobalContext(), APFloat(0.0)), - "loopcond"); - + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + // Create the "after loop" block and insert it. - BasicBlock *AfterBB = BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); - + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + // Insert the conditional branch into the end of LoopEndBB. Builder.CreateCondBr(EndCond, LoopBB, AfterBB); - + // Any new code will be inserted in AfterBB. Builder.SetInsertPoint(AfterBB); - + // Restore the unshadowed variable. if (OldVal) NamedValues[VarName] = OldVal; else NamedValues.erase(VarName); - // for expr always returns 0.0. return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); } Value *VarExprAST::Codegen() { std::vector OldBindings; - + Function *TheFunction = Builder.GetInsertBlock()->getParent(); // Register all variables and emit their initializer. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { const std::string &VarName = VarNames[i].first; ExprAST *Init = VarNames[i].second; - + // Emit the initializer before adding the variable to scope, this prevents // the initializer from referencing the variable itself, and permits stuff // like this: @@ -877,26 +953,28 @@ Value *VarExprAST::Codegen() { Value *InitVal; if (Init) { InitVal = Init->Codegen(); - if (InitVal == 0) return 0; + if (InitVal == 0) + return 0; } else { // If not specified, use 0.0. InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); } - + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); Builder.CreateStore(InitVal, Alloca); // Remember the old variable binding so that we can restore the binding when // we unrecurse. OldBindings.push_back(NamedValues[VarName]); - + // Remember this binding. NamedValues[VarName] = Alloca; } - + // Codegen the body, now that all vars are in scope. Value *BodyVal = Body->Codegen(); - if (BodyVal == 0) return 0; - + if (BodyVal == 0) + return 0; + // Pop all our variables from scope. for (unsigned i = 0, e = VarNames.size(); i != e; ++i) NamedValues[VarNames[i].first] = OldBindings[i]; @@ -907,39 +985,40 @@ Value *VarExprAST::Codegen() { Function *PrototypeAST::Codegen() { // Make the function type: double(double,double) etc. - std::vector Doubles(Args.size(), - Type::getDoubleTy(getGlobalContext())); - FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()), - Doubles, false); - - Function *F = Function::Create(FT, Function::ExternalLinkage, Name, TheModule); - + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + // If F conflicted, there was already something named 'Name'. If it has a // body, don't allow redefinition or reextern. if (F->getName() != Name) { // Delete the one we just made and get the existing one. F->eraseFromParent(); F = TheModule->getFunction(Name); - + // If F already has a body, reject this. if (!F->empty()) { ErrorF("redefinition of function"); return 0; } - + // If F took a different number of args, reject. if (F->arg_size() != Args.size()) { ErrorF("redefinition of function with different # args"); return 0; } } - + // Set names for all arguments. unsigned Idx = 0; for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); ++AI, ++Idx) AI->setName(Args[Idx]); - + return F; } @@ -961,19 +1040,19 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) { Function *FunctionAST::Codegen() { NamedValues.clear(); - + Function *TheFunction = Proto->Codegen(); if (TheFunction == 0) return 0; - + // If this is an operator, install it. if (Proto->isBinaryOp()) BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); - + // Create a new basic block to start insertion into. BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); Builder.SetInsertPoint(BB); - + // Add all arguments to the symbol table and create their allocas. Proto->CreateArgumentAllocas(TheFunction); @@ -986,10 +1065,10 @@ Function *FunctionAST::Codegen() { // Optimize the function. TheFPM->run(*TheFunction); - + return TheFunction; } - + // Error reading body, remove function. TheFunction->eraseFromParent(); @@ -1032,9 +1111,10 @@ static void HandleTopLevelExpression() { // Evaluate a top-level expression into an anonymous function. if (FunctionAST *F = ParseTopLevelExpr()) { if (Function *LF = F->Codegen()) { + TheExecutionEngine->finalizeObject(); // JIT the function, returning a function pointer. void *FPtr = TheExecutionEngine->getPointerToFunction(LF); - + // Cast it to the right type (takes no arguments, returns a double) so we // can call it as a native function. double (*FP)() = (double (*)())(intptr_t)FPtr; @@ -1051,11 +1131,20 @@ static void MainLoop() { while (1) { fprintf(stderr, "ready> "); switch (CurTok) { - case tok_eof: return; - case ';': getNextToken(); break; // ignore top-level semicolons. - case tok_def: HandleDefinition(); break; - case tok_extern: HandleExtern(); break; - default: HandleTopLevelExpression(); break; + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; } } } @@ -1065,15 +1154,13 @@ static void MainLoop() { //===----------------------------------------------------------------------===// /// putchard - putchar that takes a double and returns 0. -extern "C" -double putchard(double X) { +extern "C" double putchard(double X) { putchar((char)X); return 0; } /// printd - printf that takes a double prints it as "%f\n", returning 0. -extern "C" -double printd(double X) { +extern "C" double printd(double X) { printf("%f\n", X); return 0; } @@ -1084,6 +1171,8 @@ double printd(double X) { int main() { InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); // Install standard binary operators. @@ -1092,18 +1181,23 @@ int main() { BinopPrecedence['<'] = 10; BinopPrecedence['+'] = 20; BinopPrecedence['-'] = 20; - BinopPrecedence['*'] = 40; // highest. + BinopPrecedence['*'] = 40; // highest. // Prime the first token. fprintf(stderr, "ready> "); getNextToken(); // Make the module, which holds all the code. - TheModule = new Module("my cool jit", Context); + std::unique_ptr Owner = make_unique("my cool jit", Context); + TheModule = Owner.get(); // Create the JIT. This takes ownership of the module. std::string ErrStr; - TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); + TheExecutionEngine = + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); if (!TheExecutionEngine) { fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); exit(1); @@ -1114,7 +1208,7 @@ int main() { // Set up the optimizer pipeline. Start with registering info about how the // target lays out data structures. TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); - OurFPM.add(new DataLayoutPass(TheModule)); + OurFPM.add(new DataLayoutPass()); // Provide basic AliasAnalysis support for GVN. OurFPM.add(createBasicAliasAnalysisPass()); // Promote allocas to registers. diff --git a/examples/Kaleidoscope/Chapter8/CMakeLists.txt b/examples/Kaleidoscope/Chapter8/CMakeLists.txt new file mode 100644 index 0000000..1a95772 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/CMakeLists.txt @@ -0,0 +1,18 @@ +set(LLVM_LINK_COMPONENTS + Analysis + Core + ExecutionEngine + InstCombine + MC + ScalarOpts + Support + TransformUtils + native + mcjit + ) + +set(LLVM_REQUIRES_RTTI 1) + +add_kaleidoscope_chapter(Kaleidoscope-Ch8 + toy.cpp + ) diff --git a/examples/Kaleidoscope/Chapter8/Makefile b/examples/Kaleidoscope/Chapter8/Makefile new file mode 100644 index 0000000..8e4d4221 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/Makefile @@ -0,0 +1,16 @@ +##===- examples/Kaleidoscope/Chapter7/Makefile -------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +TOOLNAME = Kaleidoscope-Ch8 +EXAMPLE_TOOL = 1 +REQUIRES_RTTI := 1 + +LINK_COMPONENTS := core mcjit native + +include $(LEVEL)/Makefile.common diff --git a/examples/Kaleidoscope/Chapter8/toy.cpp b/examples/Kaleidoscope/Chapter8/toy.cpp new file mode 100644 index 0000000..961a0f8 --- /dev/null +++ b/examples/Kaleidoscope/Chapter8/toy.cpp @@ -0,0 +1,1494 @@ +#include "llvm/ADT/Triple.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/ExecutionEngine/MCJIT.h" +#include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/PassManager.h" +#include "llvm/Support/Host.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Transforms/Scalar.h" +#include +#include +#include +#include +#include +#include +using namespace llvm; + +//===----------------------------------------------------------------------===// +// Lexer +//===----------------------------------------------------------------------===// + +// The lexer returns tokens [0-255] if it is an unknown character, otherwise one +// of these for known things. +enum Token { + tok_eof = -1, + + // commands + tok_def = -2, + tok_extern = -3, + + // primary + tok_identifier = -4, + tok_number = -5, + + // control + tok_if = -6, + tok_then = -7, + tok_else = -8, + tok_for = -9, + tok_in = -10, + + // operators + tok_binary = -11, + tok_unary = -12, + + // var definition + tok_var = -13 +}; + +std::string getTokName(int Tok) { + switch (Tok) { + case tok_eof: + return "eof"; + case tok_def: + return "def"; + case tok_extern: + return "extern"; + case tok_identifier: + return "identifier"; + case tok_number: + return "number"; + case tok_if: + return "if"; + case tok_then: + return "then"; + case tok_else: + return "else"; + case tok_for: + return "for"; + case tok_in: + return "in"; + case tok_binary: + return "binary"; + case tok_unary: + return "unary"; + case tok_var: + return "var"; + } + return std::string(1, (char)Tok); +} + +namespace { +class PrototypeAST; +class ExprAST; +} +static IRBuilder<> Builder(getGlobalContext()); +struct DebugInfo { + DICompileUnit TheCU; + DIType DblTy; + std::vector LexicalBlocks; + std::map FnScopeMap; + + void emitLocation(ExprAST *AST); + DIType getDoubleTy(); +} KSDbgInfo; + +static std::string IdentifierStr; // Filled in if tok_identifier +static double NumVal; // Filled in if tok_number +struct SourceLocation { + int Line; + int Col; +}; +static SourceLocation CurLoc; +static SourceLocation LexLoc = { 1, 0 }; + +static int advance() { + int LastChar = getchar(); + + if (LastChar == '\n' || LastChar == '\r') { + LexLoc.Line++; + LexLoc.Col = 0; + } else + LexLoc.Col++; + return LastChar; +} + +/// gettok - Return the next token from standard input. +static int gettok() { + static int LastChar = ' '; + + // Skip any whitespace. + while (isspace(LastChar)) + LastChar = advance(); + + CurLoc = LexLoc; + + if (isalpha(LastChar)) { // identifier: [a-zA-Z][a-zA-Z0-9]* + IdentifierStr = LastChar; + while (isalnum((LastChar = advance()))) + IdentifierStr += LastChar; + + if (IdentifierStr == "def") + return tok_def; + if (IdentifierStr == "extern") + return tok_extern; + if (IdentifierStr == "if") + return tok_if; + if (IdentifierStr == "then") + return tok_then; + if (IdentifierStr == "else") + return tok_else; + if (IdentifierStr == "for") + return tok_for; + if (IdentifierStr == "in") + return tok_in; + if (IdentifierStr == "binary") + return tok_binary; + if (IdentifierStr == "unary") + return tok_unary; + if (IdentifierStr == "var") + return tok_var; + return tok_identifier; + } + + if (isdigit(LastChar) || LastChar == '.') { // Number: [0-9.]+ + std::string NumStr; + do { + NumStr += LastChar; + LastChar = advance(); + } while (isdigit(LastChar) || LastChar == '.'); + + NumVal = strtod(NumStr.c_str(), 0); + return tok_number; + } + + if (LastChar == '#') { + // Comment until end of line. + do + LastChar = advance(); + while (LastChar != EOF && LastChar != '\n' && LastChar != '\r'); + + if (LastChar != EOF) + return gettok(); + } + + // Check for end of file. Don't eat the EOF. + if (LastChar == EOF) + return tok_eof; + + // Otherwise, just return the character as its ascii value. + int ThisChar = LastChar; + LastChar = advance(); + return ThisChar; +} + +//===----------------------------------------------------------------------===// +// Abstract Syntax Tree (aka Parse Tree) +//===----------------------------------------------------------------------===// +namespace { + +std::ostream &indent(std::ostream &O, int size) { + return O << std::string(size, ' '); +} + +/// ExprAST - Base class for all expression nodes. +class ExprAST { + SourceLocation Loc; + +public: + int getLine() const { return Loc.Line; } + int getCol() const { return Loc.Col; } + ExprAST(SourceLocation Loc = CurLoc) : Loc(Loc) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + return out << ':' << getLine() << ':' << getCol() << '\n'; + } + virtual ~ExprAST() {} + virtual Value *Codegen() = 0; +}; + +/// NumberExprAST - Expression class for numeric literals like "1.0". +class NumberExprAST : public ExprAST { + double Val; + +public: + NumberExprAST(double val) : Val(val) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + return ExprAST::dump(out << Val, ind); + } + virtual Value *Codegen(); +}; + +/// VariableExprAST - Expression class for referencing a variable, like "a". +class VariableExprAST : public ExprAST { + std::string Name; + +public: + VariableExprAST(SourceLocation Loc, const std::string &name) + : ExprAST(Loc), Name(name) {} + const std::string &getName() const { return Name; } + virtual std::ostream &dump(std::ostream &out, int ind) { + return ExprAST::dump(out << Name, ind); + } + virtual Value *Codegen(); +}; + +/// UnaryExprAST - Expression class for a unary operator. +class UnaryExprAST : public ExprAST { + char Opcode; + ExprAST *Operand; + +public: + UnaryExprAST(char opcode, ExprAST *operand) + : Opcode(opcode), Operand(operand) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "unary" << Opcode, ind); + Operand->dump(out, ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// BinaryExprAST - Expression class for a binary operator. +class BinaryExprAST : public ExprAST { + char Op; + ExprAST *LHS, *RHS; + +public: + BinaryExprAST(SourceLocation Loc, char op, ExprAST *lhs, ExprAST *rhs) + : ExprAST(Loc), Op(op), LHS(lhs), RHS(rhs) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "binary" << Op, ind); + LHS->dump(indent(out, ind) << "LHS:", ind + 1); + RHS->dump(indent(out, ind) << "RHS:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// CallExprAST - Expression class for function calls. +class CallExprAST : public ExprAST { + std::string Callee; + std::vector Args; + +public: + CallExprAST(SourceLocation Loc, const std::string &callee, + std::vector &args) + : ExprAST(Loc), Callee(callee), Args(args) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "call " << Callee, ind); + for (ExprAST *Arg : Args) + Arg->dump(indent(out, ind + 1), ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// IfExprAST - Expression class for if/then/else. +class IfExprAST : public ExprAST { + ExprAST *Cond, *Then, *Else; + +public: + IfExprAST(SourceLocation Loc, ExprAST *cond, ExprAST *then, ExprAST *_else) + : ExprAST(Loc), Cond(cond), Then(then), Else(_else) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "if", ind); + Cond->dump(indent(out, ind) << "Cond:", ind + 1); + Then->dump(indent(out, ind) << "Then:", ind + 1); + Else->dump(indent(out, ind) << "Else:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// ForExprAST - Expression class for for/in. +class ForExprAST : public ExprAST { + std::string VarName; + ExprAST *Start, *End, *Step, *Body; + +public: + ForExprAST(const std::string &varname, ExprAST *start, ExprAST *end, + ExprAST *step, ExprAST *body) + : VarName(varname), Start(start), End(end), Step(step), Body(body) {} + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "for", ind); + Start->dump(indent(out, ind) << "Cond:", ind + 1); + End->dump(indent(out, ind) << "End:", ind + 1); + Step->dump(indent(out, ind) << "Step:", ind + 1); + Body->dump(indent(out, ind) << "Body:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// VarExprAST - Expression class for var/in +class VarExprAST : public ExprAST { + std::vector > VarNames; + ExprAST *Body; + +public: + VarExprAST(const std::vector > &varnames, + ExprAST *body) + : VarNames(varnames), Body(body) {} + + virtual std::ostream &dump(std::ostream &out, int ind) { + ExprAST::dump(out << "var", ind); + for (const auto &NamedVar : VarNames) + NamedVar.second->dump(indent(out, ind) << NamedVar.first << ':', ind + 1); + Body->dump(indent(out, ind) << "Body:", ind + 1); + return out; + } + virtual Value *Codegen(); +}; + +/// PrototypeAST - This class represents the "prototype" for a function, +/// which captures its argument names as well as if it is an operator. +class PrototypeAST { + std::string Name; + std::vector Args; + bool isOperator; + unsigned Precedence; // Precedence if a binary op. + int Line; + +public: + PrototypeAST(SourceLocation Loc, const std::string &name, + const std::vector &args, bool isoperator = false, + unsigned prec = 0) + : Name(name), Args(args), isOperator(isoperator), Precedence(prec), + Line(Loc.Line) {} + + bool isUnaryOp() const { return isOperator && Args.size() == 1; } + bool isBinaryOp() const { return isOperator && Args.size() == 2; } + + char getOperatorName() const { + assert(isUnaryOp() || isBinaryOp()); + return Name[Name.size() - 1]; + } + + unsigned getBinaryPrecedence() const { return Precedence; } + + Function *Codegen(); + + void CreateArgumentAllocas(Function *F); + const std::vector &getArgs() const { return Args; } +}; + +/// FunctionAST - This class represents a function definition itself. +class FunctionAST { + PrototypeAST *Proto; + ExprAST *Body; + +public: + FunctionAST(PrototypeAST *proto, ExprAST *body) : Proto(proto), Body(body) {} + + std::ostream &dump(std::ostream &out, int ind) { + indent(out, ind) << "FunctionAST\n"; + ++ind; + indent(out, ind) << "Body:"; + return Body ? Body->dump(out, ind) : out << "null\n"; + } + + Function *Codegen(); +}; +} // end anonymous namespace + +//===----------------------------------------------------------------------===// +// Parser +//===----------------------------------------------------------------------===// + +/// CurTok/getNextToken - Provide a simple token buffer. CurTok is the current +/// token the parser is looking at. getNextToken reads another token from the +/// lexer and updates CurTok with its results. +static int CurTok; +static int getNextToken() { return CurTok = gettok(); } + +/// BinopPrecedence - This holds the precedence for each binary operator that is +/// defined. +static std::map BinopPrecedence; + +/// GetTokPrecedence - Get the precedence of the pending binary operator token. +static int GetTokPrecedence() { + if (!isascii(CurTok)) + return -1; + + // Make sure it's a declared binop. + int TokPrec = BinopPrecedence[CurTok]; + if (TokPrec <= 0) + return -1; + return TokPrec; +} + +/// Error* - These are little helper functions for error handling. +ExprAST *Error(const char *Str) { + fprintf(stderr, "Error: %s\n", Str); + return 0; +} +PrototypeAST *ErrorP(const char *Str) { + Error(Str); + return 0; +} +FunctionAST *ErrorF(const char *Str) { + Error(Str); + return 0; +} + +static ExprAST *ParseExpression(); + +/// identifierexpr +/// ::= identifier +/// ::= identifier '(' expression* ')' +static ExprAST *ParseIdentifierExpr() { + std::string IdName = IdentifierStr; + + SourceLocation LitLoc = CurLoc; + + getNextToken(); // eat identifier. + + if (CurTok != '(') // Simple variable ref. + return new VariableExprAST(LitLoc, IdName); + + // Call. + getNextToken(); // eat ( + std::vector Args; + if (CurTok != ')') { + while (1) { + ExprAST *Arg = ParseExpression(); + if (!Arg) + return 0; + Args.push_back(Arg); + + if (CurTok == ')') + break; + + if (CurTok != ',') + return Error("Expected ')' or ',' in argument list"); + getNextToken(); + } + } + + // Eat the ')'. + getNextToken(); + + return new CallExprAST(LitLoc, IdName, Args); +} + +/// numberexpr ::= number +static ExprAST *ParseNumberExpr() { + ExprAST *Result = new NumberExprAST(NumVal); + getNextToken(); // consume the number + return Result; +} + +/// parenexpr ::= '(' expression ')' +static ExprAST *ParseParenExpr() { + getNextToken(); // eat (. + ExprAST *V = ParseExpression(); + if (!V) + return 0; + + if (CurTok != ')') + return Error("expected ')'"); + getNextToken(); // eat ). + return V; +} + +/// ifexpr ::= 'if' expression 'then' expression 'else' expression +static ExprAST *ParseIfExpr() { + SourceLocation IfLoc = CurLoc; + + getNextToken(); // eat the if. + + // condition. + ExprAST *Cond = ParseExpression(); + if (!Cond) + return 0; + + if (CurTok != tok_then) + return Error("expected then"); + getNextToken(); // eat the then + + ExprAST *Then = ParseExpression(); + if (Then == 0) + return 0; + + if (CurTok != tok_else) + return Error("expected else"); + + getNextToken(); + + ExprAST *Else = ParseExpression(); + if (!Else) + return 0; + + return new IfExprAST(IfLoc, Cond, Then, Else); +} + +/// forexpr ::= 'for' identifier '=' expr ',' expr (',' expr)? 'in' expression +static ExprAST *ParseForExpr() { + getNextToken(); // eat the for. + + if (CurTok != tok_identifier) + return Error("expected identifier after for"); + + std::string IdName = IdentifierStr; + getNextToken(); // eat identifier. + + if (CurTok != '=') + return Error("expected '=' after for"); + getNextToken(); // eat '='. + + ExprAST *Start = ParseExpression(); + if (Start == 0) + return 0; + if (CurTok != ',') + return Error("expected ',' after for start value"); + getNextToken(); + + ExprAST *End = ParseExpression(); + if (End == 0) + return 0; + + // The step value is optional. + ExprAST *Step = 0; + if (CurTok == ',') { + getNextToken(); + Step = ParseExpression(); + if (Step == 0) + return 0; + } + + if (CurTok != tok_in) + return Error("expected 'in' after for"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) + return 0; + + return new ForExprAST(IdName, Start, End, Step, Body); +} + +/// varexpr ::= 'var' identifier ('=' expression)? +// (',' identifier ('=' expression)?)* 'in' expression +static ExprAST *ParseVarExpr() { + getNextToken(); // eat the var. + + std::vector > VarNames; + + // At least one variable name is required. + if (CurTok != tok_identifier) + return Error("expected identifier after var"); + + while (1) { + std::string Name = IdentifierStr; + getNextToken(); // eat identifier. + + // Read the optional initializer. + ExprAST *Init = 0; + if (CurTok == '=') { + getNextToken(); // eat the '='. + + Init = ParseExpression(); + if (Init == 0) + return 0; + } + + VarNames.push_back(std::make_pair(Name, Init)); + + // End of var list, exit loop. + if (CurTok != ',') + break; + getNextToken(); // eat the ','. + + if (CurTok != tok_identifier) + return Error("expected identifier list after var"); + } + + // At this point, we have to have 'in'. + if (CurTok != tok_in) + return Error("expected 'in' keyword after 'var'"); + getNextToken(); // eat 'in'. + + ExprAST *Body = ParseExpression(); + if (Body == 0) + return 0; + + return new VarExprAST(VarNames, Body); +} + +/// primary +/// ::= identifierexpr +/// ::= numberexpr +/// ::= parenexpr +/// ::= ifexpr +/// ::= forexpr +/// ::= varexpr +static ExprAST *ParsePrimary() { + switch (CurTok) { + default: + return Error("unknown token when expecting an expression"); + case tok_identifier: + return ParseIdentifierExpr(); + case tok_number: + return ParseNumberExpr(); + case '(': + return ParseParenExpr(); + case tok_if: + return ParseIfExpr(); + case tok_for: + return ParseForExpr(); + case tok_var: + return ParseVarExpr(); + } +} + +/// unary +/// ::= primary +/// ::= '!' unary +static ExprAST *ParseUnary() { + // If the current token is not an operator, it must be a primary expr. + if (!isascii(CurTok) || CurTok == '(' || CurTok == ',') + return ParsePrimary(); + + // If this is a unary operator, read it. + int Opc = CurTok; + getNextToken(); + if (ExprAST *Operand = ParseUnary()) + return new UnaryExprAST(Opc, Operand); + return 0; +} + +/// binoprhs +/// ::= ('+' unary)* +static ExprAST *ParseBinOpRHS(int ExprPrec, ExprAST *LHS) { + // If this is a binop, find its precedence. + while (1) { + int TokPrec = GetTokPrecedence(); + + // If this is a binop that binds at least as tightly as the current binop, + // consume it, otherwise we are done. + if (TokPrec < ExprPrec) + return LHS; + + // Okay, we know this is a binop. + int BinOp = CurTok; + SourceLocation BinLoc = CurLoc; + getNextToken(); // eat binop + + // Parse the unary expression after the binary operator. + ExprAST *RHS = ParseUnary(); + if (!RHS) + return 0; + + // If BinOp binds less tightly with RHS than the operator after RHS, let + // the pending operator take RHS as its LHS. + int NextPrec = GetTokPrecedence(); + if (TokPrec < NextPrec) { + RHS = ParseBinOpRHS(TokPrec + 1, RHS); + if (RHS == 0) + return 0; + } + + // Merge LHS/RHS. + LHS = new BinaryExprAST(BinLoc, BinOp, LHS, RHS); + } +} + +/// expression +/// ::= unary binoprhs +/// +static ExprAST *ParseExpression() { + ExprAST *LHS = ParseUnary(); + if (!LHS) + return 0; + + return ParseBinOpRHS(0, LHS); +} + +/// prototype +/// ::= id '(' id* ')' +/// ::= binary LETTER number? (id, id) +/// ::= unary LETTER (id) +static PrototypeAST *ParsePrototype() { + std::string FnName; + + SourceLocation FnLoc = CurLoc; + + unsigned Kind = 0; // 0 = identifier, 1 = unary, 2 = binary. + unsigned BinaryPrecedence = 30; + + switch (CurTok) { + default: + return ErrorP("Expected function name in prototype"); + case tok_identifier: + FnName = IdentifierStr; + Kind = 0; + getNextToken(); + break; + case tok_unary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected unary operator"); + FnName = "unary"; + FnName += (char)CurTok; + Kind = 1; + getNextToken(); + break; + case tok_binary: + getNextToken(); + if (!isascii(CurTok)) + return ErrorP("Expected binary operator"); + FnName = "binary"; + FnName += (char)CurTok; + Kind = 2; + getNextToken(); + + // Read the precedence if present. + if (CurTok == tok_number) { + if (NumVal < 1 || NumVal > 100) + return ErrorP("Invalid precedecnce: must be 1..100"); + BinaryPrecedence = (unsigned)NumVal; + getNextToken(); + } + break; + } + + if (CurTok != '(') + return ErrorP("Expected '(' in prototype"); + + std::vector ArgNames; + while (getNextToken() == tok_identifier) + ArgNames.push_back(IdentifierStr); + if (CurTok != ')') + return ErrorP("Expected ')' in prototype"); + + // success. + getNextToken(); // eat ')'. + + // Verify right number of names for operator. + if (Kind && ArgNames.size() != Kind) + return ErrorP("Invalid number of operands for operator"); + + return new PrototypeAST(FnLoc, FnName, ArgNames, Kind != 0, BinaryPrecedence); +} + +/// definition ::= 'def' prototype expression +static FunctionAST *ParseDefinition() { + getNextToken(); // eat def. + PrototypeAST *Proto = ParsePrototype(); + if (Proto == 0) + return 0; + + if (ExprAST *E = ParseExpression()) + return new FunctionAST(Proto, E); + return 0; +} + +/// toplevelexpr ::= expression +static FunctionAST *ParseTopLevelExpr() { + SourceLocation FnLoc = CurLoc; + if (ExprAST *E = ParseExpression()) { + // Make an anonymous proto. + PrototypeAST *Proto = + new PrototypeAST(FnLoc, "main", std::vector()); + return new FunctionAST(Proto, E); + } + return 0; +} + +/// external ::= 'extern' prototype +static PrototypeAST *ParseExtern() { + getNextToken(); // eat extern. + return ParsePrototype(); +} + +//===----------------------------------------------------------------------===// +// Debug Info Support +//===----------------------------------------------------------------------===// + +static DIBuilder *DBuilder; + +DIType DebugInfo::getDoubleTy() { + if (DblTy.isValid()) + return DblTy; + + DblTy = DBuilder->createBasicType("double", 64, 64, dwarf::DW_ATE_float); + return DblTy; +} + +void DebugInfo::emitLocation(ExprAST *AST) { + if (!AST) + return Builder.SetCurrentDebugLocation(DebugLoc()); + DIScope *Scope; + if (LexicalBlocks.empty()) + Scope = &TheCU; + else + Scope = LexicalBlocks.back(); + Builder.SetCurrentDebugLocation( + DebugLoc::get(AST->getLine(), AST->getCol(), DIScope(*Scope))); +} + +static DICompositeType CreateFunctionType(unsigned NumArgs, DIFile Unit) { + SmallVector EltTys; + DIType DblTy = KSDbgInfo.getDoubleTy(); + + // Add the result type. + EltTys.push_back(DblTy); + + for (unsigned i = 0, e = NumArgs; i != e; ++i) + EltTys.push_back(DblTy); + + DITypeArray EltTypeArray = DBuilder->getOrCreateTypeArray(EltTys); + return DBuilder->createSubroutineType(Unit, EltTypeArray); +} + +//===----------------------------------------------------------------------===// +// Code Generation +//===----------------------------------------------------------------------===// + +static Module *TheModule; +static std::map NamedValues; +static FunctionPassManager *TheFPM; + +Value *ErrorV(const char *Str) { + Error(Str); + return 0; +} + +/// CreateEntryBlockAlloca - Create an alloca instruction in the entry block of +/// the function. This is used for mutable variables etc. +static AllocaInst *CreateEntryBlockAlloca(Function *TheFunction, + const std::string &VarName) { + IRBuilder<> TmpB(&TheFunction->getEntryBlock(), + TheFunction->getEntryBlock().begin()); + return TmpB.CreateAlloca(Type::getDoubleTy(getGlobalContext()), 0, + VarName.c_str()); +} + +Value *NumberExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + return ConstantFP::get(getGlobalContext(), APFloat(Val)); +} + +Value *VariableExprAST::Codegen() { + // Look this variable up in the function. + Value *V = NamedValues[Name]; + if (V == 0) + return ErrorV("Unknown variable name"); + + KSDbgInfo.emitLocation(this); + // Load the value. + return Builder.CreateLoad(V, Name.c_str()); +} + +Value *UnaryExprAST::Codegen() { + Value *OperandV = Operand->Codegen(); + if (OperandV == 0) + return 0; + + Function *F = TheModule->getFunction(std::string("unary") + Opcode); + if (F == 0) + return ErrorV("Unknown unary operator"); + + KSDbgInfo.emitLocation(this); + return Builder.CreateCall(F, OperandV, "unop"); +} + +Value *BinaryExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + // Special case '=' because we don't want to emit the LHS as an expression. + if (Op == '=') { + // Assignment requires the LHS to be an identifier. + VariableExprAST *LHSE = dynamic_cast(LHS); + if (!LHSE) + return ErrorV("destination of '=' must be a variable"); + // Codegen the RHS. + Value *Val = RHS->Codegen(); + if (Val == 0) + return 0; + + // Look up the name. + Value *Variable = NamedValues[LHSE->getName()]; + if (Variable == 0) + return ErrorV("Unknown variable name"); + + Builder.CreateStore(Val, Variable); + return Val; + } + + Value *L = LHS->Codegen(); + Value *R = RHS->Codegen(); + if (L == 0 || R == 0) + return 0; + + switch (Op) { + case '+': + return Builder.CreateFAdd(L, R, "addtmp"); + case '-': + return Builder.CreateFSub(L, R, "subtmp"); + case '*': + return Builder.CreateFMul(L, R, "multmp"); + case '<': + L = Builder.CreateFCmpULT(L, R, "cmptmp"); + // Convert bool 0/1 to double 0.0 or 1.0 + return Builder.CreateUIToFP(L, Type::getDoubleTy(getGlobalContext()), + "booltmp"); + default: + break; + } + + // If it wasn't a builtin binary operator, it must be a user defined one. Emit + // a call to it. + Function *F = TheModule->getFunction(std::string("binary") + Op); + assert(F && "binary operator not found!"); + + Value *Ops[] = { L, R }; + return Builder.CreateCall(F, Ops, "binop"); +} + +Value *CallExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + // Look up the name in the global module table. + Function *CalleeF = TheModule->getFunction(Callee); + if (CalleeF == 0) + return ErrorV("Unknown function referenced"); + + // If argument mismatch error. + if (CalleeF->arg_size() != Args.size()) + return ErrorV("Incorrect # arguments passed"); + + std::vector ArgsV; + for (unsigned i = 0, e = Args.size(); i != e; ++i) { + ArgsV.push_back(Args[i]->Codegen()); + if (ArgsV.back() == 0) + return 0; + } + + return Builder.CreateCall(CalleeF, ArgsV, "calltmp"); +} + +Value *IfExprAST::Codegen() { + KSDbgInfo.emitLocation(this); + + Value *CondV = Cond->Codegen(); + if (CondV == 0) + return 0; + + // Convert condition to a bool by comparing equal to 0.0. + CondV = Builder.CreateFCmpONE( + CondV, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "ifcond"); + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create blocks for the then and else cases. Insert the 'then' block at the + // end of the function. + BasicBlock *ThenBB = + BasicBlock::Create(getGlobalContext(), "then", TheFunction); + BasicBlock *ElseBB = BasicBlock::Create(getGlobalContext(), "else"); + BasicBlock *MergeBB = BasicBlock::Create(getGlobalContext(), "ifcont"); + + Builder.CreateCondBr(CondV, ThenBB, ElseBB); + + // Emit then value. + Builder.SetInsertPoint(ThenBB); + + Value *ThenV = Then->Codegen(); + if (ThenV == 0) + return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Then' can change the current block, update ThenBB for the PHI. + ThenBB = Builder.GetInsertBlock(); + + // Emit else block. + TheFunction->getBasicBlockList().push_back(ElseBB); + Builder.SetInsertPoint(ElseBB); + + Value *ElseV = Else->Codegen(); + if (ElseV == 0) + return 0; + + Builder.CreateBr(MergeBB); + // Codegen of 'Else' can change the current block, update ElseBB for the PHI. + ElseBB = Builder.GetInsertBlock(); + + // Emit merge block. + TheFunction->getBasicBlockList().push_back(MergeBB); + Builder.SetInsertPoint(MergeBB); + PHINode *PN = + Builder.CreatePHI(Type::getDoubleTy(getGlobalContext()), 2, "iftmp"); + + PN->addIncoming(ThenV, ThenBB); + PN->addIncoming(ElseV, ElseBB); + return PN; +} + +Value *ForExprAST::Codegen() { + // Output this as: + // var = alloca double + // ... + // start = startexpr + // store start -> var + // goto loop + // loop: + // ... + // bodyexpr + // ... + // loopend: + // step = stepexpr + // endcond = endexpr + // + // curvar = load var + // nextvar = curvar + step + // store nextvar -> var + // br endcond, loop, endloop + // outloop: + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Create an alloca for the variable in the entry block. + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + + KSDbgInfo.emitLocation(this); + + // Emit the start code first, without 'variable' in scope. + Value *StartVal = Start->Codegen(); + if (StartVal == 0) + return 0; + + // Store the value into the alloca. + Builder.CreateStore(StartVal, Alloca); + + // Make the new basic block for the loop header, inserting after current + // block. + BasicBlock *LoopBB = + BasicBlock::Create(getGlobalContext(), "loop", TheFunction); + + // Insert an explicit fall through from the current block to the LoopBB. + Builder.CreateBr(LoopBB); + + // Start insertion in LoopBB. + Builder.SetInsertPoint(LoopBB); + + // Within the loop, the variable is defined equal to the PHI node. If it + // shadows an existing variable, we have to restore it, so save it now. + AllocaInst *OldVal = NamedValues[VarName]; + NamedValues[VarName] = Alloca; + + // Emit the body of the loop. This, like any other expr, can change the + // current BB. Note that we ignore the value computed by the body, but don't + // allow an error. + if (Body->Codegen() == 0) + return 0; + + // Emit the step value. + Value *StepVal; + if (Step) { + StepVal = Step->Codegen(); + if (StepVal == 0) + return 0; + } else { + // If not specified, use 1.0. + StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0)); + } + + // Compute the end condition. + Value *EndCond = End->Codegen(); + if (EndCond == 0) + return EndCond; + + // Reload, increment, and restore the alloca. This handles the case where + // the body of the loop mutates the variable. + Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str()); + Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar"); + Builder.CreateStore(NextVar, Alloca); + + // Convert condition to a bool by comparing equal to 0.0. + EndCond = Builder.CreateFCmpONE( + EndCond, ConstantFP::get(getGlobalContext(), APFloat(0.0)), "loopcond"); + + // Create the "after loop" block and insert it. + BasicBlock *AfterBB = + BasicBlock::Create(getGlobalContext(), "afterloop", TheFunction); + + // Insert the conditional branch into the end of LoopEndBB. + Builder.CreateCondBr(EndCond, LoopBB, AfterBB); + + // Any new code will be inserted in AfterBB. + Builder.SetInsertPoint(AfterBB); + + // Restore the unshadowed variable. + if (OldVal) + NamedValues[VarName] = OldVal; + else + NamedValues.erase(VarName); + + // for expr always returns 0.0. + return Constant::getNullValue(Type::getDoubleTy(getGlobalContext())); +} + +Value *VarExprAST::Codegen() { + std::vector OldBindings; + + Function *TheFunction = Builder.GetInsertBlock()->getParent(); + + // Register all variables and emit their initializer. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) { + const std::string &VarName = VarNames[i].first; + ExprAST *Init = VarNames[i].second; + + // Emit the initializer before adding the variable to scope, this prevents + // the initializer from referencing the variable itself, and permits stuff + // like this: + // var a = 1 in + // var a = a in ... # refers to outer 'a'. + Value *InitVal; + if (Init) { + InitVal = Init->Codegen(); + if (InitVal == 0) + return 0; + } else { // If not specified, use 0.0. + InitVal = ConstantFP::get(getGlobalContext(), APFloat(0.0)); + } + + AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, VarName); + Builder.CreateStore(InitVal, Alloca); + + // Remember the old variable binding so that we can restore the binding when + // we unrecurse. + OldBindings.push_back(NamedValues[VarName]); + + // Remember this binding. + NamedValues[VarName] = Alloca; + } + + KSDbgInfo.emitLocation(this); + + // Codegen the body, now that all vars are in scope. + Value *BodyVal = Body->Codegen(); + if (BodyVal == 0) + return 0; + + // Pop all our variables from scope. + for (unsigned i = 0, e = VarNames.size(); i != e; ++i) + NamedValues[VarNames[i].first] = OldBindings[i]; + + // Return the body computation. + return BodyVal; +} + +Function *PrototypeAST::Codegen() { + // Make the function type: double(double,double) etc. + std::vector Doubles(Args.size(), + Type::getDoubleTy(getGlobalContext())); + FunctionType *FT = + FunctionType::get(Type::getDoubleTy(getGlobalContext()), Doubles, false); + + Function *F = + Function::Create(FT, Function::ExternalLinkage, Name, TheModule); + + // If F conflicted, there was already something named 'Name'. If it has a + // body, don't allow redefinition or reextern. + if (F->getName() != Name) { + // Delete the one we just made and get the existing one. + F->eraseFromParent(); + F = TheModule->getFunction(Name); + + // If F already has a body, reject this. + if (!F->empty()) { + ErrorF("redefinition of function"); + return 0; + } + + // If F took a different number of args, reject. + if (F->arg_size() != Args.size()) { + ErrorF("redefinition of function with different # args"); + return 0; + } + } + + // Set names for all arguments. + unsigned Idx = 0; + for (Function::arg_iterator AI = F->arg_begin(); Idx != Args.size(); + ++AI, ++Idx) + AI->setName(Args[Idx]); + + // Create a subprogram DIE for this function. + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIDescriptor FContext(Unit); + unsigned LineNo = Line; + unsigned ScopeLine = Line; + DISubprogram SP = DBuilder->createFunction( + FContext, Name, StringRef(), Unit, LineNo, + CreateFunctionType(Args.size(), Unit), false /* internal linkage */, + true /* definition */, ScopeLine, DIDescriptor::FlagPrototyped, false, F); + + KSDbgInfo.FnScopeMap[this] = SP; + return F; +} + +/// CreateArgumentAllocas - Create an alloca for each argument and register the +/// argument in the symbol table so that references to it will succeed. +void PrototypeAST::CreateArgumentAllocas(Function *F) { + Function::arg_iterator AI = F->arg_begin(); + for (unsigned Idx = 0, e = Args.size(); Idx != e; ++Idx, ++AI) { + // Create an alloca for this variable. + AllocaInst *Alloca = CreateEntryBlockAlloca(F, Args[Idx]); + + // Create a debug descriptor for the variable. + DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); + DIFile Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), + KSDbgInfo.TheCU.getDirectory()); + DIVariable D = DBuilder->createLocalVariable(dwarf::DW_TAG_arg_variable, + *Scope, Args[Idx], Unit, Line, + KSDbgInfo.getDoubleTy(), Idx); + + Instruction *Call = DBuilder->insertDeclare( + Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock()); + Call->setDebugLoc(DebugLoc::get(Line, 0, *Scope)); + + // Store the initial value into the alloca. + Builder.CreateStore(AI, Alloca); + + // Add arguments to variable symbol table. + NamedValues[Args[Idx]] = Alloca; + } +} + +Function *FunctionAST::Codegen() { + NamedValues.clear(); + + Function *TheFunction = Proto->Codegen(); + if (TheFunction == 0) + return 0; + + // Push the current scope. + KSDbgInfo.LexicalBlocks.push_back(&KSDbgInfo.FnScopeMap[Proto]); + + // Unset the location for the prologue emission (leading instructions with no + // location in a function are considered part of the prologue and the debugger + // will run past them when breaking on a function) + KSDbgInfo.emitLocation(nullptr); + + // If this is an operator, install it. + if (Proto->isBinaryOp()) + BinopPrecedence[Proto->getOperatorName()] = Proto->getBinaryPrecedence(); + + // Create a new basic block to start insertion into. + BasicBlock *BB = BasicBlock::Create(getGlobalContext(), "entry", TheFunction); + Builder.SetInsertPoint(BB); + + // Add all arguments to the symbol table and create their allocas. + Proto->CreateArgumentAllocas(TheFunction); + + KSDbgInfo.emitLocation(Body); + + if (Value *RetVal = Body->Codegen()) { + // Finish off the function. + Builder.CreateRet(RetVal); + + // Pop off the lexical block for the function. + KSDbgInfo.LexicalBlocks.pop_back(); + + // Validate the generated code, checking for consistency. + verifyFunction(*TheFunction); + + // Optimize the function. + TheFPM->run(*TheFunction); + + return TheFunction; + } + + // Error reading body, remove function. + TheFunction->eraseFromParent(); + + if (Proto->isBinaryOp()) + BinopPrecedence.erase(Proto->getOperatorName()); + + // Pop off the lexical block for the function since we added it + // unconditionally. + KSDbgInfo.LexicalBlocks.pop_back(); + + return 0; +} + +//===----------------------------------------------------------------------===// +// Top-Level parsing and JIT Driver +//===----------------------------------------------------------------------===// + +static ExecutionEngine *TheExecutionEngine; + +static void HandleDefinition() { + if (FunctionAST *F = ParseDefinition()) { + if (!F->Codegen()) { + fprintf(stderr, "Error reading function definition:"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleExtern() { + if (PrototypeAST *P = ParseExtern()) { + if (!P->Codegen()) { + fprintf(stderr, "Error reading extern"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +static void HandleTopLevelExpression() { + // Evaluate a top-level expression into an anonymous function. + if (FunctionAST *F = ParseTopLevelExpr()) { + if (!F->Codegen()) { + fprintf(stderr, "Error generating code for top level expr"); + } + } else { + // Skip token for error recovery. + getNextToken(); + } +} + +/// top ::= definition | external | expression | ';' +static void MainLoop() { + while (1) { + switch (CurTok) { + case tok_eof: + return; + case ';': + getNextToken(); + break; // ignore top-level semicolons. + case tok_def: + HandleDefinition(); + break; + case tok_extern: + HandleExtern(); + break; + default: + HandleTopLevelExpression(); + break; + } + } +} + +//===----------------------------------------------------------------------===// +// "Library" functions that can be "extern'd" from user code. +//===----------------------------------------------------------------------===// + +/// putchard - putchar that takes a double and returns 0. +extern "C" double putchard(double X) { + putchar((char)X); + return 0; +} + +/// printd - printf that takes a double prints it as "%f\n", returning 0. +extern "C" double printd(double X) { + printf("%f\n", X); + return 0; +} + +//===----------------------------------------------------------------------===// +// Main driver code. +//===----------------------------------------------------------------------===// + +int main() { + InitializeNativeTarget(); + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); + LLVMContext &Context = getGlobalContext(); + + // Install standard binary operators. + // 1 is lowest precedence. + BinopPrecedence['='] = 2; + BinopPrecedence['<'] = 10; + BinopPrecedence['+'] = 20; + BinopPrecedence['-'] = 20; + BinopPrecedence['*'] = 40; // highest. + + // Prime the first token. + getNextToken(); + + // Make the module, which holds all the code. + std::unique_ptr Owner = make_unique("my cool jit", Context); + TheModule = Owner.get(); + + // Add the current debug info version into the module. + TheModule->addModuleFlag(Module::Warning, "Debug Info Version", + DEBUG_METADATA_VERSION); + + // Darwin only supports dwarf2. + if (Triple(sys::getProcessTriple()).isOSDarwin()) + TheModule->addModuleFlag(llvm::Module::Warning, "Dwarf Version", 2); + + // Construct the DIBuilder, we do this here because we need the module. + DBuilder = new DIBuilder(*TheModule); + + // Create the compile unit for the module. + // Currently down as "fib.ks" as a filename since we're redirecting stdin + // but we'd like actual source locations. + KSDbgInfo.TheCU = DBuilder->createCompileUnit( + dwarf::DW_LANG_C, "fib.ks", ".", "Kaleidoscope Compiler", 0, "", 0); + + // Create the JIT. This takes ownership of the module. + std::string ErrStr; + TheExecutionEngine = + EngineBuilder(std::move(Owner)) + .setErrorStr(&ErrStr) + .setMCJITMemoryManager(llvm::make_unique()) + .create(); + if (!TheExecutionEngine) { + fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); + exit(1); + } + + FunctionPassManager OurFPM(TheModule); + + // Set up the optimizer pipeline. Start with registering info about how the + // target lays out data structures. + TheModule->setDataLayout(TheExecutionEngine->getDataLayout()); + OurFPM.add(new DataLayoutPass()); +#if 0 + // Provide basic AliasAnalysis support for GVN. + OurFPM.add(createBasicAliasAnalysisPass()); + // Promote allocas to registers. + OurFPM.add(createPromoteMemoryToRegisterPass()); + // Do simple "peephole" optimizations and bit-twiddling optzns. + OurFPM.add(createInstructionCombiningPass()); + // Reassociate expressions. + OurFPM.add(createReassociatePass()); + // Eliminate Common SubExpressions. + OurFPM.add(createGVNPass()); + // Simplify the control flow graph (deleting unreachable blocks, etc). + OurFPM.add(createCFGSimplificationPass()); + #endif + OurFPM.doInitialization(); + + // Set the global so the code gen can use this. + TheFPM = &OurFPM; + + // Run the main "interpreter loop" now. + MainLoop(); + + TheFPM = 0; + + // Finalize the debug info. + DBuilder->finalize(); + + // Print out all of the generated code. + TheModule->dump(); + + return 0; +} diff --git a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp index 9466360a..00f5b83 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy-jit.cpp @@ -2,7 +2,6 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" diff --git a/examples/Kaleidoscope/MCJIT/cached/toy.cpp b/examples/Kaleidoscope/MCJIT/cached/toy.cpp index 16c548c..af51b4a 100644 --- a/examples/Kaleidoscope/MCJIT/cached/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/cached/toy.cpp @@ -897,7 +897,6 @@ ExecutionEngine *MCJITHelper::compileModule(Module *M) { std::string ErrStr; ExecutionEngine *NewEngine = EngineBuilder(M) .setErrorStr(&ErrStr) - .setUseMCJIT(true) .setMCJITMemoryManager(new HelpingMemoryManager(this)) .create(); if (!NewEngine) { diff --git a/examples/Kaleidoscope/MCJIT/complete/toy.cpp b/examples/Kaleidoscope/MCJIT/complete/toy.cpp index 10e7ada..3beb0d8 100644 --- a/examples/Kaleidoscope/MCJIT/complete/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/complete/toy.cpp @@ -1,6 +1,5 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -52,10 +51,6 @@ namespace { cl::desc("Dump IR from modules to stderr on shutdown"), cl::init(false)); - cl::opt UseMCJIT( - "use-mcjit", cl::desc("Use the MCJIT execution engine"), - cl::init(true)); - cl::opt EnableLazyCompilation( "enable-lazy-compilation", cl::desc("Enable lazy compilation when using the MCJIT engine"), cl::init(true)); @@ -793,96 +788,6 @@ public: }; //===----------------------------------------------------------------------===// -// Helper class for JIT execution engine -//===----------------------------------------------------------------------===// - -class JITHelper : public BaseHelper { -public: - JITHelper(LLVMContext &Context) { - // Make the module, which holds all the code. - if (!InputIR.empty()) { - TheModule = parseInputIR(InputIR, Context); - } else { - TheModule = new Module("my cool jit", Context); - } - - // Create the JIT. This takes ownership of the module. - std::string ErrStr; - TheExecutionEngine = EngineBuilder(TheModule).setErrorStr(&ErrStr).create(); - if (!TheExecutionEngine) { - fprintf(stderr, "Could not create ExecutionEngine: %s\n", ErrStr.c_str()); - exit(1); - } - - TheFPM = new FunctionPassManager(TheModule); - - // Set up the optimizer pipeline. Start with registering info about how the - // target lays out data structures. - TheFPM->add(new DataLayout(*TheExecutionEngine->getDataLayout())); - // Provide basic AliasAnalysis support for GVN. - TheFPM->add(createBasicAliasAnalysisPass()); - // Promote allocas to registers. - TheFPM->add(createPromoteMemoryToRegisterPass()); - // Do simple "peephole" optimizations and bit-twiddling optzns. - TheFPM->add(createInstructionCombiningPass()); - // Reassociate expressions. - TheFPM->add(createReassociatePass()); - // Eliminate Common SubExpressions. - TheFPM->add(createGVNPass()); - // Simplify the control flow graph (deleting unreachable blocks, etc). - TheFPM->add(createCFGSimplificationPass()); - - TheFPM->doInitialization(); - } - - virtual ~JITHelper() { - if (TheFPM) - delete TheFPM; - if (TheExecutionEngine) - delete TheExecutionEngine; - } - - virtual Function *getFunction(const std::string FnName) { - assert(TheModule); - return TheModule->getFunction(FnName); - } - - virtual Module *getModuleForNewFunction() { - assert(TheModule); - return TheModule; - } - - virtual void *getPointerToFunction(Function* F) { - assert(TheExecutionEngine); - return TheExecutionEngine->getPointerToFunction(F); - } - - virtual void *getPointerToNamedFunction(const std::string &Name) { - return TheExecutionEngine->getPointerToNamedFunction(Name); - } - - virtual void runFPM(Function &F) { - assert(TheFPM); - TheFPM->run(F); - } - - virtual void closeCurrentModule() { - // This should never be called for JIT - assert(false); - } - - virtual void dump() { - assert(TheModule); - TheModule->dump(); - } - -private: - Module *TheModule; - ExecutionEngine *TheExecutionEngine; - FunctionPassManager *TheFPM; -}; - -//===----------------------------------------------------------------------===// // MCJIT helper class //===----------------------------------------------------------------------===// @@ -1034,7 +939,6 @@ ExecutionEngine *MCJITHelper::compileModule(Module *M) { std::string ErrStr; ExecutionEngine *EE = EngineBuilder(M) .setErrorStr(&ErrStr) - .setUseMCJIT(true) .setMCJITMemoryManager(new HelpingMemoryManager(this)) .create(); if (!EE) { @@ -1194,10 +1098,8 @@ Value *UnaryExprAST::Codegen() { Value *OperandV = Operand->Codegen(); if (OperandV == 0) return 0; Function *F; - if (UseMCJIT) - F = TheHelper->getFunction(MakeLegalFunctionName(std::string("unary")+Opcode)); - else - F = TheHelper->getFunction(std::string("unary")+Opcode); + F = TheHelper->getFunction( + MakeLegalFunctionName(std::string("unary") + Opcode)); if (F == 0) return ErrorV("Unknown unary operator"); @@ -1246,10 +1148,7 @@ Value *BinaryExprAST::Codegen() { // If it wasn't a builtin binary operator, it must be a user defined one. Emit // a call to it. Function *F; - if (UseMCJIT) - F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); - else - F = TheHelper->getFunction(std::string("binary")+Op); + F = TheHelper->getFunction(MakeLegalFunctionName(std::string("binary")+Op)); assert(F && "binary operator not found!"); Value *Ops[] = { L, R }; @@ -1482,10 +1381,7 @@ Function *PrototypeAST::Codegen() { Doubles, false); std::string FnName; - if (UseMCJIT) - FnName = MakeLegalFunctionName(Name); - else - FnName = Name; + FnName = MakeLegalFunctionName(Name); Module* M = TheHelper->getModuleForNewFunction(); Function *F = Function::Create(FT, Function::ExternalLinkage, FnName, M); @@ -1560,10 +1456,6 @@ Function *FunctionAST::Codegen() { // Validate the generated code, checking for consistency. verifyFunction(*TheFunction); - // Optimize the function. - if (!UseMCJIT) - TheHelper->runFPM(*TheFunction); - return TheFunction; } @@ -1581,7 +1473,7 @@ Function *FunctionAST::Codegen() { static void HandleDefinition() { if (FunctionAST *F = ParseDefinition()) { - if (UseMCJIT && EnableLazyCompilation) + if (EnableLazyCompilation) TheHelper->closeCurrentModule(); Function *LF = F->Codegen(); if (LF && VerboseOutput) { @@ -1671,10 +1563,8 @@ double printlf() { int main(int argc, char **argv) { InitializeNativeTarget(); - if (UseMCJIT) { - InitializeNativeTargetAsmPrinter(); - InitializeNativeTargetAsmParser(); - } + InitializeNativeTargetAsmPrinter(); + InitializeNativeTargetAsmParser(); LLVMContext &Context = getGlobalContext(); cl::ParseCommandLineOptions(argc, argv, @@ -1690,10 +1580,7 @@ int main(int argc, char **argv) { BinopPrecedence['*'] = 40; // highest. // Make the Helper, which holds all the code. - if (UseMCJIT) - TheHelper = new MCJITHelper(Context); - else - TheHelper = new JITHelper(Context); + TheHelper = new MCJITHelper(Context); // Prime the first token. if (!SuppressPrompts) diff --git a/examples/Kaleidoscope/MCJIT/initial/toy.cpp b/examples/Kaleidoscope/MCJIT/initial/toy.cpp index 4c47113..2c1b297 100644 --- a/examples/Kaleidoscope/MCJIT/initial/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/initial/toy.cpp @@ -778,7 +778,6 @@ void *MCJITHelper::getPointerToFunction(Function* F) { std::string ErrStr; ExecutionEngine *NewEngine = EngineBuilder(OpenModule) .setErrorStr(&ErrStr) - .setUseMCJIT(true) .setMCJITMemoryManager(new HelpingMemoryManager(this)) .create(); if (!NewEngine) { diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp index 2d540dd..98c1001 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy-jit.cpp @@ -2,7 +2,6 @@ #include "llvm/Analysis/Passes.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/IRBuilder.h" diff --git a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp index ff88e23..9c2a0d4 100644 --- a/examples/Kaleidoscope/MCJIT/lazy/toy.cpp +++ b/examples/Kaleidoscope/MCJIT/lazy/toy.cpp @@ -808,7 +808,6 @@ ExecutionEngine *MCJITHelper::compileModule(Module *M) { std::string ErrStr; ExecutionEngine *NewEngine = EngineBuilder(M) .setErrorStr(&ErrStr) - .setUseMCJIT(true) .setMCJITMemoryManager(new HelpingMemoryManager(this)) .create(); if (!NewEngine) { diff --git a/examples/Kaleidoscope/Makefile b/examples/Kaleidoscope/Makefile index bd0c252..8c3b1e3 100644 --- a/examples/Kaleidoscope/Makefile +++ b/examples/Kaleidoscope/Makefile @@ -10,6 +10,6 @@ LEVEL=../.. include $(LEVEL)/Makefile.config -PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 +PARALLEL_DIRS:= Chapter2 Chapter3 Chapter4 Chapter5 Chapter6 Chapter7 Chapter8 include $(LEVEL)/Makefile.common diff --git a/examples/ParallelJIT/CMakeLists.txt b/examples/ParallelJIT/CMakeLists.txt index 8673917..07c0a08 100644 --- a/examples/ParallelJIT/CMakeLists.txt +++ b/examples/ParallelJIT/CMakeLists.txt @@ -2,7 +2,7 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine Interpreter - JIT + MC Support nativecodegen ) diff --git a/examples/ParallelJIT/Makefile b/examples/ParallelJIT/Makefile index 8a49d42..0f2a357 100644 --- a/examples/ParallelJIT/Makefile +++ b/examples/ParallelJIT/Makefile @@ -10,7 +10,7 @@ LEVEL = ../.. TOOLNAME = ParallelJIT EXAMPLE_TOOL = 1 -LINK_COMPONENTS := jit interpreter nativecodegen +LINK_COMPONENTS := mcjit interpreter nativecodegen include $(LEVEL)/Makefile.common diff --git a/examples/ParallelJIT/ParallelJIT.cpp b/examples/ParallelJIT/ParallelJIT.cpp index 2aa63d9..4ebf3d0 100644 --- a/examples/ParallelJIT/ParallelJIT.cpp +++ b/examples/ParallelJIT/ParallelJIT.cpp @@ -19,7 +19,6 @@ #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" @@ -243,13 +242,14 @@ int main() { LLVMContext Context; // Create some module to put our function into it. - Module *M = new Module("test", Context); + std::unique_ptr Owner = make_unique("test", Context); + Module *M = Owner.get(); Function* add1F = createAdd1( M ); Function* fibF = CreateFibFunction( M ); // Now we create the JIT. - ExecutionEngine* EE = EngineBuilder(M).create(); + ExecutionEngine* EE = EngineBuilder(std::move(Owner)).create(); //~ std::cout << "We just constructed this LLVM module:\n\n" << *M; //~ std::cout << "\n\nRunning foo: " << std::flush; diff --git a/include/llvm-c/BitReader.h b/include/llvm-c/BitReader.h index 7af209b..f3b388b 100644 --- a/include/llvm-c/BitReader.h +++ b/include/llvm-c/BitReader.h @@ -16,8 +16,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_C_BITCODEREADER_H -#define LLVM_C_BITCODEREADER_H +#ifndef LLVM_C_BITREADER_H +#define LLVM_C_BITREADER_H #include "llvm-c/Core.h" diff --git a/include/llvm-c/BitWriter.h b/include/llvm-c/BitWriter.h index f605e24..f25ad3a 100644 --- a/include/llvm-c/BitWriter.h +++ b/include/llvm-c/BitWriter.h @@ -16,8 +16,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_C_BITCODEWRITER_H -#define LLVM_C_BITCODEWRITER_H +#ifndef LLVM_C_BITWRITER_H +#define LLVM_C_BITWRITER_H #include "llvm-c/Core.h" @@ -45,6 +45,9 @@ int LLVMWriteBitcodeToFD(LLVMModuleRef M, int FD, int ShouldClose, descriptor. Returns 0 on success. Closes the Handle. */ int LLVMWriteBitcodeToFileHandle(LLVMModuleRef M, int Handle); +/** Writes a module to a new memory buffer and returns it. */ +LLVMMemoryBufferRef LLVMWriteBitcodeToMemoryBuffer(LLVMModuleRef M); + /** * @} */ diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index fdff77b..8873fdb 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -560,6 +560,10 @@ LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID); */ LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID, LLVMContextRef C); +/** + * Return an exact copy of the specified module. + */ +LLVMModuleRef LLVMCloneModule(LLVMModuleRef M); /** * Destroy a module instance. @@ -1153,8 +1157,6 @@ LLVMTypeRef LLVMX86MMXType(void); macro(Argument) \ macro(BasicBlock) \ macro(InlineAsm) \ - macro(MDNode) \ - macro(MDString) \ macro(User) \ macro(Constant) \ macro(BlockAddress) \ @@ -1303,6 +1305,9 @@ LLVMBool LLVMIsUndef(LLVMValueRef Val); LLVMValueRef LLVMIsA##name(LLVMValueRef Val); LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DECLARE_VALUE_CAST) +LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val); +LLVMValueRef LLVMIsAMDString(LLVMValueRef Val); + /** * @} */ @@ -1378,6 +1383,13 @@ LLVMValueRef LLVMGetUsedValue(LLVMUseRef U); LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index); /** + * Obtain the use of an operand at a specific index in a llvm::User value. + * + * @see llvm::User::getOperandUse() + */ +LLVMUseRef LLVMGetOperandUse(LLVMValueRef Val, unsigned Index); + +/** * Set an operand at a specific index in a llvm::User value. * * @see llvm::User::setOperand() @@ -1538,6 +1550,14 @@ unsigned long long LLVMConstIntGetZExtValue(LLVMValueRef ConstantVal); long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal); /** + * Obtain the double value for an floating point constant value. + * losesInfo indicates if some precision was lost in the conversion. + * + * @see llvm::ConstantFP::getDoubleValue + */ +double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *losesInfo); + +/** * @} */ @@ -1570,6 +1590,20 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length, LLVMBool DontNullTerminate); /** + * Returns true if the specified constant is an array of i8. + * + * @see ConstantDataSequential::getAsString() + */ +LLVMBool LLVMIsConstantString(LLVMValueRef c); + +/** + * Get the given constant data sequential as a string. + * + * @see ConstantDataSequential::getAsString() + */ +const char *LLVMGetAsString(LLVMValueRef c, size_t* out); + +/** * Create an anonymous ConstantStruct with the specified values. * * @see llvm::ConstantStruct::getAnon() @@ -1607,6 +1641,13 @@ LLVMValueRef LLVMConstNamedStruct(LLVMTypeRef StructTy, unsigned Count); /** + * Get an element at specified index as a constant. + * + * @see ConstantDataSequential::getElementAsConstant() + */ +LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef c, unsigned idx); + +/** * Create a ConstantVector from values. * * @see llvm::ConstantVector::get() @@ -2377,6 +2418,26 @@ LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst); LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst); /** + * Obtain the float predicate of an instruction. + * + * This is only valid for instructions that correspond to llvm::FCmpInst + * or llvm::ConstantExpr whose opcode is llvm::Instruction::FCmp. + * + * @see llvm::FCmpInst::getPredicate() + */ +LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst); + +/** + * Create a copy of 'this' instruction that is identical in all ways + * except the following: + * * The instruction has no parent + * * The instruction has no name + * + * @see llvm::Instruction::clone() + */ +LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst); + +/** * @defgroup LLVMCCoreValueInstructionCall Call Sites and Invocations * * Functions in this group apply to instructions that refer to call @@ -2437,6 +2498,63 @@ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); */ /** + * @defgroup LLVMCCoreValueInstructionTerminator Terminators + * + * Functions in this group only apply to instructions that map to + * llvm::TerminatorInst instances. + * + * @{ + */ + +/** + * Return the number of successors that this terminator has. + * + * @see llvm::TerminatorInst::getNumSuccessors + */ +unsigned LLVMGetNumSuccessors(LLVMValueRef Term); + +/** + * Return the specified successor. + * + * @see llvm::TerminatorInst::getSuccessor + */ +LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i); + +/** + * Update the specified successor to point at the provided block. + * + * @see llvm::TerminatorInst::setSuccessor + */ +void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block); + +/** + * Return if a branch is conditional. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::isConditional + */ +LLVMBool LLVMIsConditional(LLVMValueRef Branch); + +/** + * Return the condition of a branch instruction. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::getCondition + */ +LLVMValueRef LLVMGetCondition(LLVMValueRef Branch); + +/** + * Set the condition of a branch instruction. + * + * This only works on llvm::BranchInst instructions. + * + * @see llvm::BranchInst::setCondition + */ +void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond); + +/** * Obtain the default destination basic block of a switch instruction. * * This only works on llvm::SwitchInst instructions. @@ -2446,6 +2564,10 @@ void LLVMSetTailCall(LLVMValueRef CallInst, LLVMBool IsTailCall); LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef SwitchInstr); /** + * @} + */ + +/** * @defgroup LLVMCCoreValueInstructionPHINode PHI Nodes * * Functions in this group only apply to instructions that map to diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index 8f31150..d6cbe31c 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -174,8 +174,8 @@ extern "C" { * by passing a block of information in the DisInfo parameter and specifying the * TagType and callback functions as described above. These can all be passed * as NULL. If successful, this returns a disassembler context. If not, it - * returns NULL. This function is equivalent to calling LLVMCreateDisasmCPU() - * with an empty CPU name. + * returns NULL. This function is equivalent to calling + * LLVMCreateDisasmCPUFeatures() with an empty CPU name and feature set. */ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, @@ -186,7 +186,8 @@ LLVMDisasmContextRef LLVMCreateDisasm(const char *TripleName, void *DisInfo, * disassembly is supported by passing a block of information in the DisInfo * parameter and specifying the TagType and callback functions as described * above. These can all be passed * as NULL. If successful, this returns a - * disassembler context. If not, it returns NULL. + * disassembler context. If not, it returns NULL. This function is equivalent + * to calling LLVMCreateDisasmCPUFeatures() with an empty feature set. */ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, void *DisInfo, int TagType, @@ -194,6 +195,19 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, LLVMSymbolLookupCallback SymbolLookUp); /** + * Create a disassembler for the TripleName, a specific CPU and specific feature + * string. Symbolic disassembly is supported by passing a block of information + * in the DisInfo parameter and specifying the TagType and callback functions as + * described above. These can all be passed * as NULL. If successful, this + * returns a disassembler context. If not, it returns NULL. + */ +LLVMDisasmContextRef +LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU, + const char *Features, void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp); + +/** * Set the disassembler's options. Returns 1 if it can set the Options and 0 * otherwise. */ diff --git a/include/llvm-c/ExecutionEngine.h b/include/llvm-c/ExecutionEngine.h index 7cdf0d7..eb3ecab 100644 --- a/include/llvm-c/ExecutionEngine.h +++ b/include/llvm-c/ExecutionEngine.h @@ -34,7 +34,6 @@ extern "C" { * @{ */ -void LLVMLinkInJIT(void); void LLVMLinkInMCJIT(void); void LLVMLinkInInterpreter(void); @@ -171,6 +170,10 @@ void LLVMAddGlobalMapping(LLVMExecutionEngineRef EE, LLVMValueRef Global, void *LLVMGetPointerToGlobal(LLVMExecutionEngineRef EE, LLVMValueRef Global); +uint64_t LLVMGetGlobalValueAddress(LLVMExecutionEngineRef EE, const char *Name); + +uint64_t LLVMGetFunctionAddress(LLVMExecutionEngineRef EE, const char *Name); + /*===-- Operations on memory managers -------------------------------------===*/ typedef uint8_t *(*LLVMMemoryManagerAllocateCodeSectionCallback)( diff --git a/include/llvm-c/Initialization.h b/include/llvm-c/Initialization.h index ada4738..44194f8 100644 --- a/include/llvm-c/Initialization.h +++ b/include/llvm-c/Initialization.h @@ -13,8 +13,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef LLVM_C_INITIALIZEPASSES_H -#define LLVM_C_INITIALIZEPASSES_H +#ifndef LLVM_C_INITIALIZATION_H +#define LLVM_C_INITIALIZATION_H #include "llvm-c/Core.h" diff --git a/include/llvm-c/Linker.h b/include/llvm-c/Linker.h index 9f337cf..cedde5e 100644 --- a/include/llvm-c/Linker.h +++ b/include/llvm-c/Linker.h @@ -20,20 +20,13 @@ extern "C" { #endif - -typedef enum { - LLVMLinkerDestroySource = 0, /* Allow source module to be destroyed. */ - LLVMLinkerPreserveSource = 1 /* Preserve the source module. */ -} LLVMLinkerMode; - - /* Links the source module into the destination module, taking ownership * of the source module away from the caller. Optionally returns a * human-readable description of any errors that occurred in linking. * OutMessage must be disposed with LLVMDisposeMessage. The return value * is true if an error occurred, false otherwise. */ LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, - LLVMLinkerMode Mode, char **OutMessage); + unsigned Unused, char **OutMessage); #ifdef __cplusplus } diff --git a/include/llvm-c/Support.h b/include/llvm-c/Support.h index 4e6ff22..a9216d0 100644 --- a/include/llvm-c/Support.h +++ b/include/llvm-c/Support.h @@ -47,6 +47,17 @@ typedef struct LLVMOpaqueMemoryBuffer *LLVMMemoryBufferRef; */ LLVMBool LLVMLoadLibraryPermanently(const char* Filename); +/** + * This function parses the given arguments using the LLVM command line parser. + * Note that the only stable thing about this function is its signature; you + * cannot rely on any particular set of command line arguments being interpreted + * the same way across LLVM versions. + * + * @see llvm::cl::ParseCommandLineOptions() + */ +void LLVMParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview); + #ifdef __cplusplus } #endif diff --git a/include/llvm-c/Transforms/Scalar.h b/include/llvm-c/Transforms/Scalar.h index 0ca72ce..7ad1ad1 100644 --- a/include/llvm-c/Transforms/Scalar.h +++ b/include/llvm-c/Transforms/Scalar.h @@ -35,6 +35,9 @@ extern "C" { /** See llvm::createAggressiveDCEPass function. */ void LLVMAddAggressiveDCEPass(LLVMPassManagerRef PM); +/** See llvm::createAlignmentFromAssumptionsPass function. */ +void LLVMAddAlignmentFromAssumptionsPass(LLVMPassManagerRef PM); + /** See llvm::createCFGSimplificationPass function. */ void LLVMAddCFGSimplificationPass(LLVMPassManagerRef PM); @@ -86,6 +89,9 @@ void LLVMAddMemCpyOptPass(LLVMPassManagerRef PM); /** See llvm::createPartiallyInlineLibCallsPass function. */ void LLVMAddPartiallyInlineLibCallsPass(LLVMPassManagerRef PM); +/** See llvm::createLowerSwitchPass function. */ +void LLVMAddLowerSwitchPass(LLVMPassManagerRef PM); + /** See llvm::createPromoteMemoryToRegisterPass function. */ void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM); @@ -132,6 +138,9 @@ void LLVMAddLowerExpectIntrinsicPass(LLVMPassManagerRef PM); /** See llvm::createTypeBasedAliasAnalysisPass function */ void LLVMAddTypeBasedAliasAnalysisPass(LLVMPassManagerRef PM); +/** See llvm::createScopedNoAliasAAPass function */ +void LLVMAddScopedNoAliasAAPass(LLVMPassManagerRef PM); + /** See llvm::createBasicAliasAnalysisPass function */ void LLVMAddBasicAliasAnalysisPass(LLVMPassManagerRef PM); diff --git a/include/llvm-c/lto.h b/include/llvm-c/lto.h index c525710..3f30d6d 100644 --- a/include/llvm-c/lto.h +++ b/include/llvm-c/lto.h @@ -40,7 +40,7 @@ typedef bool lto_bool_t; * @{ */ -#define LTO_API_VERSION 10 +#define LTO_API_VERSION 11 /** * \since prior to LTO_API_VERSION=3 @@ -178,6 +178,35 @@ lto_module_create_from_memory_with_path(const void* mem, size_t length, const char *path); /** + * \brief Loads an object file in its own context. + * + * Loads an object file in its own LLVMContext. This function call is + * thread-safe. However, modules created this way should not be merged into an + * lto_code_gen_t using \a lto_codegen_add_module(). + * + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=11 + */ +extern lto_module_t +lto_module_create_in_local_context(const void *mem, size_t length, + const char *path); + +/** + * \brief Loads an object file in the codegen context. + * + * Loads an object file into the same context as \c cg. The module is safe to + * add using \a lto_codegen_add_module(). + * + * Returns NULL on error (check lto_get_error_message() for details). + * + * \since LTO_API_VERSION=11 + */ +extern lto_module_t +lto_module_create_in_codegen_context(const void *mem, size_t length, + const char *path, lto_code_gen_t cg); + +/** * Loads an object file from disk. The seek point of fd is not preserved. * Returns NULL on error (check lto_get_error_message() for details). * @@ -324,12 +353,27 @@ extern void lto_codegen_set_diagnostic_handler(lto_code_gen_t, * Instantiates a code generator. * Returns NULL on error (check lto_get_error_message() for details). * + * All modules added using \a lto_codegen_add_module() must have been created + * in the same context as the codegen. + * * \since prior to LTO_API_VERSION=3 */ extern lto_code_gen_t lto_codegen_create(void); /** + * \brief Instantiate a code generator in its own context. + * + * Instantiates a code generator in its own context. Modules added via \a + * lto_codegen_add_module() must have all been created in the same context, + * using \a lto_module_create_in_codegen_context(). + * + * \since LTO_API_VERSION=11 + */ +extern lto_code_gen_t +lto_codegen_create_in_local_context(void); + +/** * Frees all code generator and all memory it internally allocated. * Upon return the lto_code_gen_t is no longer valid. * @@ -342,6 +386,10 @@ lto_codegen_dispose(lto_code_gen_t); * Add an object module to the set of modules for which code will be generated. * Returns true on error (check lto_get_error_message() for details). * + * \c cg and \c mod must both be in the same context. See \a + * lto_codegen_create_in_local_context() and \a + * lto_module_create_in_codegen_context(). + * * \since prior to LTO_API_VERSION=3 */ extern lto_bool_t diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index 50f1463..26aae77 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -304,6 +304,38 @@ public: /// IEEE-754R 5.3.1: nextUp/nextDown. opStatus next(bool nextDown); + /// \brief Operator+ overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator+(const APFloat &RHS) const { + APFloat Result = *this; + Result.add(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator- overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator-(const APFloat &RHS) const { + APFloat Result = *this; + Result.subtract(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator* overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator*(const APFloat &RHS) const { + APFloat Result = *this; + Result.multiply(RHS, rmNearestTiesToEven); + return Result; + } + + /// \brief Operator/ overload which provides the default + /// \c nmNearestTiesToEven rounding mode and *no* error checking. + APFloat operator/(const APFloat &RHS) const { + APFloat Result = *this; + Result.divide(RHS, rmNearestTiesToEven); + return Result; + } + /// @} /// \name Sign operations. @@ -313,6 +345,13 @@ public: void clearSign(); void copySign(const APFloat &); + /// \brief A static helper to produce a copy of an APFloat value with its sign + /// copied from some other APFloat. + static APFloat copySign(APFloat Value, const APFloat &Sign) { + Value.copySign(Sign); + return std::move(Value); + } + /// @} /// \name Conversions @@ -452,6 +491,36 @@ public: /// return true. bool getExactInverse(APFloat *inv) const; + /// \brief Enumeration of \c ilogb error results. + enum IlogbErrorKinds { + IEK_Zero = INT_MIN+1, + IEK_NaN = INT_MIN, + IEK_Inf = INT_MAX + }; + + /// \brief Returns the exponent of the internal representation of the APFloat. + /// + /// Because the radix of APFloat is 2, this is equivalent to floor(log2(x)). + /// For special APFloat values, this returns special error codes: + /// + /// NaN -> \c IEK_NaN + /// 0 -> \c IEK_Zero + /// Inf -> \c IEK_Inf + /// + friend int ilogb(const APFloat &Arg) { + if (Arg.isNaN()) + return IEK_NaN; + if (Arg.isZero()) + return IEK_Zero; + if (Arg.isInfinity()) + return IEK_Inf; + + return Arg.exponent; + } + + /// \brief Returns: X * 2^Exp for integral exponents. + friend APFloat scalbn(APFloat X, int Exp); + private: /// \name Simple Queries @@ -573,11 +642,41 @@ private: unsigned int sign : 1; }; -/// See friend declaration above. +/// See friend declarations above. /// -/// This additional declaration is required in order to compile LLVM with IBM +/// These additional declarations are required in order to compile LLVM with IBM /// xlC compiler. hash_code hash_value(const APFloat &Arg); +APFloat scalbn(APFloat X, int Exp); + +/// \brief Returns the absolute value of the argument. +inline APFloat abs(APFloat X) { + X.clearSign(); + return X; +} + +/// Implements IEEE minNum semantics. Returns the smaller of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat minnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (B.compare(A) == APFloat::cmpLessThan) ? B : A; +} + +/// Implements IEEE maxNum semantics. Returns the larger of the 2 arguments if +/// both are not NaN. If either argument is a NaN, returns the other argument. +LLVM_READONLY +inline APFloat maxnum(const APFloat &A, const APFloat &B) { + if (A.isNaN()) + return B; + if (B.isNaN()) + return A; + return (A.compare(B) == APFloat::cmpLessThan) ? B : A; +} + } // namespace llvm #endif // LLVM_ADT_APFLOAT_H diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index aa3c3f6..025397d 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -91,6 +91,8 @@ class APInt { APINT_WORD_SIZE = static_cast(sizeof(uint64_t)) }; + friend struct DenseMapAPIntKeyInfo; + /// \brief Fast internal constructor /// /// This constructor is used only internally for speed of construction of @@ -277,7 +279,6 @@ public: /// Simply makes *this a copy of that. /// @brief Copy Constructor. APInt(const APInt &that) : BitWidth(that.BitWidth), VAL(0) { - assert(BitWidth && "bitwidth too small"); if (isSingleWord()) VAL = that.VAL; else @@ -656,13 +657,24 @@ public: /// @brief Move assignment operator. APInt &operator=(APInt &&that) { - if (!isSingleWord()) + if (!isSingleWord()) { + // The MSVC STL shipped in 2013 requires that self move assignment be a + // no-op. Otherwise algorithms like stable_sort will produce answers + // where half of the output is left in a moved-from state. + if (this == &that) + return *this; delete[] pVal; + } - BitWidth = that.BitWidth; - VAL = that.VAL; + // Use memcpy so that type based alias analysis sees both VAL and pVal + // as modified. + memcpy(&VAL, &that.VAL, sizeof(uint64_t)); + // If 'this == &that', avoid zeroing our own bitwidth by storing to 'that' + // first. + unsigned ThatBitWidth = that.BitWidth; that.BitWidth = 0; + BitWidth = ThatBitWidth; return *this; } @@ -936,7 +948,8 @@ public: APInt sdiv_ov(const APInt &RHS, bool &Overflow) const; APInt smul_ov(const APInt &RHS, bool &Overflow) const; APInt umul_ov(const APInt &RHS, bool &Overflow) const; - APInt sshl_ov(unsigned Amt, bool &Overflow) const; + APInt sshl_ov(const APInt &Amt, bool &Overflow) const; + APInt ushl_ov(const APInt &Amt, bool &Overflow) const; /// \brief Array-indexing support. /// diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h index ee34e9b..a6693f7 100644 --- a/include/llvm/ADT/APSInt.h +++ b/include/llvm/ADT/APSInt.h @@ -269,19 +269,15 @@ public: else if (I2.getBitWidth() > I1.getBitWidth()) return isSameValue(I1.extend(I2.getBitWidth()), I2); - // We have a signedness mismatch. Turn the signed value into an unsigned - // value. - if (I1.isSigned()) { - if (I1.isNegative()) - return false; + assert(I1.isSigned() != I2.isSigned()); - return APSInt(I1, true) == I2; - } - - if (I2.isNegative()) + // We have a signedness mismatch. Check for negative values and do an + // unsigned compare if signs match. + if ((I1.isSigned() && I1.isNegative()) || + (!I1.isSigned() && I2.isNegative())) return false; - return I1 == APSInt(I2, true); + return I1.eq(I2); } /// Profile - Used to insert APSInt objects, or objects that contain APSInt diff --git a/include/llvm/ADT/ArrayRef.h b/include/llvm/ADT/ArrayRef.h index 0fff505..8c14a42 100644 --- a/include/llvm/ADT/ArrayRef.h +++ b/include/llvm/ADT/ArrayRef.h @@ -11,6 +11,7 @@ #define LLVM_ADT_ARRAYREF_H #include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include @@ -43,6 +44,19 @@ namespace llvm { /// The number of elements. size_type Length; + /// \brief A dummy "optional" type that is only created by implicit + /// conversion from a reference to T. + /// + /// This type must *only* be used in a function argument or as a copy of + /// a function argument, as otherwise it will hold a pointer to a temporary + /// past that temporaries' lifetime. + struct TRefOrNothing { + const T *TPtr; + + TRefOrNothing() : TPtr(nullptr) {} + TRefOrNothing(const T &TRef) : TPtr(&TRef) {} + }; + public: /// @name Constructors /// @{ @@ -90,6 +104,14 @@ namespace llvm { Length(Vec.size()) {} #endif + /// Construct an ArrayRef from ArrayRef. This uses SFINAE to + /// ensure that only ArrayRefs of pointers can be converted. + template + ArrayRef(const ArrayRef &A, + typename std::enable_if< + std::is_convertible::value>::type* = 0) + : Data(A.data()), Length(A.size()) {} + /// @} /// @name Simple Operations /// @{ @@ -131,7 +153,13 @@ namespace llvm { bool equals(ArrayRef RHS) const { if (Length != RHS.Length) return false; - return std::equal(begin(), end(), RHS.begin()); + // Don't use std::equal(), since it asserts in MSVC on nullptr iterators. + for (auto L = begin(), LE = end(), R = RHS.begin(); L != LE; ++L, ++R) + // Match std::equal() in using == (instead of !=) to minimize API + // requirements of ArrayRef'ed types. + if (!(*L == *R)) + return false; + return true; } /// slice(n) - Chop off the first N elements of the array. @@ -176,6 +204,47 @@ namespace llvm { } /// @} + /// @{ + /// @name Convenience methods + + /// @brief Predicate for testing that the array equals the exact sequence of + /// arguments. + /// + /// Will return false if the size is not equal to the exact number of + /// arguments given or if the array elements don't equal the argument + /// elements in order. Currently supports up to 16 arguments, but can + /// easily be extended. + bool equals(TRefOrNothing Arg0 = TRefOrNothing(), + TRefOrNothing Arg1 = TRefOrNothing(), + TRefOrNothing Arg2 = TRefOrNothing(), + TRefOrNothing Arg3 = TRefOrNothing(), + TRefOrNothing Arg4 = TRefOrNothing(), + TRefOrNothing Arg5 = TRefOrNothing(), + TRefOrNothing Arg6 = TRefOrNothing(), + TRefOrNothing Arg7 = TRefOrNothing(), + TRefOrNothing Arg8 = TRefOrNothing(), + TRefOrNothing Arg9 = TRefOrNothing(), + TRefOrNothing Arg10 = TRefOrNothing(), + TRefOrNothing Arg11 = TRefOrNothing(), + TRefOrNothing Arg12 = TRefOrNothing(), + TRefOrNothing Arg13 = TRefOrNothing(), + TRefOrNothing Arg14 = TRefOrNothing(), + TRefOrNothing Arg15 = TRefOrNothing()) { + TRefOrNothing Args[] = {Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, + Arg6, Arg7, Arg8, Arg9, Arg10, Arg11, + Arg12, Arg13, Arg14, Arg15}; + if (size() > array_lengthof(Args)) + return false; + + for (unsigned i = 0, e = size(); i != e; ++i) + if (Args[i].TPtr == nullptr || (*this)[i] != *Args[i].TPtr) + return false; + + // Either the size is exactly as many args, or the next arg must be null. + return size() == array_lengthof(Args) || Args[size()].TPtr == nullptr; + } + + /// @} }; /// MutableArrayRef - Represent a mutable reference to an array (0 or more diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h index 34e2284..a40f694 100644 --- a/include/llvm/ADT/BitVector.h +++ b/include/llvm/ADT/BitVector.h @@ -239,6 +239,7 @@ public: } BitVector &set(unsigned Idx) { + assert(Bits && "Bits never allocated"); Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE); return *this; } @@ -450,6 +451,7 @@ public: // Grow the bitvector to have enough elements. Capacity = RHSWords; + assert(Capacity > 0 && "negative capacity?"); BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord)); std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord)); @@ -545,6 +547,7 @@ private: void grow(unsigned NewSize) { Capacity = std::max(NumBitWords(NewSize), Capacity * 2); + assert(Capacity > 0 && "realloc-ing zero space"); Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord)); clear_unused_bits(); diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 85f37b9..050f8ac 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -31,26 +31,35 @@ namespace llvm { -template, - bool IsConst = false> +namespace detail { +// We extend a pair to allow users to override the bucket type with their own +// implementation without requiring two members. +template +struct DenseMapPair : public std::pair { + KeyT &getFirst() { return std::pair::first; } + const KeyT &getFirst() const { return std::pair::first; } + ValueT &getSecond() { return std::pair::second; } + const ValueT &getSecond() const { return std::pair::second; } +}; +} + +template < + typename KeyT, typename ValueT, typename KeyInfoT = DenseMapInfo, + typename Bucket = detail::DenseMapPair, bool IsConst = false> class DenseMapIterator; -template +template class DenseMapBase { -protected: - typedef std::pair BucketT; - public: typedef unsigned size_type; typedef KeyT key_type; typedef ValueT mapped_type; typedef BucketT value_type; - typedef DenseMapIterator iterator; - typedef DenseMapIterator const_iterator; + typedef DenseMapIterator iterator; + typedef DenseMapIterator + const_iterator; inline iterator begin() { // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). return empty() ? end() : iterator(getBuckets(), getBucketsEnd()); @@ -88,12 +97,12 @@ public: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey)) { - if (!KeyInfoT::isEqual(P->first, TombstoneKey)) { - P->second.~ValueT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { + P->getSecond().~ValueT(); decrementNumEntries(); } - P->first = EmptyKey; + P->getFirst() = EmptyKey; } } assert(getNumEntries() == 0 && "Node count imbalance!"); @@ -144,7 +153,7 @@ public: ValueT lookup(const KeyT &Val) const { const BucketT *TheBucket; if (LookupBucketFor(Val, TheBucket)) - return TheBucket->second; + return TheBucket->getSecond(); return ValueT(); } @@ -191,16 +200,16 @@ public: if (!LookupBucketFor(Val, TheBucket)) return false; // not in map. - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); return true; } void erase(iterator I) { BucketT *TheBucket = &*I; - TheBucket->second.~ValueT(); - TheBucket->first = getTombstoneKey(); + TheBucket->getSecond().~ValueT(); + TheBucket->getFirst() = getTombstoneKey(); decrementNumEntries(); incrementNumTombstones(); } @@ -250,10 +259,10 @@ protected: const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) - P->second.~ValueT(); - P->first.~KeyT(); + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) + P->getSecond().~ValueT(); + P->getFirst().~KeyT(); } #ifndef NDEBUG @@ -269,7 +278,7 @@ protected: "# initial buckets must be a power of two!"); const KeyT EmptyKey = getEmptyKey(); for (BucketT *B = getBuckets(), *E = getBucketsEnd(); B != E; ++B) - new (&B->first) KeyT(EmptyKey); + new (&B->getFirst()) KeyT(EmptyKey); } void moveFromOldBuckets(BucketT *OldBucketsBegin, BucketT *OldBucketsEnd) { @@ -279,21 +288,21 @@ protected: const KeyT EmptyKey = getEmptyKey(); const KeyT TombstoneKey = getTombstoneKey(); for (BucketT *B = OldBucketsBegin, *E = OldBucketsEnd; B != E; ++B) { - if (!KeyInfoT::isEqual(B->first, EmptyKey) && - !KeyInfoT::isEqual(B->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(B->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(B->getFirst(), TombstoneKey)) { // Insert the key/value into the new table. BucketT *DestBucket; - bool FoundVal = LookupBucketFor(B->first, DestBucket); + bool FoundVal = LookupBucketFor(B->getFirst(), DestBucket); (void)FoundVal; // silence warning. assert(!FoundVal && "Key already in new map?"); - DestBucket->first = std::move(B->first); - new (&DestBucket->second) ValueT(std::move(B->second)); + DestBucket->getFirst() = std::move(B->getFirst()); + new (&DestBucket->getSecond()) ValueT(std::move(B->getSecond())); incrementNumEntries(); // Free the value. - B->second.~ValueT(); + B->getSecond().~ValueT(); } - B->first.~KeyT(); + B->getFirst().~KeyT(); } #ifndef NDEBUG @@ -304,7 +313,9 @@ protected: } template - void copyFrom(const DenseMapBase& other) { + void copyFrom( + const DenseMapBase &other) { + assert(&other != this); assert(getNumBuckets() == other.getNumBuckets()); setNumEntries(other.getNumEntries()); @@ -315,10 +326,12 @@ protected: getNumBuckets() * sizeof(BucketT)); else for (size_t i = 0; i < getNumBuckets(); ++i) { - new (&getBuckets()[i].first) KeyT(other.getBuckets()[i].first); - if (!KeyInfoT::isEqual(getBuckets()[i].first, getEmptyKey()) && - !KeyInfoT::isEqual(getBuckets()[i].first, getTombstoneKey())) - new (&getBuckets()[i].second) ValueT(other.getBuckets()[i].second); + new (&getBuckets()[i].getFirst()) + KeyT(other.getBuckets()[i].getFirst()); + if (!KeyInfoT::isEqual(getBuckets()[i].getFirst(), getEmptyKey()) && + !KeyInfoT::isEqual(getBuckets()[i].getFirst(), getTombstoneKey())) + new (&getBuckets()[i].getSecond()) + ValueT(other.getBuckets()[i].getSecond()); } } @@ -395,8 +408,8 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(Value); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(Value); return TheBucket; } @@ -404,16 +417,16 @@ private: BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = Key; - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = Key; + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } BucketT *InsertIntoBucket(KeyT &&Key, ValueT &&Value, BucketT *TheBucket) { TheBucket = InsertIntoBucketImpl(Key, TheBucket); - TheBucket->first = std::move(Key); - new (&TheBucket->second) ValueT(std::move(Value)); + TheBucket->getFirst() = std::move(Key); + new (&TheBucket->getSecond()) ValueT(std::move(Value)); return TheBucket; } @@ -445,7 +458,7 @@ private: // If we are writing over a tombstone, remember this. const KeyT EmptyKey = getEmptyKey(); - if (!KeyInfoT::isEqual(TheBucket->first, EmptyKey)) + if (!KeyInfoT::isEqual(TheBucket->getFirst(), EmptyKey)) decrementNumTombstones(); return TheBucket; @@ -479,14 +492,14 @@ private: while (1) { const BucketT *ThisBucket = BucketsPtr + BucketNo; // Found Val's bucket? If so, return it. - if (KeyInfoT::isEqual(Val, ThisBucket->first)) { + if (KeyInfoT::isEqual(Val, ThisBucket->getFirst())) { FoundBucket = ThisBucket; return true; } // If we found an empty bucket, the key doesn't exist in the set. // Insert it and return the default value. - if (KeyInfoT::isEqual(ThisBucket->first, EmptyKey)) { + if (KeyInfoT::isEqual(ThisBucket->getFirst(), EmptyKey)) { // If we've already seen a tombstone while probing, fill it in instead // of the empty bucket we eventually probed to. FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; @@ -495,7 +508,8 @@ private: // If this is a tombstone, remember it. If Val ends up not in the map, we // prefer to return it than something that would require more probing. - if (KeyInfoT::isEqual(ThisBucket->first, TombstoneKey) && !FoundTombstone) + if (KeyInfoT::isEqual(ThisBucket->getFirst(), TombstoneKey) && + !FoundTombstone) FoundTombstone = ThisBucket; // Remember the first tombstone found. // Otherwise, it's a hash collision or a tombstone, continue quadratic @@ -524,16 +538,15 @@ public: } }; -template > -class DenseMap - : public DenseMapBase, - KeyT, ValueT, KeyInfoT> { +template , + typename BucketT = detail::DenseMapPair> +class DenseMap : public DenseMapBase, + KeyT, ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase; + typedef DenseMapBase BaseT; + friend class DenseMapBase; BucketT *Buckets; unsigned NumEntries; @@ -574,7 +587,8 @@ public: } DenseMap& operator=(const DenseMap& other) { - copyFrom(other); + if (&other != this) + copyFrom(other); return *this; } @@ -675,17 +689,17 @@ private: } }; -template > +template , + typename BucketT = detail::DenseMapPair> class SmallDenseMap - : public DenseMapBase, - KeyT, ValueT, KeyInfoT> { + : public DenseMapBase< + SmallDenseMap, KeyT, + ValueT, KeyInfoT, BucketT> { // Lift some types from the dependent base class into this class for // simplicity of referring to them. - typedef DenseMapBase BaseT; - typedef typename BaseT::BucketT BucketT; - friend class DenseMapBase; + typedef DenseMapBase BaseT; + friend class DenseMapBase; unsigned Small : 1; unsigned NumEntries : 31; @@ -742,23 +756,23 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *LHSB = &getInlineBuckets()[i], *RHSB = &RHS.getInlineBuckets()[i]; - bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->first, EmptyKey) && - !KeyInfoT::isEqual(LHSB->first, TombstoneKey)); - bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->first, EmptyKey) && - !KeyInfoT::isEqual(RHSB->first, TombstoneKey)); + bool hasLHSValue = (!KeyInfoT::isEqual(LHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(LHSB->getFirst(), TombstoneKey)); + bool hasRHSValue = (!KeyInfoT::isEqual(RHSB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(RHSB->getFirst(), TombstoneKey)); if (hasLHSValue && hasRHSValue) { // Swap together if we can... std::swap(*LHSB, *RHSB); continue; } // Swap separately and handle any assymetry. - std::swap(LHSB->first, RHSB->first); + std::swap(LHSB->getFirst(), RHSB->getFirst()); if (hasLHSValue) { - new (&RHSB->second) ValueT(std::move(LHSB->second)); - LHSB->second.~ValueT(); + new (&RHSB->getSecond()) ValueT(std::move(LHSB->getSecond())); + LHSB->getSecond().~ValueT(); } else if (hasRHSValue) { - new (&LHSB->second) ValueT(std::move(RHSB->second)); - RHSB->second.~ValueT(); + new (&LHSB->getSecond()) ValueT(std::move(RHSB->getSecond())); + RHSB->getSecond().~ValueT(); } } return; @@ -783,12 +797,12 @@ public: for (unsigned i = 0, e = InlineBuckets; i != e; ++i) { BucketT *NewB = &LargeSide.getInlineBuckets()[i], *OldB = &SmallSide.getInlineBuckets()[i]; - new (&NewB->first) KeyT(std::move(OldB->first)); - OldB->first.~KeyT(); - if (!KeyInfoT::isEqual(NewB->first, EmptyKey) && - !KeyInfoT::isEqual(NewB->first, TombstoneKey)) { - new (&NewB->second) ValueT(std::move(OldB->second)); - OldB->second.~ValueT(); + new (&NewB->getFirst()) KeyT(std::move(OldB->getFirst())); + OldB->getFirst().~KeyT(); + if (!KeyInfoT::isEqual(NewB->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(NewB->getFirst(), TombstoneKey)) { + new (&NewB->getSecond()) ValueT(std::move(OldB->getSecond())); + OldB->getSecond().~ValueT(); } } @@ -799,7 +813,8 @@ public: } SmallDenseMap& operator=(const SmallDenseMap& other) { - copyFrom(other); + if (&other != this) + copyFrom(other); return *this; } @@ -849,16 +864,16 @@ public: const KeyT EmptyKey = this->getEmptyKey(); const KeyT TombstoneKey = this->getTombstoneKey(); for (BucketT *P = getBuckets(), *E = P + InlineBuckets; P != E; ++P) { - if (!KeyInfoT::isEqual(P->first, EmptyKey) && - !KeyInfoT::isEqual(P->first, TombstoneKey)) { + if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey) && + !KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { assert(size_t(TmpEnd - TmpBegin) < InlineBuckets && "Too many inline buckets!"); - new (&TmpEnd->first) KeyT(std::move(P->first)); - new (&TmpEnd->second) ValueT(std::move(P->second)); + new (&TmpEnd->getFirst()) KeyT(std::move(P->getFirst())); + new (&TmpEnd->getSecond()) ValueT(std::move(P->getSecond())); ++TmpEnd; - P->second.~ValueT(); + P->getSecond().~ValueT(); } - P->first.~KeyT(); + P->getFirst().~KeyT(); } // Now make this map use the large rep, and move all the entries back @@ -969,13 +984,12 @@ private: } }; -template +template class DenseMapIterator { - typedef std::pair Bucket; - typedef DenseMapIterator ConstIterator; - friend class DenseMapIterator; + typedef DenseMapIterator ConstIterator; + friend class DenseMapIterator; + public: typedef ptrdiff_t difference_type; typedef typename std::conditional::type @@ -996,9 +1010,9 @@ public: // If IsConst is true this is a converting constructor from iterator to // const_iterator and the default copy constructor is used. // Otherwise this is a copy constructor for iterator. - DenseMapIterator(const DenseMapIterator& I) - : Ptr(I.Ptr), End(I.End) {} + DenseMapIterator( + const DenseMapIterator &I) + : Ptr(I.Ptr), End(I.End) {} reference operator*() const { return *Ptr; @@ -1028,9 +1042,8 @@ private: const KeyT Empty = KeyInfoT::getEmptyKey(); const KeyT Tombstone = KeyInfoT::getTombstoneKey(); - while (Ptr != End && - (KeyInfoT::isEqual(Ptr->first, Empty) || - KeyInfoT::isEqual(Ptr->first, Tombstone))) + while (Ptr != End && (KeyInfoT::isEqual(Ptr->getFirst(), Empty) || + KeyInfoT::isEqual(Ptr->getFirst(), Tombstone))) ++Ptr; } }; diff --git a/include/llvm/ADT/DenseSet.h b/include/llvm/ADT/DenseSet.h index 37a81b0..d340240 100644 --- a/include/llvm/ADT/DenseSet.h +++ b/include/llvm/ADT/DenseSet.h @@ -18,18 +18,34 @@ namespace llvm { +namespace detail { +struct DenseSetEmpty {}; + +// Use the empty base class trick so we can create a DenseMap where the buckets +// contain only a single item. +template class DenseSetPair : public DenseSetEmpty { + KeyT key; + +public: + KeyT &getFirst() { return key; } + const KeyT &getFirst() const { return key; } + DenseSetEmpty &getSecond() { return *this; } + const DenseSetEmpty &getSecond() const { return *this; } +}; +} + /// DenseSet - This implements a dense probed hash-table based set. -/// -/// FIXME: This is currently implemented directly in terms of DenseMap, this -/// should be optimized later if there is a need. template > class DenseSet { - typedef DenseMap MapTy; + typedef DenseMap> MapTy; + static_assert(sizeof(typename MapTy::value_type) == sizeof(ValueT), + "DenseMap buckets unexpectedly large!"); MapTy TheMap; public: typedef ValueT key_type; typedef ValueT value_type; - typedef unsigned size_type; + typedef unsigned size_type; explicit DenseSet(unsigned NumInitBuckets = 0) : TheMap(NumInitBuckets) {} @@ -45,7 +61,7 @@ public: TheMap.clear(); } - /// Return 1 if the specified key is in the set, 0 otherwise. + /// Return 1 if the specified key is in the set, 0 otherwise. size_type count(const ValueT &V) const { return TheMap.count(V); } @@ -72,8 +88,8 @@ public: Iterator(const typename MapTy::iterator &i) : I(i) {} - ValueT& operator*() { return I->first; } - ValueT* operator->() { return &I->first; } + ValueT &operator*() { return I->getFirst(); } + ValueT *operator->() { return &I->getFirst(); } Iterator& operator++() { ++I; return *this; } bool operator==(const Iterator& X) const { return I == X.I; } @@ -92,8 +108,8 @@ public: ConstIterator(const typename MapTy::const_iterator &i) : I(i) {} - const ValueT& operator*() { return I->first; } - const ValueT* operator->() { return &I->first; } + const ValueT &operator*() { return I->getFirst(); } + const ValueT *operator->() { return &I->getFirst(); } ConstIterator& operator++() { ++I; return *this; } bool operator==(const ConstIterator& X) const { return I == X.I; } @@ -110,11 +126,27 @@ public: const_iterator end() const { return ConstIterator(TheMap.end()); } iterator find(const ValueT &V) { return Iterator(TheMap.find(V)); } + + /// Alternative version of find() which allows a different, and possibly less + /// expensive, key type. + /// The DenseMapInfo is responsible for supplying methods + /// getHashValue(LookupKeyT) and isEqual(LookupKeyT, KeyT) for each key type + /// used. + template + iterator find_as(const LookupKeyT &Val) { + return Iterator(TheMap.find_as(Val)); + } + template + const_iterator find_as(const LookupKeyT &Val) const { + return ConstIterator(TheMap.find_as(Val)); + } + void erase(Iterator I) { return TheMap.erase(I.I); } void erase(ConstIterator CI) { return TheMap.erase(CI.I); } std::pair insert(const ValueT &V) { - return TheMap.insert(std::make_pair(V, 0)); + detail::DenseSetEmpty Empty; + return TheMap.insert(std::make_pair(V, Empty)); } // Range insertion of values. diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index dfba43f..6cd9e68 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -33,10 +33,10 @@ #ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H #define LLVM_ADT_DEPTHFIRSTITERATOR_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include #include @@ -231,6 +231,13 @@ df_ext_iterator df_ext_end(const T& G, SetTy &S) { return df_ext_iterator::end(G, S); } +template +iterator_range> depth_first_ext(const T& G, + SetTy &S) { + return iterator_range>(df_ext_begin(G, S), + df_ext_end(G, S)); +} + // Provide global definitions of inverse depth first iterators... template idf_ext_end(const T& G, SetTy &S) { return idf_ext_iterator::end(Inverse(G), S); } +template +iterator_range> inverse_depth_first_ext(const T& G, + SetTy &S) { + return iterator_range>(idf_ext_begin(G, S), + idf_ext_end(G, S)); +} + } // End llvm namespace #endif diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index f9df378..c859c98 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -197,6 +197,9 @@ public: private: void retain() { if (Obj) IntrusiveRefCntPtrInfo::retain(Obj); } void release() { if (Obj) IntrusiveRefCntPtrInfo::release(Obj); } + + template + friend class IntrusiveRefCntPtr; }; template diff --git a/include/llvm/ADT/MapVector.h b/include/llvm/ADT/MapVector.h index 4e1fc15..1331b15 100644 --- a/include/llvm/ADT/MapVector.h +++ b/include/llvm/ADT/MapVector.h @@ -18,6 +18,7 @@ #define LLVM_ADT_MAPVECTOR_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include namespace llvm { @@ -37,26 +38,20 @@ class MapVector { public: typedef typename VectorType::iterator iterator; typedef typename VectorType::const_iterator const_iterator; + typedef typename VectorType::reverse_iterator reverse_iterator; + typedef typename VectorType::const_reverse_iterator const_reverse_iterator; - size_type size() const { - return Vector.size(); - } - - iterator begin() { - return Vector.begin(); - } + size_type size() const { return Vector.size(); } - const_iterator begin() const { - return Vector.begin(); - } - - iterator end() { - return Vector.end(); - } + iterator begin() { return Vector.begin(); } + const_iterator begin() const { return Vector.begin(); } + iterator end() { return Vector.end(); } + const_iterator end() const { return Vector.end(); } - const_iterator end() const { - return Vector.end(); - } + reverse_iterator rbegin() { return Vector.rbegin(); } + const_reverse_iterator rbegin() const { return Vector.rbegin(); } + reverse_iterator rend() { return Vector.rend(); } + const_reverse_iterator rend() const { return Vector.rend(); } bool empty() const { return Vector.empty(); @@ -147,6 +142,17 @@ public: return Next; } + /// \brief Remove all elements with the key value Key. + /// + /// Returns the number of elements removed. + size_type erase(const KeyT &Key) { + auto Iterator = find(Key); + if (Iterator == end()) + return 0; + erase(Iterator); + return 1; + } + /// \brief Remove the elements that match the predicate. /// /// Erase all elements that match \c Pred in a single pass. Takes linear @@ -176,6 +182,14 @@ void MapVector::remove_if(Function Pred) { Vector.erase(O, Vector.end()); } +/// \brief A MapVector that performs no allocations if smaller than a certain +/// size. +template +struct SmallMapVector + : MapVector, + SmallVector, N>> { +}; + } // end namespace llvm #endif diff --git a/include/llvm/ADT/Optional.h b/include/llvm/ADT/Optional.h index ae8344d..591872e 100644 --- a/include/llvm/ADT/Optional.h +++ b/include/llvm/ADT/Optional.h @@ -20,6 +20,7 @@ #include "llvm/Support/AlignOf.h" #include "llvm/Support/Compiler.h" #include +#include #include namespace llvm { @@ -29,6 +30,8 @@ class Optional { AlignedCharArrayUnion storage; bool hasVal; public: + typedef T value_type; + Optional(NoneType) : hasVal(false) {} explicit Optional() : hasVal(false) {} Optional(const T &y) : hasVal(true) { @@ -67,6 +70,61 @@ public: return *this; } +#if LLVM_HAS_VARIADIC_TEMPLATES + + /// Create a new object by constructing it in place with the given arguments. + template + void emplace(ArgTypes &&...Args) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward(Args)...); + } + +#else + + /// Create a new object by default-constructing it in place. + void emplace() { + reset(); + hasVal = true; + new (storage.buffer) T(); + } + + /// Create a new object by constructing it in place with the given arguments. + template + void emplace(T1 &&A1) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward(A1)); + } + + /// Create a new object by constructing it in place with the given arguments. + template + void emplace(T1 &&A1, T2 &&A2) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward(A1), std::forward(A2)); + } + + /// Create a new object by constructing it in place with the given arguments. + template + void emplace(T1 &&A1, T2 &&A2, T3 &&A3) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward(A1), std::forward(A2), + std::forward(A3)); + } + + /// Create a new object by constructing it in place with the given arguments. + template + void emplace(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { + reset(); + hasVal = true; + new (storage.buffer) T(std::forward(A1), std::forward(A2), + std::forward(A3), std::forward(A4)); + } + +#endif // LLVM_HAS_VARIADIC_TEMPLATES + static inline Optional create(const T* y) { return y ? Optional(*y) : Optional(); } @@ -117,9 +175,19 @@ public: const T& operator*() const LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } T& operator*() LLVM_LVALUE_FUNCTION { assert(hasVal); return *getPointer(); } + template + LLVM_CONSTEXPR T getValueOr(U &&value) const LLVM_LVALUE_FUNCTION { + return hasValue() ? getValue() : std::forward(value); + } + #if LLVM_HAS_RVALUE_REFERENCE_THIS T&& getValue() && { assert(hasVal); return std::move(*getPointer()); } T&& operator*() && { assert(hasVal); return std::move(*getPointer()); } + + template + T getValueOr(U &&value) && { + return hasValue() ? std::move(getValue()) : std::forward(value); + } #endif }; diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index dd8cc74..dfadc3b 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -57,7 +57,7 @@ public: // Return true if edge destination should be visited. template bool insertEdge(NodeType *From, NodeType *To) { - return Visited.insert(To); + return Visited.insert(To).second; } // Called after all children of BB have been visited. @@ -76,8 +76,9 @@ public: // Return true if edge destination should be visited, called with From = 0 for // the root node. // Graph edges can be pruned by specializing this function. - template - bool insertEdge(NodeType *From, NodeType *To) { return Visited.insert(To); } + template bool insertEdge(NodeType *From, NodeType *To) { + return Visited.insert(To).second; + } // Called after all children of BB have been visited. template diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 1cef393..4e56e4d 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -77,8 +77,11 @@ class function_ref { } public: - template - function_ref(Callable &&callable) + template + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn::type>), callable(reinterpret_cast(&callable)) {} Ret operator()(Params ...params) const { @@ -100,7 +103,10 @@ class function_ref { public: template - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn::type>), callable(reinterpret_cast(&callable)) {} Ret operator()() const { return callback(callable); } @@ -119,7 +125,10 @@ class function_ref { public: template - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn::type>), callable(reinterpret_cast(&callable)) {} Ret operator()(Param1 param1) { @@ -141,7 +150,10 @@ class function_ref { public: template - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn::type>), callable(reinterpret_cast(&callable)) {} Ret operator()(Param1 param1, Param2 param2) { @@ -167,7 +179,10 @@ class function_ref { public: template - function_ref(Callable &&callable) + function_ref(Callable &&callable, + typename std::enable_if< + !std::is_same::type, + function_ref>::value>::type * = nullptr) : callback(callback_fn::type>), callable(reinterpret_cast(&callable)) {} Ret operator()(Param1 param1, Param2 param2, Param3 param3) { @@ -530,6 +545,12 @@ make_unique(size_t n) { #endif +struct FreeDeleter { + void operator()(void* v) { + ::free(v); + } +}; + template struct pair_hash { size_t operator()(const std::pair &P) const { diff --git a/include/llvm/ADT/ScopedHashTable.h b/include/llvm/ADT/ScopedHashTable.h index 02a6ea3..2f60ecc 100644 --- a/include/llvm/ADT/ScopedHashTable.h +++ b/include/llvm/ADT/ScopedHashTable.h @@ -148,7 +148,7 @@ public: /// ScopeTy - This is a helpful typedef that allows clients to get easy access /// to the name of the scope for this hash table. typedef ScopedHashTableScope ScopeTy; - typedef unsigned size_type; + typedef unsigned size_type; private: typedef ScopedHashTableVal ValTy; DenseMap TopLevelMap; @@ -171,7 +171,7 @@ public: AllocatorTy &getAllocator() { return Allocator; } const AllocatorTy &getAllocator() const { return Allocator; } - /// Return 1 if the specified key is in the table, 0 otherwise. + /// Return 1 if the specified key is in the table, 0 otherwise. size_type count(const K &Key) const { return TopLevelMap.count(Key); } diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h index 1e7d237..a7fd408 100644 --- a/include/llvm/ADT/SetVector.h +++ b/include/llvm/ADT/SetVector.h @@ -100,7 +100,7 @@ public: /// \brief Insert a new element into the SetVector. /// \returns true iff the element was inserted into the SetVector. bool insert(const value_type &X) { - bool result = set_.insert(X); + bool result = set_.insert(X).second; if (result) vector_.push_back(X); return result; @@ -110,7 +110,7 @@ public: template void insert(It Start, It End) { for (; Start != End; ++Start) - if (set_.insert(*Start)) + if (set_.insert(*Start).second) vector_.push_back(*Start); } diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index 0922017..1e2f365 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -54,7 +54,7 @@ class SmallBitVector { }; public: - typedef unsigned size_type; + typedef unsigned size_type; // Encapsulation of a single bit. class reference { SmallBitVector &TheVector; @@ -292,8 +292,12 @@ public: } SmallBitVector &set(unsigned Idx) { - if (isSmall()) + if (isSmall()) { + assert(Idx <= static_cast( + std::numeric_limits::digits) && + "undefined behavior"); setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); + } else getPointer()->set(Idx); return *this; diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h index 74f3fd4..cb1c5e1 100644 --- a/include/llvm/ADT/SmallPtrSet.h +++ b/include/llvm/ADT/SmallPtrSet.h @@ -22,6 +22,7 @@ #include #include #include +#include namespace llvm { @@ -100,7 +101,7 @@ protected: /// insert_imp - This returns true if the pointer was new to the set, false if /// it was already in the set. This is hidden from the client so that the /// derived class can check that the right type of pointer is passed in. - bool insert_imp(const void * Ptr); + std::pair insert_imp(const void *Ptr); /// erase_imp - If the set contains the specified pointer, remove it and /// return true, otherwise return false. This is hidden from the client so @@ -240,6 +241,8 @@ struct RoundUpToPowerOfTwo { template class SmallPtrSetImpl : public SmallPtrSetImplBase { typedef PointerLikeTypeTraits PtrTraits; + + SmallPtrSetImpl(const SmallPtrSetImpl&) LLVM_DELETED_FUNCTION; protected: // Constructors that forward to the base. SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl &that) @@ -251,10 +254,16 @@ protected: : SmallPtrSetImplBase(SmallStorage, SmallSize) {} public: - /// insert - This returns true if the pointer was new to the set, false if it - /// was already in the set. - bool insert(PtrType Ptr) { - return insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + typedef SmallPtrSetIterator iterator; + typedef SmallPtrSetIterator const_iterator; + + /// Inserts Ptr if and only if there is no element in the container equal to + /// Ptr. The bool component of the returned pair is true if and only if the + /// insertion takes place, and the iterator component of the pair points to + /// the element equal to Ptr. + std::pair insert(PtrType Ptr) { + auto p = insert_imp(PtrTraits::getAsVoidPointer(Ptr)); + return std::make_pair(iterator(p.first, CurArray + CurArraySize), p.second); } /// erase - If the set contains the specified pointer, remove it and return @@ -274,8 +283,6 @@ public: insert(*I); } - typedef SmallPtrSetIterator iterator; - typedef SmallPtrSetIterator const_iterator; inline iterator begin() const { return iterator(CurArray, CurArray+CurArraySize); } diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h index bb1971e..bc64935 100644 --- a/include/llvm/ADT/SmallSet.h +++ b/include/llvm/ADT/SmallSet.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_SMALLSET_H #define LLVM_ADT_SMALLSET_H +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include @@ -60,16 +61,21 @@ public: /// insert - Insert an element into the set if it isn't already there. /// Returns true if the element is inserted (it was not in the set before). - bool insert(const T &V) { + /// The first value of the returned pair is unused and provided for + /// partial compatibility with the standard library self-associative container + /// concept. + // FIXME: Add iterators that abstract over the small and large form, and then + // return those here. + std::pair insert(const T &V) { if (!isSmall()) - return Set.insert(V).second; + return std::make_pair(None, Set.insert(V).second); VIterator I = vfind(V); if (I != Vector.end()) // Don't reinsert if it already exists. - return false; + return std::make_pair(None, false); if (Vector.size() < N) { Vector.push_back(V); - return true; + return std::make_pair(None, true); } // Otherwise, grow from vector to set. @@ -78,7 +84,7 @@ public: Vector.pop_back(); } Set.insert(V); - return true; + return std::make_pair(None, true); } template diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h index 82538e9..44a3521 100644 --- a/include/llvm/ADT/SmallVector.h +++ b/include/llvm/ADT/SmallVector.h @@ -29,8 +29,7 @@ namespace llvm { -/// SmallVectorBase - This is all the non-templated stuff common to all -/// SmallVectors. +/// This is all the non-templated stuff common to all SmallVectors. class SmallVectorBase { protected: void *BeginX, *EndX, *CapacityX; @@ -39,12 +38,12 @@ protected: SmallVectorBase(void *FirstEl, size_t Size) : BeginX(FirstEl), EndX(FirstEl), CapacityX((char*)FirstEl+Size) {} - /// grow_pod - This is an implementation of the grow() method which only works + /// This is an implementation of the grow() method which only works /// on POD-like data types and is out of line to reduce code duplication. void grow_pod(void *FirstEl, size_t MinSizeInBytes, size_t TSize); public: - /// size_in_bytes - This returns size()*sizeof(T). + /// This returns size()*sizeof(T). size_t size_in_bytes() const { return size_t((char*)EndX - (char*)BeginX); } @@ -59,10 +58,9 @@ public: template struct SmallVectorStorage; -/// SmallVectorTemplateCommon - This is the part of SmallVectorTemplateBase -/// which does not depend on whether the type T is a POD. The extra dummy -/// template argument is used by ArrayRef to avoid unnecessarily requiring T -/// to be complete. +/// This is the part of SmallVectorTemplateBase which does not depend on whether +/// the type T is a POD. The extra dummy template argument is used by ArrayRef +/// to avoid unnecessarily requiring T to be complete. template class SmallVectorTemplateCommon : public SmallVectorBase { private: @@ -82,13 +80,13 @@ protected: SmallVectorBase::grow_pod(&FirstEl, MinSizeInBytes, TSize); } - /// isSmall - Return true if this is a smallvector which has not had dynamic + /// Return true if this is a smallvector which has not had dynamic /// memory allocated for it. bool isSmall() const { return BeginX == static_cast(&FirstEl); } - /// resetToSmall - Put this vector in a state of being small. + /// Put this vector in a state of being small. void resetToSmall() { BeginX = EndX = CapacityX = &FirstEl; } @@ -128,21 +126,20 @@ public: size_type size() const { return end()-begin(); } size_type max_size() const { return size_type(-1) / sizeof(T); } - /// capacity - Return the total number of elements in the currently allocated - /// buffer. + /// Return the total number of elements in the currently allocated buffer. size_t capacity() const { return capacity_ptr() - begin(); } - /// data - Return a pointer to the vector's buffer, even if empty(). + /// Return a pointer to the vector's buffer, even if empty(). pointer data() { return pointer(begin()); } - /// data - Return a pointer to the vector's buffer, even if empty(). + /// Return a pointer to the vector's buffer, even if empty(). const_pointer data() const { return const_pointer(begin()); } - reference operator[](unsigned idx) { - assert(begin() + idx < end()); + reference operator[](size_type idx) { + assert(idx < size()); return begin()[idx]; } - const_reference operator[](unsigned idx) const { - assert(begin() + idx < end()); + const_reference operator[](size_type idx) const { + assert(idx < size()); return begin()[idx]; } @@ -179,7 +176,7 @@ protected: } } - /// move - Use move-assignment to move the range [I, E) onto the + /// Use move-assignment to move the range [I, E) onto the /// objects starting with "Dest". This is just 's /// std::move, but not all stdlibs actually provide that. template @@ -189,7 +186,7 @@ protected: return Dest; } - /// move_backward - Use move-assignment to move the range + /// Use move-assignment to move the range /// [I, E) onto the objects ending at "Dest", moving objects /// in reverse order. This is just 's /// std::move_backward, but not all stdlibs actually provide that. @@ -200,25 +197,24 @@ protected: return Dest; } - /// uninitialized_move - Move the range [I, E) into the uninitialized - /// memory starting with "Dest", constructing elements as needed. + /// Move the range [I, E) into the uninitialized memory starting with "Dest", + /// constructing elements as needed. template static void uninitialized_move(It1 I, It1 E, It2 Dest) { for (; I != E; ++I, ++Dest) ::new ((void*) &*Dest) T(::std::move(*I)); } - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized - /// memory starting with "Dest", constructing elements as needed. + /// Copy the range [I, E) onto the uninitialized memory starting with "Dest", + /// constructing elements as needed. template static void uninitialized_copy(It1 I, It1 E, It2 Dest) { std::uninitialized_copy(I, E, Dest); } - /// grow - Grow the allocated memory (without initializing new - /// elements), doubling the size of the allocated memory. - /// Guarantees space for at least one more element, or MinSize more - /// elements if specified. + /// Grow the allocated memory (without initializing new elements), doubling + /// the size of the allocated memory. Guarantees space for at least one more + /// element, or MinSize more elements if specified. void grow(size_t MinSize = 0); public: @@ -240,6 +236,51 @@ public: this->setEnd(this->end()-1); this->end()->~T(); } + +#if LLVM_HAS_VARIADIC_TEMPLATES + template void emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void *)this->end()) T(std::forward(Args)...); + this->setEnd(this->end() + 1); + } +#else +private: + template void emplace_back_impl(Constructor construct) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + construct((void *)this->end()); + this->setEnd(this->end() + 1); + } + +public: + void emplace_back() { + emplace_back_impl([](void *Mem) { ::new (Mem) T(); }); + } + template void emplace_back(T1 &&A1) { + emplace_back_impl([&](void *Mem) { ::new (Mem) T(std::forward(A1)); }); + } + template void emplace_back(T1 &&A1, T2 &&A2) { + emplace_back_impl([&](void *Mem) { + ::new (Mem) T(std::forward(A1), std::forward(A2)); + }); + } + template + void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3) { + T(std::forward(A1), std::forward(A2), std::forward(A3)); + emplace_back_impl([&](void *Mem) { + ::new (Mem) + T(std::forward(A1), std::forward(A2), std::forward(A3)); + }); + } + template + void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { + emplace_back_impl([&](void *Mem) { + ::new (Mem) T(std::forward(A1), std::forward(A2), + std::forward(A3), std::forward(A4)); + }); + } +#endif // LLVM_HAS_VARIADIC_TEMPLATES }; // Define this out-of-line to dissuade the C++ compiler from inlining it. @@ -279,22 +320,21 @@ protected: // No need to do a destroy loop for POD's. static void destroy_range(T *, T *) {} - /// move - Use move-assignment to move the range [I, E) onto the + /// Use move-assignment to move the range [I, E) onto the /// objects starting with "Dest". For PODs, this is just memcpy. template static It2 move(It1 I, It1 E, It2 Dest) { return ::std::copy(I, E, Dest); } - /// move_backward - Use move-assignment to move the range - /// [I, E) onto the objects ending at "Dest", moving objects - /// in reverse order. + /// Use move-assignment to move the range [I, E) onto the objects ending at + /// "Dest", moving objects in reverse order. template static It2 move_backward(It1 I, It1 E, It2 Dest) { return ::std::copy_backward(I, E, Dest); } - /// uninitialized_move - Move the range [I, E) onto the uninitialized memory + /// Move the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template static void uninitialized_move(It1 I, It1 E, It2 Dest) { @@ -302,7 +342,7 @@ protected: uninitialized_copy(I, E, Dest); } - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template static void uninitialized_copy(It1 I, It1 E, It2 Dest) { @@ -310,7 +350,7 @@ protected: std::uninitialized_copy(I, E, Dest); } - /// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory + /// Copy the range [I, E) onto the uninitialized memory /// starting with "Dest", constructing elements into it as needed. template static void uninitialized_copy(T1 *I, T1 *E, T2 *Dest) { @@ -320,7 +360,7 @@ protected: memcpy(Dest, I, (E-I)*sizeof(T)); } - /// grow - double the size of the allocated memory, guaranteeing space for at + /// Double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. void grow(size_t MinSize = 0) { this->grow_pod(MinSize*sizeof(T), sizeof(T)); @@ -339,9 +379,8 @@ public: }; -/// SmallVectorImpl - This class consists of common code factored out of the -/// SmallVector class to reduce code duplication based on the SmallVector 'N' -/// template parameter. +/// This class consists of common code factored out of the SmallVector class to +/// reduce code duplication based on the SmallVector 'N' template parameter. template class SmallVectorImpl : public SmallVectorTemplateBase::value> { typedef SmallVectorTemplateBase::value > SuperClass; @@ -373,7 +412,7 @@ public: this->EndX = this->BeginX; } - void resize(unsigned N) { + void resize(size_type N) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -386,7 +425,7 @@ public: } } - void resize(unsigned N, const T &NV) { + void resize(size_type N, const T &NV) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -398,7 +437,7 @@ public: } } - void reserve(unsigned N) { + void reserve(size_type N) { if (this->capacity() < N) this->grow(N); } @@ -411,8 +450,7 @@ public: void swap(SmallVectorImpl &RHS); - /// append - Add the specified range to the end of the SmallVector. - /// + /// Add the specified range to the end of the SmallVector. template void append(in_iter in_start, in_iter in_end) { size_type NumInputs = std::distance(in_start, in_end); @@ -427,8 +465,7 @@ public: this->setEnd(this->end() + NumInputs); } - /// append - Add the specified range to the end of the SmallVector. - /// + /// Add the specified range to the end of the SmallVector. void append(size_type NumInputs, const T &Elt) { // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) @@ -439,7 +476,7 @@ public: this->setEnd(this->end() + NumInputs); } - void assign(unsigned NumElts, const T &Elt) { + void assign(size_type NumElts, const T &Elt) { clear(); if (this->capacity() < NumElts) this->grow(NumElts); @@ -545,7 +582,7 @@ public: assert(I <= this->end() && "Inserting past the end of the vector."); // Ensure there is enough space. - reserve(static_cast(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -599,7 +636,7 @@ public: size_t NumToInsert = std::distance(From, To); // Ensure there is enough space. - reserve(static_cast(this->size() + NumToInsert)); + reserve(this->size() + NumToInsert); // Uninvalidate the iterator. I = this->begin()+InsertElt; @@ -666,7 +703,7 @@ public: /// of the buffer when they know that more elements are available, and only /// update the size later. This avoids the cost of value initializing elements /// which will only be overwritten. - void set_size(unsigned N) { + void set_size(size_type N) { assert(N <= this->capacity()); this->setEnd(this->begin() + N); } @@ -692,7 +729,7 @@ void SmallVectorImpl::swap(SmallVectorImpl &RHS) { // Swap the shared elements. size_t NumShared = this->size(); if (NumShared > RHS.size()) NumShared = RHS.size(); - for (unsigned i = 0; i != static_cast(NumShared); ++i) + for (size_type i = 0; i != NumShared; ++i) std::swap((*this)[i], RHS[i]); // Copy over the extra elts. @@ -833,7 +870,7 @@ struct SmallVectorStorage { template struct SmallVectorStorage {}; template struct SmallVectorStorage {}; -/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized +/// This is a 'vector' (really, a variable-sized array), optimized /// for the case when the array is small. It contains some number of elements /// in-place, which allows it to avoid heap allocation when the actual number of /// elements is below that threshold. This allows normal "small" cases to be @@ -843,13 +880,13 @@ template struct SmallVectorStorage {}; /// template class SmallVector : public SmallVectorImpl { - /// Storage - Inline space for elements which aren't stored in the base class. + /// Inline space for elements which aren't stored in the base class. SmallVectorStorage Storage; public: SmallVector() : SmallVectorImpl(N) { } - explicit SmallVector(unsigned Size, const T &Value = T()) + explicit SmallVector(size_t Size, const T &Value = T()) : SmallVectorImpl(N) { this->assign(Size, Value); } diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 36754d6..d5bde29 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -45,7 +45,7 @@ struct SparseBitVectorElement : public ilist_node > { public: typedef unsigned long BitWord; - typedef unsigned size_type; + typedef unsigned size_type; enum { BITWORD_SIZE = sizeof(BitWord) * CHAR_BIT, BITWORDS_PER_ELEMENT = (ElementSize + BITWORD_SIZE - 1) / BITWORD_SIZE, diff --git a/include/llvm/ADT/SparseMultiSet.h b/include/llvm/ADT/SparseMultiSet.h index dc1273e..f858536 100644 --- a/include/llvm/ADT/SparseMultiSet.h +++ b/include/llvm/ADT/SparseMultiSet.h @@ -185,7 +185,7 @@ public: typedef const ValueT &const_reference; typedef ValueT *pointer; typedef const ValueT *const_pointer; - typedef unsigned size_type; + typedef unsigned size_type; SparseMultiSet() : Sparse(nullptr), Universe(0), FreelistIdx(SMSNode::INVALID), NumFree(0) {} diff --git a/include/llvm/ADT/SparseSet.h b/include/llvm/ADT/SparseSet.h index 632d52a..9a13440 100644 --- a/include/llvm/ADT/SparseSet.h +++ b/include/llvm/ADT/SparseSet.h @@ -124,7 +124,7 @@ class SparseSet { typedef typename KeyFunctorT::argument_type KeyT; typedef SmallVector DenseT; - typedef unsigned size_type; + typedef unsigned size_type; DenseT Dense; SparseT *Sparse; unsigned Universe; diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h index c40e5e2..3437607 100644 --- a/include/llvm/ADT/StringMap.h +++ b/include/llvm/ADT/StringMap.h @@ -117,8 +117,9 @@ public: explicit StringMapEntry(unsigned strLen) : StringMapEntryBase(strLen), second() {} - StringMapEntry(unsigned strLen, ValueTy V) - : StringMapEntryBase(strLen), second(std::move(V)) {} + template + StringMapEntry(unsigned strLen, InitTy &&V) + : StringMapEntryBase(strLen), second(std::forward(V)) {} StringRef getKey() const { return StringRef(getKeyData(), getKeyLength()); @@ -138,10 +139,9 @@ public: /// Create - Create a StringMapEntry for the specified key and default /// construct the value. - template - static StringMapEntry *Create(StringRef Key, - AllocatorTy &Allocator, - InitType InitVal) { + template + static StringMapEntry *Create(StringRef Key, AllocatorTy &Allocator, + InitType &&InitVal) { unsigned KeyLength = Key.size(); // Allocate a new item with space for the string at the end and a null @@ -154,7 +154,7 @@ public: static_cast(Allocator.Allocate(AllocSize,Alignment)); // Default construct the value. - new (NewItem) StringMapEntry(KeyLength, std::move(InitVal)); + new (NewItem) StringMapEntry(KeyLength, std::forward(InitVal)); // Copy the string information. char *StrBuffer = const_cast(NewItem->getKeyData()); @@ -170,28 +170,15 @@ public: /// Create - Create a StringMapEntry with normal malloc/free. template - static StringMapEntry *Create(StringRef Key, InitType InitVal) { + static StringMapEntry *Create(StringRef Key, InitType &&InitVal) { MallocAllocator A; - return Create(Key, A, std::move(InitVal)); + return Create(Key, A, std::forward(InitVal)); } static StringMapEntry *Create(StringRef Key) { return Create(Key, ValueTy()); } - /// GetStringMapEntryFromValue - Given a value that is known to be embedded - /// into a StringMapEntry, return the StringMapEntry itself. - static StringMapEntry &GetStringMapEntryFromValue(ValueTy &V) { - StringMapEntry *EPtr = 0; - char *Ptr = reinterpret_cast(&V) - - (reinterpret_cast(&EPtr->second) - - reinterpret_cast(EPtr)); - return *reinterpret_cast(Ptr); - } - static const StringMapEntry &GetStringMapEntryFromValue(const ValueTy &V) { - return GetStringMapEntryFromValue(const_cast(V)); - } - /// GetStringMapEntryFromKeyData - Given key data that is known to be embedded /// into a StringMapEntry, return the StringMapEntry itself. static StringMapEntry &GetStringMapEntryFromKeyData(const char *KeyData) { @@ -296,7 +283,7 @@ public: } ValueTy &operator[](StringRef Key) { - return GetOrCreateValue(Key).getValue(); + return insert(std::make_pair(Key, ValueTy())).first->second; } /// count - Return 1 if the element is in the map, 0 otherwise. @@ -363,18 +350,6 @@ public: NumTombstones = 0; } - /// GetOrCreateValue - Look up the specified key in the table. If a value - /// exists, return it. Otherwise, default construct a value, insert it, and - /// return. - template - MapEntryTy &GetOrCreateValue(StringRef Key, InitTy Val) { - return *insert(std::make_pair(Key, std::move(Val))).first; - } - - MapEntryTy &GetOrCreateValue(StringRef Key) { - return GetOrCreateValue(Key, ValueTy()); - } - /// remove - Remove the specified key/value pair from the map, but do not /// erase it. This aborts if the key is not in the map. void remove(MapEntryTy *KeyValue) { diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index 1f413e8..6111c42 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -51,12 +51,6 @@ namespace llvm { /// The length of the string. size_t Length; - // Workaround PR5482: nearly all gcc 4.x miscompile StringRef and std::min() - // Changing the arg of min to be an integer, instead of a reference to an - // integer works around this bug. - static size_t min(size_t a, size_t b) { return a < b ? a : b; } - static size_t max(size_t a, size_t b) { return a > b ? a : b; } - // Workaround memcmp issue with null pointers (undefined behavior) // by providing a specialized version static int compareMemory(const char *Lhs, const char *Rhs, size_t Length) { @@ -97,6 +91,13 @@ namespace llvm { iterator end() const { return Data + Length; } + const unsigned char *bytes_begin() const { + return reinterpret_cast(begin()); + } + const unsigned char *bytes_end() const { + return reinterpret_cast(end()); + } + /// @} /// @name String Operations /// @{ @@ -124,7 +125,7 @@ namespace llvm { } // copy - Allocate copy in Allocator and return StringRef to it. - template StringRef copy(Allocator &A) { + template StringRef copy(Allocator &A) const { char *S = A.template Allocate(Length); std::copy(begin(), end(), S); return StringRef(S, Length); @@ -146,7 +147,7 @@ namespace llvm { /// is lexicographically less than, equal to, or greater than the \p RHS. int compare(StringRef RHS) const { // Check the prefix for a mismatch. - if (int Res = compareMemory(Data, RHS.Data, min(Length, RHS.Length))) + if (int Res = compareMemory(Data, RHS.Data, std::min(Length, RHS.Length))) return Res < 0 ? -1 : 1; // Otherwise the prefixes match, so we only need to check the lengths. @@ -237,7 +238,7 @@ namespace llvm { /// \returns The index of the first occurrence of \p C, or npos if not /// found. size_t find(char C, size_t From = 0) const { - for (size_t i = min(From, Length), e = Length; i != e; ++i) + for (size_t i = std::min(From, Length), e = Length; i != e; ++i) if (Data[i] == C) return i; return npos; @@ -254,7 +255,7 @@ namespace llvm { /// \returns The index of the last occurrence of \p C, or npos if not /// found. size_t rfind(char C, size_t From = npos) const { - From = min(From, Length); + From = std::min(From, Length); size_t i = From; while (i != 0) { --i; @@ -353,8 +354,11 @@ namespace llvm { typename std::enable_if::is_signed, bool>::type getAsInteger(unsigned Radix, T &Result) const { unsigned long long ULLVal; + // The additional cast to unsigned long long is required to avoid the + // Visual C++ warning C4805: '!=' : unsafe mix of type 'bool' and type + // 'unsigned __int64' when instantiating getAsInteger with T = bool. if (getAsUnsignedInteger(*this, Radix, ULLVal) || - static_cast(ULLVal) != ULLVal) + static_cast(static_cast(ULLVal)) != ULLVal) return true; Result = ULLVal; return false; @@ -396,8 +400,8 @@ namespace llvm { /// exceeds the number of characters remaining in the string, the string /// suffix (starting with \p Start) will be returned. StringRef substr(size_t Start, size_t N = npos) const { - Start = min(Start, Length); - return StringRef(Data + Start, min(N, Length - Start)); + Start = std::min(Start, Length); + return StringRef(Data + Start, std::min(N, Length - Start)); } /// Return a StringRef equal to 'this' but with the first \p N elements @@ -425,8 +429,8 @@ namespace llvm { /// number of characters remaining in the string, the string suffix /// (starting with \p Start) will be returned. StringRef slice(size_t Start, size_t End) const { - Start = min(Start, Length); - End = min(max(Start, End), Length); + Start = std::min(Start, Length); + End = std::min(std::max(Start, End), Length); return StringRef(Data + Start, End - Start); } diff --git a/include/llvm/ADT/StringSet.h b/include/llvm/ADT/StringSet.h index 7bea577..3e0cc20 100644 --- a/include/llvm/ADT/StringSet.h +++ b/include/llvm/ADT/StringSet.h @@ -24,20 +24,9 @@ namespace llvm { typedef llvm::StringMap base; public: - /// insert - Insert the specified key into the set. If the key already - /// exists in the set, return false and ignore the request, otherwise insert - /// it and return true. - bool insert(StringRef Key) { - // Get or create the map entry for the key; if it doesn't exist the value - // type will be default constructed which we use to detect insert. - // - // We use '+' as the sentinel value in the map. + std::pair insert(StringRef Key) { assert(!Key.empty()); - StringMapEntry &Entry = this->GetOrCreateValue(Key); - if (Entry.getValue() == '+') - return false; - Entry.setValue('+'); - return true; + return base::insert(std::make_pair(Key, '\0')); } }; } diff --git a/include/llvm/ADT/TinyPtrVector.h b/include/llvm/ADT/TinyPtrVector.h index 5669b2a..15137f5 100644 --- a/include/llvm/ADT/TinyPtrVector.h +++ b/include/llvm/ADT/TinyPtrVector.h @@ -96,10 +96,17 @@ public: return *this; } + /// Constructor from a single element. + explicit TinyPtrVector(EltTy Elt) : Val(Elt) {} + + /// Constructor from an ArrayRef. + explicit TinyPtrVector(ArrayRef Elts) + : Val(new VecTy(Elts.begin(), Elts.end())) {} + // implicit conversion operator to ArrayRef. operator ArrayRef() const { if (Val.isNull()) - return ArrayRef(); + return None; if (Val.template is()) return *Val.getAddrOfPtr1(); return *Val.template get(); diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index b96f114..8a68599 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -48,8 +48,6 @@ public: arm, // ARM (little endian): arm, armv.*, xscale armeb, // ARM (big endian): armeb - arm64, // ARM64 (little endian): arm64 - arm64_be, // ARM64 (big endian): arm64_be aarch64, // AArch64 (little endian): aarch64 aarch64_be, // AArch64 (big endian): aarch64_be hexagon, // Hexagon: hexagon @@ -62,6 +60,7 @@ public: ppc64, // PPC64: powerpc64, ppu ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX + amdgcn, // AMDGCN: AMD GCN GPUs sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 systemz, // SystemZ: s390x @@ -74,7 +73,11 @@ public: nvptx, // NVPTX: 32-bit nvptx64, // NVPTX: 64-bit le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) - amdil, // amdil: amd IL + le64, // le64: generic little-endian 64-bit CPU (PNaCl / Emscripten) + amdil, // AMDIL + amdil64, // AMDIL with 64-bit pointers + hsail, // AMD HSAIL + hsail64, // AMD HSAIL with 64-bit pointers spir, // SPIR: standard portable IR for OpenCL 32-bit version spir64, // SPIR: standard portable IR for OpenCL 64-bit version kalimba // Kalimba: generic kalimba @@ -92,7 +95,11 @@ public: ARMSubArch_v6t2, ARMSubArch_v5, ARMSubArch_v5te, - ARMSubArch_v4t + ARMSubArch_v4t, + + KalimbaSubArch_v3, + KalimbaSubArch_v4, + KalimbaSubArch_v5 }; enum VendorType { UnknownVendor, @@ -112,8 +119,6 @@ public: enum OSType { UnknownOS, - AuroraUX, - Cygwin, Darwin, DragonFly, FreeBSD, @@ -122,7 +127,6 @@ public: Linux, Lv2, // PS3 MacOSX, - MinGW32, // i*86-pc-mingw32, *-w64-mingw32 NetBSD, OpenBSD, Solaris, @@ -135,7 +139,8 @@ public: Bitrig, AIX, CUDA, // NVIDIA CUDA - NVCL // NVIDIA OpenCL + NVCL, // NVIDIA OpenCL + AMDHSA // AMD HSA Runtime }; enum EnvironmentType { UnknownEnvironment, @@ -361,10 +366,28 @@ public: return isMacOSX() || isiOS(); } + bool isOSNetBSD() const { + return getOS() == Triple::NetBSD; + } + + bool isOSOpenBSD() const { + return getOS() == Triple::OpenBSD; + } + bool isOSFreeBSD() const { return getOS() == Triple::FreeBSD; } + bool isOSDragonFly() const { return getOS() == Triple::DragonFly; } + + bool isOSSolaris() const { + return getOS() == Triple::Solaris; + } + + bool isOSBitrig() const { + return getOS() == Triple::Bitrig; + } + bool isWindowsMSVCEnvironment() const { return getOS() == Triple::Win32 && (getEnvironment() == Triple::UnknownEnvironment || @@ -380,13 +403,11 @@ public: } bool isWindowsCygwinEnvironment() const { - return getOS() == Triple::Cygwin || - (getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus); + return getOS() == Triple::Win32 && getEnvironment() == Triple::Cygnus; } bool isWindowsGNUEnvironment() const { - return getOS() == Triple::MinGW32 || - (getOS() == Triple::Win32 && getEnvironment() == Triple::GNU); + return getOS() == Triple::Win32 && getEnvironment() == Triple::GNU; } /// \brief Tests for either Cygwin or MinGW OS @@ -396,7 +417,8 @@ public: /// \brief Is this a "Windows" OS targeting a "MSVCRT.dll" environment. bool isOSMSVCRT() const { - return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment(); + return isWindowsMSVCEnvironment() || isWindowsGNUEnvironment() || + isWindowsItaniumEnvironment(); } /// \brief Tests whether the OS is Windows. @@ -475,10 +497,6 @@ public: /// environment components with a single string. void setOSAndEnvironmentName(StringRef Str); - /// getArchNameForAssembler - Get an architecture name that is understood by - /// the target assembler. - const char *getArchNameForAssembler(); - /// @} /// @name Helpers to build variants of a particular triple. /// @{ diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 4be3ee6..05d2fea 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -80,7 +80,7 @@ namespace llvm { /// StringRef) codegen as desired. class Twine { /// NodeKind - Represent the type of an argument. - enum NodeKind { + enum NodeKind : unsigned char { /// An empty string; the result of concatenating anything with it is also /// empty. NullKind, @@ -153,12 +153,10 @@ namespace llvm { /// RHS - The suffix in the concatenation, which may be uninitialized for /// Null or Empty kinds. Child RHS; - // enums stored as unsigned chars to save on space while some compilers - // don't support specifying the backing type for an enum /// LHSKind - The NodeKind of the left hand side, \see getLHSKind(). - unsigned char LHSKind; - /// RHSKind - The NodeKind of the left hand side, \see getLHSKind(). - unsigned char RHSKind; + NodeKind LHSKind; + /// RHSKind - The NodeKind of the right hand side, \see getRHSKind(). + NodeKind RHSKind; private: /// Construct a nullary twine; the kind must be NullKind or EmptyKind. @@ -238,10 +236,10 @@ namespace llvm { } /// getLHSKind - Get the NodeKind of the left-hand side. - NodeKind getLHSKind() const { return (NodeKind) LHSKind; } + NodeKind getLHSKind() const { return LHSKind; } /// getRHSKind - Get the NodeKind of the right-hand side. - NodeKind getRHSKind() const { return (NodeKind) RHSKind; } + NodeKind getRHSKind() const { return RHSKind; } /// printOneChild - Print one child from a twine. void printOneChild(raw_ostream &OS, Child Ptr, NodeKind Kind) const; diff --git a/include/llvm/ADT/VariadicFunction.h b/include/llvm/ADT/VariadicFunction.h index 0497aa7..403130c 100644 --- a/include/llvm/ADT/VariadicFunction.h +++ b/include/llvm/ADT/VariadicFunction.h @@ -105,7 +105,7 @@ template )> struct VariadicFunction { ResultT operator()() const { - return Func(ArrayRef()); + return Func(None); } #define LLVM_DEFINE_OVERLOAD(N) \ @@ -152,7 +152,7 @@ template )> struct VariadicFunction1 { ResultT operator()(Param0T P0) const { - return Func(P0, ArrayRef()); + return Func(P0, None); } #define LLVM_DEFINE_OVERLOAD(N) \ @@ -199,7 +199,7 @@ template )> struct VariadicFunction2 { ResultT operator()(Param0T P0, Param1T P1) const { - return Func(P0, P1, ArrayRef()); + return Func(P0, P1, None); } #define LLVM_DEFINE_OVERLOAD(N) \ @@ -248,7 +248,7 @@ template )> struct VariadicFunction3 { ResultT operator()(Param0T P0, Param1T P1, Param2T P2) const { - return Func(P0, P1, P2, ArrayRef()); + return Func(P0, P1, P2, None); } #define LLVM_DEFINE_OVERLOAD(N) \ diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index bc14845..8c19a6f 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -579,60 +579,6 @@ public: void splice(iterator where, iplist &L2, iterator first, iterator last) { if (first != last) transfer(where, L2, first, last); } - - - - //===----------------------------------------------------------------------=== - // High-Level Functionality that shouldn't really be here, but is part of list - // - - // These two functions are actually called remove/remove_if in list<>, but - // they actually do the job of erase, rename them accordingly. - // - void erase(const NodeTy &val) { - for (iterator I = begin(), E = end(); I != E; ) { - iterator next = I; ++next; - if (*I == val) erase(I); - I = next; - } - } - template void erase_if(Pr1 pred) { - for (iterator I = begin(), E = end(); I != E; ) { - iterator next = I; ++next; - if (pred(*I)) erase(I); - I = next; - } - } - - template void unique(Pr2 pred) { - if (empty()) return; - for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { - if (pred(*I)) - erase(Next); - else - I = Next; - Next = I; - } - } - void unique() { unique(op_equal); } - - template void merge(iplist &right, Pr3 pred) { - iterator first1 = begin(), last1 = end(); - iterator first2 = right.begin(), last2 = right.end(); - while (first1 != last1 && first2 != last2) - if (pred(*first2, *first1)) { - iterator next = first2; - transfer(first1, right, first2, ++next); - first2 = next; - } else { - ++first1; - } - if (first2 != last2) transfer(last1, right, first2, last2); - } - void merge(iplist &right) { return merge(right, op_less); } - - template void sort(Pr3 pred); - void sort() { sort(op_less); } }; diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index 85aa7a4..26d0b55 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ADT_ILISTNODE_H -#define LLVM_ADT_ILISTNODE_H +#ifndef LLVM_ADT_ILIST_NODE_H +#define LLVM_ADT_ILIST_NODE_H namespace llvm { diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index 56041db..e2c9e5e 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -10,8 +10,8 @@ #ifndef LLVM_ADT_ITERATOR_H #define LLVM_ADT_ITERATOR_H -#include #include +#include namespace llvm { diff --git a/include/llvm/ADT/iterator_range.h b/include/llvm/ADT/iterator_range.h index dd17d6c..523a86f 100644 --- a/include/llvm/ADT/iterator_range.h +++ b/include/llvm/ADT/iterator_range.h @@ -32,7 +32,6 @@ class iterator_range { IteratorT begin_iterator, end_iterator; public: - iterator_range() {} iterator_range(IteratorT begin_iterator, IteratorT end_iterator) : begin_iterator(std::move(begin_iterator)), end_iterator(std::move(end_iterator)) {} @@ -48,6 +47,10 @@ public: template iterator_range make_range(T x, T y) { return iterator_range(std::move(x), std::move(y)); } + +template iterator_range make_range(std::pair p) { + return iterator_range(std::move(p.first), std::move(p.second)); +} } #endif diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 6897664..763f372 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -39,6 +39,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/IR/CallSite.h" +#include "llvm/IR/Metadata.h" namespace llvm { @@ -112,13 +113,14 @@ public: /// there are restrictions on stepping out of one object and into another. /// See http://llvm.org/docs/LangRef.html#pointeraliasing uint64_t Size; - /// TBAATag - The metadata node which describes the TBAA type of - /// the location, or null if there is no known unique tag. - const MDNode *TBAATag; + /// AATags - The metadata nodes which describes the aliasing of the + /// location (each member is null if that kind of information is + /// unavailable).. + AAMDNodes AATags; explicit Location(const Value *P = nullptr, uint64_t S = UnknownSize, - const MDNode *N = nullptr) - : Ptr(P), Size(S), TBAATag(N) {} + const AAMDNodes &N = AAMDNodes()) + : Ptr(P), Size(S), AATags(N) {} Location getWithNewPtr(const Value *NewPtr) const { Location Copy(*this); @@ -132,9 +134,9 @@ public: return Copy; } - Location getWithoutTBAATag() const { + Location getWithoutAATags() const { Location Copy(*this); - Copy.TBAATag = nullptr; + Copy.AATags = AAMDNodes(); return Copy; } }; @@ -500,7 +502,7 @@ public: /// /// canBasicBlockModify - Return true if it is possible for execution of the - /// specified basic block to modify the value pointed to by Ptr. + /// specified basic block to modify the location Loc. bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); /// canBasicBlockModify - A convenience wrapper. @@ -508,17 +510,20 @@ public: return canBasicBlockModify(BB, Location(P, Size)); } - /// canInstructionRangeModify - Return true if it is possible for the - /// execution of the specified instructions to modify the value pointed to by - /// Ptr. The instructions to consider are all of the instructions in the - /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Location &Loc); + /// canInstructionRangeModRef - Return true if it is possible for the + /// execution of the specified instructions to mod\ref (according to the + /// mode) the location Loc. The instructions to consider are all + /// of the instructions in the range of [I1,I2] INCLUSIVE. + /// I1 and I2 must be in the same basic block. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Location &Loc, + const ModRefResult Mode); - /// canInstructionRangeModify - A convenience wrapper. - bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, - const Value *Ptr, uint64_t Size) { - return canInstructionRangeModify(I1, I2, Location(Ptr, Size)); + /// canInstructionRangeModRef - A convenience wrapper. + bool canInstructionRangeModRef(const Instruction &I1, + const Instruction &I2, const Value *Ptr, + uint64_t Size, const ModRefResult Mode) { + return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode); } //===--------------------------------------------------------------------===// @@ -566,25 +571,23 @@ public: template<> struct DenseMapInfo { static inline AliasAnalysis::Location getEmptyKey() { - return - AliasAnalysis::Location(DenseMapInfo::getEmptyKey(), - 0, nullptr); + return AliasAnalysis::Location(DenseMapInfo::getEmptyKey(), + 0); } static inline AliasAnalysis::Location getTombstoneKey() { - return - AliasAnalysis::Location(DenseMapInfo::getTombstoneKey(), - 0, nullptr); + return AliasAnalysis::Location( + DenseMapInfo::getTombstoneKey(), 0); } static unsigned getHashValue(const AliasAnalysis::Location &Val) { return DenseMapInfo::getHashValue(Val.Ptr) ^ DenseMapInfo::getHashValue(Val.Size) ^ - DenseMapInfo::getHashValue(Val.TBAATag); + DenseMapInfo::getHashValue(Val.AATags); } static bool isEqual(const AliasAnalysis::Location &LHS, const AliasAnalysis::Location &RHS) { return LHS.Ptr == RHS.Ptr && LHS.Size == RHS.Size && - LHS.TBAATag == RHS.TBAATag; + LHS.AATags == RHS.AATags; } }; diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h index e32b6d6..036d58d 100644 --- a/include/llvm/Analysis/AliasSetTracker.h +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -20,6 +20,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" #include @@ -40,11 +41,11 @@ class AliasSet : public ilist_node { PointerRec **PrevInList, *NextInList; AliasSet *AS; uint64_t Size; - const MDNode *TBAAInfo; + AAMDNodes AAInfo; public: PointerRec(Value *V) : Val(V), PrevInList(nullptr), NextInList(nullptr), AS(nullptr), Size(0), - TBAAInfo(DenseMapInfo::getEmptyKey()) {} + AAInfo(DenseMapInfo::getEmptyKey()) {} Value *getValue() const { return Val; } @@ -56,27 +57,27 @@ class AliasSet : public ilist_node { return &NextInList; } - void updateSizeAndTBAAInfo(uint64_t NewSize, const MDNode *NewTBAAInfo) { + void updateSizeAndAAInfo(uint64_t NewSize, const AAMDNodes &NewAAInfo) { if (NewSize > Size) Size = NewSize; - if (TBAAInfo == DenseMapInfo::getEmptyKey()) - // We don't have a TBAAInfo yet. Set it to NewTBAAInfo. - TBAAInfo = NewTBAAInfo; - else if (TBAAInfo != NewTBAAInfo) - // NewTBAAInfo conflicts with TBAAInfo. - TBAAInfo = DenseMapInfo::getTombstoneKey(); + if (AAInfo == DenseMapInfo::getEmptyKey()) + // We don't have a AAInfo yet. Set it to NewAAInfo. + AAInfo = NewAAInfo; + else if (AAInfo != NewAAInfo) + // NewAAInfo conflicts with AAInfo. + AAInfo = DenseMapInfo::getTombstoneKey(); } uint64_t getSize() const { return Size; } - /// getTBAAInfo - Return the TBAAInfo, or null if there is no + /// getAAInfo - Return the AAInfo, or null if there is no /// information or conflicting information. - const MDNode *getTBAAInfo() const { - // If we have missing or conflicting TBAAInfo, return null. - if (TBAAInfo == DenseMapInfo::getEmptyKey() || - TBAAInfo == DenseMapInfo::getTombstoneKey()) - return nullptr; - return TBAAInfo; + AAMDNodes getAAInfo() const { + // If we have missing or conflicting AAInfo, return null. + if (AAInfo == DenseMapInfo::getEmptyKey() || + AAInfo == DenseMapInfo::getTombstoneKey()) + return AAMDNodes(); + return AAInfo; } AliasSet *getAliasSet(AliasSetTracker &AST) { @@ -204,7 +205,7 @@ public: Value *getPointer() const { return CurNode->getValue(); } uint64_t getSize() const { return CurNode->getSize(); } - const MDNode *getTBAAInfo() const { return CurNode->getTBAAInfo(); } + AAMDNodes getAAInfo() const { return CurNode->getAAInfo(); } iterator& operator++() { // Preincrement assert(CurNode && "Advancing past AliasSet.end()!"); @@ -250,7 +251,7 @@ private: void removeFromTracker(AliasSetTracker &AST); void addPointer(AliasSetTracker &AST, PointerRec &Entry, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, bool KnownMustAlias = false); void addUnknownInst(Instruction *I, AliasAnalysis &AA); void removeUnknownInst(AliasSetTracker &AST, Instruction *I) { @@ -270,7 +271,7 @@ public: /// aliasesPointer - Return true if the specified pointer "may" (or must) /// alias one of the members in the set. /// - bool aliasesPointer(const Value *Ptr, uint64_t Size, const MDNode *TBAAInfo, + bool aliasesPointer(const Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo, AliasAnalysis &AA) const; bool aliasesUnknownInst(Instruction *Inst, AliasAnalysis &AA) const; }; @@ -325,7 +326,7 @@ public: /// These methods return true if inserting the instruction resulted in the /// addition of a new alias set (i.e., the pointer did not alias anything). /// - bool add(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); // Add a location + bool add(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); // Add a loc. bool add(LoadInst *LI); bool add(StoreInst *SI); bool add(VAArgInst *VAAI); @@ -338,7 +339,7 @@ public: /// be aliased by the specified instruction. These methods return true if any /// alias sets were eliminated. // Remove a location - bool remove(Value *Ptr, uint64_t Size, const MDNode *TBAAInfo); + bool remove(Value *Ptr, uint64_t Size, const AAMDNodes &AAInfo); bool remove(LoadInst *LI); bool remove(StoreInst *SI); bool remove(VAArgInst *VAAI); @@ -357,20 +358,24 @@ public: /// true if a new alias set is created to contain the pointer (because the /// pointer didn't alias anything). AliasSet &getAliasSetForPointer(Value *P, uint64_t Size, - const MDNode *TBAAInfo, + const AAMDNodes &AAInfo, bool *New = nullptr); /// getAliasSetForPointerIfExists - Return the alias set containing the /// location specified if one exists, otherwise return null. AliasSet *getAliasSetForPointerIfExists(Value *P, uint64_t Size, - const MDNode *TBAAInfo) { - return findAliasSetForPointer(P, Size, TBAAInfo); + const AAMDNodes &AAInfo) { + return findAliasSetForPointer(P, Size, AAInfo); } /// containsPointer - Return true if the specified location is represented by /// this alias set, false otherwise. This does not modify the AST object or /// alias sets. - bool containsPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo) const; + bool containsPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo) const; + + /// Return true if the specified instruction "may" (or must) alias one of the + /// members in any of the sets. + bool containsUnknown(Instruction *I) const; /// getAliasAnalysis - Return the underlying alias analysis object used by /// this tracker. @@ -417,16 +422,16 @@ private: return *Entry; } - AliasSet &addPointer(Value *P, uint64_t Size, const MDNode *TBAAInfo, + AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo, AliasSet::AccessType E, bool &NewSet) { NewSet = false; - AliasSet &AS = getAliasSetForPointer(P, Size, TBAAInfo, &NewSet); + AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet); AS.AccessTy |= E; return AS; } AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, - const MDNode *TBAAInfo); + const AAMDNodes &AAInfo); AliasSet *findAliasSetForUnknownInst(Instruction *Inst); }; diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h new file mode 100644 index 0000000..b129e67 --- /dev/null +++ b/include/llvm/Analysis/AssumptionCache.h @@ -0,0 +1,142 @@ +//===- llvm/Analysis/AssumptionCache.h - Track @llvm.assume ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that keeps track of @llvm.assume intrinsics in +// the functions of a module (allowing assumptions within any function to be +// found cheaply by other parts of the optimizer). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ASSUMPTIONCACHE_H +#define LLVM_ANALYSIS_ASSUMPTIONCACHE_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/ValueHandle.h" +#include "llvm/Pass.h" +#include + +namespace llvm { + +/// \brief A cache of @llvm.assume calls within a function. +/// +/// This cache provides fast lookup of assumptions within a function by caching +/// them and amortizing the cost of scanning for them across all queries. The +/// cache is also conservatively self-updating so that it will never return +/// incorrect results about a function even as the function is being mutated. +/// However, flushing the cache and rebuilding it (or explicitly updating it) +/// may allow it to discover new assumptions. +class AssumptionCache { + /// \brief The function for which this cache is handling assumptions. + /// + /// We track this to lazily populate our assumptions. + Function &F; + + /// \brief Vector of weak value handles to calls of the @llvm.assume + /// intrinsic. + SmallVector AssumeHandles; + + /// \brief Flag tracking whether we have scanned the function yet. + /// + /// We want to be as lazy about this as possible, and so we scan the function + /// at the last moment. + bool Scanned; + + /// \brief Scan the function for assumptions and add them to the cache. + void scanFunction(); + +public: + /// \brief Construct an AssumptionCache from a function by scanning all of + /// its instructions. + AssumptionCache(Function &F) : F(F), Scanned(false) {} + + /// \brief Add an @llvm.assume intrinsic to this function's cache. + /// + /// The call passed in must be an instruction within this fuction and must + /// not already be in the cache. + void registerAssumption(CallInst *CI); + + /// \brief Clear the cache of @llvm.assume intrinsics for a function. + /// + /// It will be re-scanned the next time it is requested. + void clear() { + AssumeHandles.clear(); + Scanned = false; + } + + /// \brief Access the list of assumption handles currently tracked for this + /// fuction. + /// + /// Note that these produce weak handles that may be null. The caller must + /// handle that case. + /// FIXME: We should replace this with pointee_iterator> + /// when we can write that to filter out the null values. Then caller code + /// will become simpler. + MutableArrayRef assumptions() { + if (!Scanned) + scanFunction(); + return AssumeHandles; + } +}; + +/// \brief An immutable pass that tracks lazily created \c AssumptionCache +/// objects. +/// +/// This is essentially a workaround for the legacy pass manager's weaknesses +/// which associates each assumption cache with Function and clears it if the +/// function is deleted. The nature of the AssumptionCache is that it is not +/// invalidated by any changes to the function body and so this is sufficient +/// to be conservatively correct. +class AssumptionCacheTracker : public ImmutablePass { + /// A callback value handle applied to function objects, which we use to + /// delete our cache of intrinsics for a function when it is deleted. + class FunctionCallbackVH : public CallbackVH { + AssumptionCacheTracker *ACT; + void deleted() override; + + public: + typedef DenseMapInfo DMI; + + FunctionCallbackVH(Value *V, AssumptionCacheTracker *ACT = nullptr) + : CallbackVH(V), ACT(ACT) {} + }; + + friend FunctionCallbackVH; + + typedef DenseMap, + FunctionCallbackVH::DMI> FunctionCallsMap; + FunctionCallsMap AssumptionCaches; + +public: + /// \brief Get the cached assumptions for a function. + /// + /// If no assumptions are cached, this will scan the function. Otherwise, the + /// existing cache will be returned. + AssumptionCache &getAssumptionCache(Function &F); + + AssumptionCacheTracker(); + ~AssumptionCacheTracker(); + + void releaseMemory() override { AssumptionCaches.shrink_and_clear(); } + + void verifyAnalysis() const override; + bool doFinalization(Module &) override { + verifyAnalysis(); + return false; + } + + static char ID; // Pass identification, replacement for typeid +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index bb256c7..57b5154 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -260,7 +260,7 @@ public: /// loop. /// /// This function should only be called when distributing mass. As long as - /// there are no irreducilbe edges to Node, then it will have complexity + /// there are no irreducible edges to Node, then it will have complexity /// O(1) in this context. /// /// In general, the complexity is O(L), where L is the number of loop diff --git a/include/llvm/Analysis/BranchProbabilityInfo.h b/include/llvm/Analysis/BranchProbabilityInfo.h index 4414c84..89eef68 100644 --- a/include/llvm/Analysis/BranchProbabilityInfo.h +++ b/include/llvm/Analysis/BranchProbabilityInfo.h @@ -111,6 +111,10 @@ public: void setEdgeWeight(const BasicBlock *Src, unsigned IndexInSuccessors, uint32_t Weight); + static uint32_t getBranchWeightStackProtector(bool IsLikely) { + return IsLikely ? (1u << 20) - 1 : 1; + } + private: // Since we allow duplicate edges from one basic block to another, we use // a pair (PredBlock and an index in the successors) to specify an edge. diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index e6d2ed1..0357648 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -72,13 +72,13 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { OutStr.erase(OutStr.begin()+i, OutStr.begin()+Idx); --i; } else if (ColNum == MaxColumns) { // Wrap lines. - if (LastSpace) { - OutStr.insert(LastSpace, "\\l..."); - ColNum = i - LastSpace; - LastSpace = 0; - i += 3; // The loop will advance 'i' again. - } - // Else keep trying to find a space. + // Wrap very long names even though we can't find a space. + if (!LastSpace) + LastSpace = i; + OutStr.insert(LastSpace, "\\l..."); + ColNum = i - LastSpace; + LastSpace = 0; + i += 3; // The loop will advance 'i' again. } else ++ColNum; diff --git a/include/llvm/Analysis/CGSCCPassManager.h b/include/llvm/Analysis/CGSCCPassManager.h index 09101ae..0d4fe93 100644 --- a/include/llvm/Analysis/CGSCCPassManager.h +++ b/include/llvm/Analysis/CGSCCPassManager.h @@ -18,138 +18,28 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H -#define LLVM_ANALYSIS_CGSCC_PASS_MANAGER_H +#ifndef LLVM_ANALYSIS_CGSCCPASSMANAGER_H +#define LLVM_ANALYSIS_CGSCCPASSMANAGER_H -#include "llvm/IR/PassManager.h" #include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/PassManager.h" namespace llvm { -class CGSCCAnalysisManager; - -class CGSCCPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCPassManager() {} - CGSCCPassManager(CGSCCPassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - CGSCCPassManager &operator=(CGSCCPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - /// \brief Run all of the CGSCC passes in this pass manager over a SCC. - PreservedAnalyses run(LazyCallGraph::SCC *C, - CGSCCAnalysisManager *AM = nullptr); - - template void addPass(CGSCCPassT Pass) { - Passes.emplace_back(new CGSCCPassModel(std::move(Pass))); - } - - static StringRef name() { return "CGSCCPassManager"; } - -private: - // Pull in the concept type and model template specialized for SCCs. - typedef detail::PassConcept - CGSCCPassConcept; - template - struct CGSCCPassModel - : detail::PassModel { - CGSCCPassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; - - CGSCCPassManager(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - CGSCCPassManager &operator=(const CGSCCPassManager &) LLVM_DELETED_FUNCTION; - - std::vector> Passes; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class CGSCCAnalysisManager : public detail::AnalysisManagerBase< - CGSCCAnalysisManager, LazyCallGraph::SCC *> { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // Most public APIs are inherited from the CRTP base class. - - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - CGSCCAnalysisManager() {} - CGSCCAnalysisManager(CGSCCAnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - CGSCCAnalysisResults(std::move(Arg.CGSCCAnalysisResults)) {} - CGSCCAnalysisManager &operator=(CGSCCAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - CGSCCAnalysisResults = std::move(RHS.CGSCCAnalysisResults); - return *this; - } - - /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; - - /// \brief Clear the function analysis result cache. - /// - /// This routine allows cleaning up when the set of functions itself has - /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); - -private: - CGSCCAnalysisManager(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - CGSCCAnalysisManager & - operator=(const CGSCCAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, - LazyCallGraph::SCC *C) const; - - /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, LazyCallGraph::SCC *C); - - /// \brief Invalidate the results for a function.. - void invalidateImpl(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); +/// \brief The CGSCC pass manager. +/// +/// See the documentation for the PassManager template for details. It runs +/// a sequency of SCC passes over each SCC that the manager is run over. This +/// typedef serves as a convenient way to refer to this construct. +typedef PassManager CGSCCPassManager; - /// \brief List of function analysis pass IDs and associated concept pointers. - /// - /// Requires iterators to be valid across appending new entries and arbitrary - /// erases. Provides both the pass ID and concept pointer such that it is - /// half of a bijection and provides storage for the actual result concept. - typedef std::list< - std::pair>>> CGSCCAnalysisResultListT; - - /// \brief Map type from function pointer to our custom list type. - typedef DenseMap - CGSCCAnalysisResultListMapT; - - /// \brief Map from function to a list of function analysis results. - /// - /// Provides linear time removal of all analysis results for a function and - /// the ultimate storage for a particular cached analysis result. - CGSCCAnalysisResultListMapT CGSCCAnalysisResultLists; - - /// \brief Map type from a pair of analysis ID and function pointer to an - /// iterator into a particular result list. - typedef DenseMap, - CGSCCAnalysisResultListT::iterator> CGSCCAnalysisResultMapT; - - /// \brief Map from an analysis ID and function to a particular cached - /// analysis result. - CGSCCAnalysisResultMapT CGSCCAnalysisResults; -}; +/// \brief The CGSCC analysis manager. +/// +/// See the documentation for the AnalysisManager template for detail +/// documentation. This typedef serves as a convenient way to refer to this +/// construct in the adaptors and proxies used to integrate this into the larger +/// pass manager infrastructure. +typedef AnalysisManager CGSCCAnalysisManager; /// \brief A module analysis which acts as a proxy for a CGSCC analysis /// manager. @@ -187,7 +77,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c CGSCCAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: CGSCCAnalysisManager *CGAM; @@ -195,12 +85,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerModuleProxy"; } + explicit CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - CGSCCAnalysisManagerModuleProxy( - const CGSCCAnalysisManagerModuleProxy &Arg) + CGSCCAnalysisManagerModuleProxy(const CGSCCAnalysisManagerModuleProxy &Arg) : CGAM(Arg.CGAM) {} CGSCCAnalysisManagerModuleProxy(CGSCCAnalysisManagerModuleProxy &&Arg) : CGAM(std::move(Arg.CGAM)) {} @@ -219,7 +110,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the CGSCC analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -257,7 +148,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(LazyCallGraph::SCC *) { return false; } + bool invalidate(LazyCallGraph::SCC &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -265,12 +156,13 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerCGSCCProxy"; } + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - ModuleAnalysisManagerCGSCCProxy( - const ModuleAnalysisManagerCGSCCProxy &Arg) + ModuleAnalysisManagerCGSCCProxy(const ModuleAnalysisManagerCGSCCProxy &Arg) : MAM(Arg.MAM) {} ModuleAnalysisManagerCGSCCProxy(ModuleAnalysisManagerCGSCCProxy &&Arg) : MAM(std::move(Arg.MAM)) {} @@ -283,7 +175,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(LazyCallGraph::SCC *) { return Result(*MAM); } + Result run(LazyCallGraph::SCC &) { return Result(*MAM); } private: static char PassID; @@ -323,7 +215,7 @@ public: } /// \brief Runs the CGSCC pass across every SCC in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { assert(AM && "We need analyses to compute the call graph!"); // Setup the CGSCC analysis manager from its proxy. @@ -335,15 +227,17 @@ public: PreservedAnalyses PA = PreservedAnalyses::all(); for (LazyCallGraph::SCC &C : CG.postorder_sccs()) { - PreservedAnalyses PassPA = Pass.run(&C, &CGAM); + PreservedAnalyses PassPA = Pass.run(C, &CGAM); // We know that the CGSCC pass couldn't have invalidated any other // SCC's analyses (that's the contract of a CGSCC pass), so - // directly handle the CGSCC analysis manager's invalidation here. + // directly handle the CGSCC analysis manager's invalidation here. We + // also update the preserved set of analyses to reflect that invalidated + // analyses are now safe to preserve. // FIXME: This isn't quite correct. We need to handle the case where the // pass updated the CG, particularly some child of the current SCC, and // invalidate its analyses. - CGAM.invalidate(&C, PassPA); + PassPA = CGAM.invalidate(C, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -409,7 +303,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(LazyCallGraph::SCC *C, const PreservedAnalyses &PA); + bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -417,6 +311,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerCGSCCProxy"; } + explicit FunctionAnalysisManagerCGSCCProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -441,7 +337,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(LazyCallGraph::SCC *C); + Result run(LazyCallGraph::SCC &C); private: static char PassID; @@ -479,7 +375,7 @@ public: const CGSCCAnalysisManager &getManager() const { return *CGAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const CGSCCAnalysisManager *CGAM; @@ -487,6 +383,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "CGSCCAnalysisManagerFunctionProxy"; } + CGSCCAnalysisManagerFunctionProxy(const CGSCCAnalysisManager &CGAM) : CGAM(&CGAM) {} // We have to explicitly define all the special member functions because MSVC @@ -505,7 +403,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c CGAM reference into the /// result. - Result run(Function *) { return Result(*CGAM); } + Result run(Function &) { return Result(*CGAM); } private: static char PassID; @@ -531,7 +429,8 @@ public: : Pass(Arg.Pass) {} CGSCCToFunctionPassAdaptor(CGSCCToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(CGSCCToFunctionPassAdaptor &LHS, CGSCCToFunctionPassAdaptor &RHS) { + friend void swap(CGSCCToFunctionPassAdaptor &LHS, + CGSCCToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -541,21 +440,23 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(LazyCallGraph::SCC *C, CGSCCAnalysisManager *AM) { + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult(C).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (LazyCallGraph::Node *N : *C) { - PreservedAnalyses PassPA = Pass.run(&N->getFunction(), FAM); + for (LazyCallGraph::Node *N : C) { + PreservedAnalyses PassPA = Pass.run(N->getFunction(), FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so // directly handle the function analysis manager's invalidation here. + // Also, update the preserved analyses to reflect that once invalidated + // these can again be preserved. if (FAM) - FAM->invalidate(&N->getFunction(), PassPA); + PassPA = FAM->invalidate(N->getFunction(), std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -585,7 +486,6 @@ CGSCCToFunctionPassAdaptor createCGSCCToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(CGSCCToFunctionPassAdaptor(std::move(Pass))); } - } #endif diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 9a6a4a7..76d9073 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -58,7 +58,6 @@ #include "llvm/IR/Function.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Pass.h" -#include "llvm/Support/IncludeFile.h" #include namespace llvm { @@ -418,13 +417,24 @@ template <> struct GraphTraits { template <> struct GraphTraits { typedef const CallGraphNode NodeType; - typedef NodeType::const_iterator ChildIteratorType; + + typedef CallGraphNode::CallRecord CGNPairTy; + typedef std::pointer_to_unary_function + CGNDerefFun; static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; } + + typedef mapped_iterator + ChildIteratorType; + static inline ChildIteratorType child_begin(NodeType *N) { - return N->begin(); + return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); } - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static inline ChildIteratorType child_end(NodeType *N) { + return map_iterator(N->end(), CGNDerefFun(CGNDeref)); + } + + static const CallGraphNode *CGNDeref(CGNPairTy P) { return P.second; } }; template <> @@ -451,17 +461,24 @@ template <> struct GraphTraits : public GraphTraits< const CallGraphNode *> { static NodeType *getEntryNode(const CallGraph *CGN) { - return CGN->getExternalCallingNode(); + return CGN->getExternalCallingNode(); // Start at the external node! } + typedef std::pair PairTy; + typedef std::pointer_to_unary_function + DerefFun; + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef CallGraph::const_iterator nodes_iterator; - static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); } - static nodes_iterator nodes_end(const CallGraph *CG) { return CG->end(); } + typedef mapped_iterator nodes_iterator; + static nodes_iterator nodes_begin(const CallGraph *CG) { + return map_iterator(CG->begin(), DerefFun(CGdereference)); + } + static nodes_iterator nodes_end(const CallGraph *CG) { + return map_iterator(CG->end(), DerefFun(CGdereference)); + } + + static const CallGraphNode &CGdereference(PairTy P) { return *P.second; } }; } // End llvm namespace -// Make sure that any clients of this file link in CallGraph.cpp -FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph) - #endif diff --git a/include/llvm/Analysis/CodeMetrics.h b/include/llvm/Analysis/CodeMetrics.h index 04b39c1..2f59691 100644 --- a/include/llvm/Analysis/CodeMetrics.h +++ b/include/llvm/Analysis/CodeMetrics.h @@ -16,10 +16,13 @@ #define LLVM_ANALYSIS_CODEMETRICS_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/CallSite.h" namespace llvm { +class AssumptionCache; class BasicBlock; +class Loop; class Function; class Instruction; class DataLayout; @@ -85,7 +88,18 @@ struct CodeMetrics { NumInlineCandidates(0), NumVectorInsts(0), NumRets(0) {} /// \brief Add information about a block to the current state. - void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI); + void analyzeBasicBlock(const BasicBlock *BB, const TargetTransformInfo &TTI, + SmallPtrSetImpl &EphValues); + + /// \brief Collect a loop's ephemeral values (those used only by an assume + /// or similar intrinsics in the loop). + static void collectEphemeralValues(const Loop *L, AssumptionCache *AC, + SmallPtrSetImpl &EphValues); + + /// \brief Collect a functions's ephemeral values (those used only by an + /// assume or similar intrinsics in the function). + static void collectEphemeralValues(const Function *L, AssumptionCache *AC, + SmallPtrSetImpl &EphValues); }; } diff --git a/include/llvm/Analysis/DOTGraphTraitsPass.h b/include/llvm/Analysis/DOTGraphTraitsPass.h index 53c832c..cb74e9f 100644 --- a/include/llvm/Analysis/DOTGraphTraitsPass.h +++ b/include/llvm/Analysis/DOTGraphTraitsPass.h @@ -66,15 +66,15 @@ public: bool runOnFunction(Function &F) override { GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis()); std::string Filename = Name + "." + F.getName().str() + ".dot"; - std::string ErrorInfo; + std::error_code EC; errs() << "Writing '" << Filename << "'..."; - raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); + raw_fd_ostream File(Filename, EC, sys::fs::F_Text); std::string GraphName = DOTGraphTraits::getGraphName(Graph); std::string Title = GraphName + " for '" + F.getName().str() + "' function"; - if (ErrorInfo.empty()) + if (!EC) WriteGraph(File, Graph, IsSimple, Title); else errs() << " error opening file for writing!"; @@ -129,14 +129,14 @@ public: bool runOnModule(Module &M) override { GraphT Graph = AnalysisGraphTraitsT::getGraph(&getAnalysis()); std::string Filename = Name + ".dot"; - std::string ErrorInfo; + std::error_code EC; errs() << "Writing '" << Filename << "'..."; - raw_fd_ostream File(Filename.c_str(), ErrorInfo, sys::fs::F_Text); + raw_fd_ostream File(Filename, EC, sys::fs::F_Text); std::string Title = DOTGraphTraits::getGraphName(Graph); - if (ErrorInfo.empty()) + if (!EC) WriteGraph(File, Graph, IsSimple, Title); else errs() << " error opening file for writing!"; diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index 279755e..1041e3f 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -287,9 +287,9 @@ namespace llvm { /// The flag PossiblyLoopIndependent should be set by the caller /// if it appears that control flow can reach from Src to Dst /// without traversing a loop back edge. - Dependence *depends(Instruction *Src, - Instruction *Dst, - bool PossiblyLoopIndependent); + std::unique_ptr depends(Instruction *Src, + Instruction *Dst, + bool PossiblyLoopIndependent); /// getSplitIteration - Give a dependence that's splittable at some /// particular level, return the iteration that should be used to split @@ -331,7 +331,7 @@ namespace llvm { /// /// breaks the dependence and allows us to vectorize/parallelize /// both loops. - const SCEV *getSplitIteration(const Dependence *Dep, unsigned Level); + const SCEV *getSplitIteration(const Dependence &Dep, unsigned Level); private: AliasAnalysis *AA; @@ -523,6 +523,12 @@ namespace llvm { /// in LoopNest. bool isLoopInvariant(const SCEV *Expression, const Loop *LoopNest) const; + /// Makes sure both subscripts (i.e. Pair->Src and Pair->Dst) share the same + /// integer type by sign-extending one of them when necessary. + /// Sign-extending a subscript is safe because getelementptr assumes the + /// array subscripts are signed. + void unifySubscriptType(Subscript *Pair); + /// removeMatchingExtensions - Examines a subscript pair. /// If the source and destination are identically sign (or zero) /// extended, it strips off the extension in an effort to @@ -911,7 +917,7 @@ namespace llvm { bool tryDelinearize(const SCEV *SrcSCEV, const SCEV *DstSCEV, SmallVectorImpl &Pair, - const SCEV *ElementSize) const; + const SCEV *ElementSize); public: static char ID; // Class identification, replacement for typeinfo diff --git a/include/llvm/Analysis/DominanceFrontier.h b/include/llvm/Analysis/DominanceFrontier.h index f42b9cb..996700e 100644 --- a/include/llvm/Analysis/DominanceFrontier.h +++ b/include/llvm/Analysis/DominanceFrontier.h @@ -102,7 +102,9 @@ public: void print(raw_ostream &OS) const; /// dump - Dump the dominance frontier to dbgs(). +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const; +#endif }; //===------------------------------------- diff --git a/include/llvm/Analysis/DominanceFrontierImpl.h b/include/llvm/Analysis/DominanceFrontierImpl.h index 04df2cc..735bfb8 100644 --- a/include/llvm/Analysis/DominanceFrontierImpl.h +++ b/include/llvm/Analysis/DominanceFrontierImpl.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H -#define LLVM_ANALYSIS_DOMINANCEFRONTIER_IMPL_H +#ifndef LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H +#define LLVM_ANALYSIS_DOMINANCEFRONTIERIMPL_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Debug.h" @@ -172,9 +172,7 @@ ForwardDominanceFrontierBase::calculate(const DomTreeT &DT, DomSetType &S = this->Frontiers[currentBB]; // Visit each block only once. - if (visited.count(currentBB) == 0) { - visited.insert(currentBB); - + if (visited.insert(currentBB).second) { // Loop over CFG successors to calculate DFlocal[currentNode] for (auto SI = BlockTraits::child_begin(currentBB), SE = BlockTraits::child_end(currentBB); diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h deleted file mode 100644 index 574c947..0000000 --- a/include/llvm/Analysis/FindUsedTypes.h +++ /dev/null @@ -1,66 +0,0 @@ -//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This pass is used to seek out all of the types in use by the program. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H -#define LLVM_ANALYSIS_FINDUSEDTYPES_H - -#include "llvm/ADT/SetVector.h" -#include "llvm/Pass.h" - -namespace llvm { - -class Type; -class Value; - -class FindUsedTypes : public ModulePass { - SetVector UsedTypes; -public: - static char ID; // Pass identification, replacement for typeid - FindUsedTypes() : ModulePass(ID) { - initializeFindUsedTypesPass(*PassRegistry::getPassRegistry()); - } - - /// getTypes - After the pass has been run, return the set containing all of - /// the types used in the module. - /// - const SetVector &getTypes() const { return UsedTypes; } - - /// Print the types found in the module. If the optional Module parameter is - /// passed in, then the types are printed symbolically if possible, using the - /// symbol table from the module. - /// - void print(raw_ostream &o, const Module *M) const override; - -private: - /// IncorporateType - Incorporate one type and all of its subtypes into the - /// collection of used types. - /// - void IncorporateType(Type *Ty); - - /// IncorporateValue - Incorporate all of the types used by this value. - /// - void IncorporateValue(const Value *V); - -public: - /// run - This incorporates all types used by the specified module - bool runOnModule(Module &M) override; - - /// getAnalysisUsage - We do not modify anything. - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesAll(); - } -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Analysis/FunctionTargetTransformInfo.h b/include/llvm/Analysis/FunctionTargetTransformInfo.h new file mode 100644 index 0000000..fce5a1a --- /dev/null +++ b/include/llvm/Analysis/FunctionTargetTransformInfo.h @@ -0,0 +1,49 @@ +//===- llvm/Analysis/FunctionTargetTransformInfo.h --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass wraps a TargetTransformInfo in a FunctionPass so that it can +// forward along the current Function so that we can make target specific +// decisions based on the particular subtarget specified for each Function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H +#define LLVM_ANALYSIS_FUNCTIONTARGETTRANSFORMINFO_H + +#include "TargetTransformInfo.h" +#include "llvm/Pass.h" + +namespace llvm { +class FunctionTargetTransformInfo final : public FunctionPass { +private: + const Function *Fn; + const TargetTransformInfo *TTI; + + FunctionTargetTransformInfo(const FunctionTargetTransformInfo &) + LLVM_DELETED_FUNCTION; + void operator=(const FunctionTargetTransformInfo &) LLVM_DELETED_FUNCTION; + +public: + static char ID; + FunctionTargetTransformInfo(); + + // Implementation boilerplate. + void getAnalysisUsage(AnalysisUsage &AU) const override; + void releaseMemory() override; + bool runOnFunction(Function &F) override; + + // Shimmed functions from TargetTransformInfo. + void + getUnrollingPreferences(Loop *L, + TargetTransformInfo::UnrollingPreferences &UP) const { + TTI->getUnrollingPreferences(Fn, L, UP); + } +}; +} +#endif diff --git a/include/llvm/Analysis/IVUsers.h b/include/llvm/Analysis/IVUsers.h index 6038872..d1f0370 100644 --- a/include/llvm/Analysis/IVUsers.h +++ b/include/llvm/Analysis/IVUsers.h @@ -174,7 +174,7 @@ public: /// dump - This method is used for debugging. void dump() const; protected: - bool AddUsersImpl(Instruction *I, SmallPtrSet &SimpleLoopNests); + bool AddUsersImpl(Instruction *I, SmallPtrSetImpl &SimpleLoopNests); }; Pass *createIVUsersPass(); diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index aaed716..a064cfc 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -19,6 +19,7 @@ #include namespace llvm { +class AssumptionCacheTracker; class CallSite; class DataLayout; class Function; @@ -100,6 +101,7 @@ public: /// \brief Cost analyzer used by inliner. class InlineCostAnalysis : public CallGraphSCCPass { const TargetTransformInfo *TTI; + AssumptionCacheTracker *ACT; public: static char ID; diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index 2367c0b..b88e089 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -37,6 +37,7 @@ namespace llvm { template class ArrayRef; + class AssumptionCache; class DominatorTree; class Instruction; class DataLayout; @@ -50,150 +51,193 @@ namespace llvm { Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySubInst - Given operands for a Sub, see if we can /// fold the result. If not, this returns null. Value *SimplifySubInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FAdd, see if we can fold the result. If not, this /// returns null. Value *SimplifyFAddInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FSub, see if we can fold the result. If not, this /// returns null. Value *SimplifyFSubInst(Value *LHS, Value *RHS, FastMathFlags FMF, - const DataLayout *TD = nullptr, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DataLayout *TD = nullptr, + const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// Given operands for an FMul, see if we can fold the result. If not, this /// returns null. - Value *SimplifyFMulInst(Value *LHS, Value *RHS, - FastMathFlags FMF, + Value *SimplifyFMulInst(Value *LHS, Value *RHS, FastMathFlags FMF, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyMulInst - Given operands for a Mul, see if we can /// fold the result. If not, this returns null. Value *SimplifyMulInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySDivInst - Given operands for an SDiv, see if we can /// fold the result. If not, this returns null. Value *SimplifySDivInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyUDivInst - Given operands for a UDiv, see if we can /// fold the result. If not, this returns null. Value *SimplifyUDivInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyFDivInst - Given operands for an FDiv, see if we can /// fold the result. If not, this returns null. Value *SimplifyFDivInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySRemInst - Given operands for an SRem, see if we can /// fold the result. If not, this returns null. Value *SimplifySRemInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyURemInst - Given operands for a URem, see if we can /// fold the result. If not, this returns null. Value *SimplifyURemInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyFRemInst - Given operands for an FRem, see if we can /// fold the result. If not, this returns null. Value *SimplifyFRemInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyShlInst - Given operands for a Shl, see if we can /// fold the result. If not, this returns null. Value *SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyLShrInst - Given operands for a LShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyAShrInst - Given operands for a AShr, see if we can /// fold the result. If not, this returns null. Value *SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyAndInst - Given operands for an And, see if we can /// fold the result. If not, this returns null. Value *SimplifyAndInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyOrInst - Given operands for an Or, see if we can /// fold the result. If not, this returns null. Value *SimplifyOrInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyXorInst - Given operands for a Xor, see if we can /// fold the result. If not, this returns null. Value *SimplifyXorInst(Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyICmpInst - Given operands for an ICmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + Instruction *CxtI = nullptr); /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifySelectInst - Given operands for a SelectInst, see if we can fold /// the result. If not, this returns null. Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyGEPInst - Given operands for an GetElementPtrInst, see if we can /// fold the result. If not, this returns null. Value *SimplifyGEPInst(ArrayRef Ops, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyInsertValueInst - Given operands for an InsertValueInst, see if we /// can fold the result. If not, this returns null. @@ -201,13 +245,17 @@ namespace llvm { ArrayRef Idxs, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold /// the result. If not, this returns null. Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); //=== Helper functions for higher up the class hierarchy. @@ -217,14 +265,18 @@ namespace llvm { Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyBinOp - Given operands for a BinaryOperator, see if we can /// fold the result. If not, this returns null. Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and iterators over arguments, see if we can fold /// the result. @@ -233,7 +285,9 @@ namespace llvm { Value *SimplifyCall(Value *V, User::op_iterator ArgBegin, User::op_iterator ArgEnd, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// \brief Given a function and set of arguments, see if we can fold the /// result. @@ -242,14 +296,16 @@ namespace llvm { Value *SimplifyCall(Value *V, ArrayRef Args, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr); /// SimplifyInstruction - See if we can compute a simplified version of this /// instruction. If not, this returns null. Value *SimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); - + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr); /// \brief Replace all uses of 'I' with 'SimpleV' and simplify the uses /// recursively. @@ -262,7 +318,8 @@ namespace llvm { bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr); /// \brief Recursively attempt to simplify an instruction. /// @@ -273,7 +330,8 @@ namespace llvm { bool recursivelySimplifyInstruction(Instruction *I, const DataLayout *TD = nullptr, const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr); + const DominatorTree *DT = nullptr, + AssumptionCache *AC = nullptr); } // end namespace llvm #endif diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h index 73aff76..3b51d44 100644 --- a/include/llvm/Analysis/IntervalIterator.h +++ b/include/llvm/Analysis/IntervalIterator.h @@ -165,10 +165,10 @@ private: // bool ProcessInterval(NodeTy *Node) { BasicBlock *Header = getNodeHeader(Node); - if (Visited.count(Header)) return false; + if (!Visited.insert(Header).second) + return false; Interval *Int = new Interval(Header); - Visited.insert(Header); // The header has now been visited! // Check all of our successors to see if they are in the interval... for (typename GT::ChildIteratorType I = GT::child_begin(Node), diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h index 54760aa..591e794 100644 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -16,7 +16,6 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Pass.h" - #include namespace llvm { @@ -37,7 +36,9 @@ class JumpInstrTableInfo : public ImmutablePass { public: static char ID; - JumpInstrTableInfo(); + /// The default byte alignment for jump tables is 16, which is large but + /// usually safe. + JumpInstrTableInfo(uint64_t ByteAlign = 16); virtual ~JumpInstrTableInfo(); const char *getPassName() const override { return "Jump-Instruction Table Info"; @@ -52,9 +53,19 @@ public: /// Gets the tables. const JumpTables &getTables() const { return Tables; } + /// Gets the alignment in bytes of a jumptable entry. + uint64_t entryByteAlignment() const { return ByteAlignment; } private: JumpTables Tables; + + /// A power-of-two alignment of a jumptable entry. + uint64_t ByteAlignment; }; + +/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This +/// bound specifies the maximum number of bytes needed to represent an +/// unconditional jump or a trap instruction in the back end currently in use. +ModulePass *createJumpInstrTableInfoPass(unsigned Bound); } #endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */ diff --git a/include/llvm/Analysis/LazyCallGraph.h b/include/llvm/Analysis/LazyCallGraph.h index 70a4df5..b0b9068 100644 --- a/include/llvm/Analysis/LazyCallGraph.h +++ b/include/llvm/Analysis/LazyCallGraph.h @@ -32,8 +32,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ANALYSIS_LAZY_CALL_GRAPH -#define LLVM_ANALYSIS_LAZY_CALL_GRAPH +#ifndef LLVM_ANALYSIS_LAZYCALLGRAPH_H +#define LLVM_ANALYSIS_LAZYCALLGRAPH_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" @@ -46,11 +46,11 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" #include "llvm/Support/Allocator.h" #include namespace llvm { -class ModuleAnalysisManager; class PreservedAnalyses; class raw_ostream; @@ -252,6 +252,12 @@ public: /// \brief Test if this SCC is a descendant of \a C. bool isDescendantOf(const SCC &C) const; + /// \brief Short name useful for debugging or logging. + /// + /// We use the name of the first function in the SCC to name the SCC for + /// the purposes of debugging and logging. + StringRef getName() const { return (*begin())->getFunction().getName(); } + ///@{ /// \name Mutation API /// @@ -537,11 +543,13 @@ public: static void *ID() { return (void *)&PassID; } - /// \brief Compute the \c LazyCallGraph for a the module \c M. + static StringRef name() { return "Lazy CallGraph Analysis"; } + + /// \brief Compute the \c LazyCallGraph for the module \c M. /// /// This just builds the set of entry points to the call graph. The rest is /// built lazily as it is walked. - LazyCallGraph run(Module *M) { return LazyCallGraph(*M); } + LazyCallGraph run(Module &M) { return LazyCallGraph(M); } private: static char PassID; @@ -556,7 +564,7 @@ class LazyCallGraphPrinterPass { public: explicit LazyCallGraphPrinterPass(raw_ostream &OS); - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM); + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM); static StringRef name() { return "LazyCallGraphPrinterPass"; } }; diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 2fe7386..9a67d52 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -18,16 +18,20 @@ #include "llvm/Pass.h" namespace llvm { + class AssumptionCache; class Constant; class DataLayout; + class DominatorTree; + class Instruction; class TargetLibraryInfo; class Value; -/// LazyValueInfo - This pass computes, caches, and vends lazy value constraint -/// information. +/// This pass computes, caches, and vends lazy value constraint information. class LazyValueInfo : public FunctionPass { + AssumptionCache *AC; const DataLayout *DL; class TargetLibraryInfo *TLI; + DominatorTree *DT; void *PImpl; LazyValueInfo(const LazyValueInfo&) LLVM_DELETED_FUNCTION; void operator=(const LazyValueInfo&) LLVM_DELETED_FUNCTION; @@ -38,7 +42,7 @@ public: } ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } - /// Tristate - This is used to return true/false/dunno results. + /// This is used to return true/false/dunno results. enum Tristate { Unknown = -1, False = 0, True = 1 }; @@ -46,26 +50,33 @@ public: // Public query interface. - /// getPredicateOnEdge - Determine whether the specified value comparison - /// with a constant is known to be true or false on the specified CFG edge. + /// Determine whether the specified value comparison with a constant is known + /// to be true or false on the specified CFG edge. /// Pred is a CmpInst predicate. Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C, - BasicBlock *FromBB, BasicBlock *ToBB); + BasicBlock *FromBB, BasicBlock *ToBB, + Instruction *CxtI = nullptr); - - /// getConstant - Determine whether the specified value is known to be a + /// Determine whether the specified value comparison with a constant is known + /// to be true or false at the specified instruction + /// (from an assume intrinsic). Pred is a CmpInst predicate. + Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C, + Instruction *CxtI); + + /// Determine whether the specified value is known to be a /// constant at the end of the specified block. Return null if not. - Constant *getConstant(Value *V, BasicBlock *BB); + Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr); - /// getConstantOnEdge - Determine whether the specified value is known to be a + /// Determine whether the specified value is known to be a /// constant on the specified edge. Return null if not. - Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB); + Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB, + Instruction *CxtI = nullptr); - /// threadEdge - Inform the analysis cache that we have threaded an edge from + /// Inform the analysis cache that we have threaded an edge from /// PredBB to OldSucc to be from PredBB to NewSucc instead. void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc); - /// eraseBlock - Inform the analysis cache that we have erased a block. + /// Inform the analysis cache that we have erased a block. void eraseBlock(BasicBlock *BB); // Implementation boilerplate. diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index 25c5928..0fe3453 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -44,14 +44,14 @@ bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom, /// If it is set to 0, it will scan the whole block. You can also optionally /// specify an alias analysis implementation, which makes this more precise. /// -/// If TBAATag is non-null and a load or store is found, the TBAA tag from the -/// load or store is recorded there. If there is no TBAA tag or if no access +/// If AATags is non-null and a load or store is found, the AA tags from the +/// load or store are recorded there. If there are no AA tags or if no access /// is found, it is left unmodified. Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB, BasicBlock::iterator &ScanFrom, unsigned MaxInstsToScan = 6, AliasAnalysis *AA = nullptr, - MDNode **TBAATag = nullptr); + AAMDNodes *AATags = nullptr); } diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h index 726e286..8650000 100644 --- a/include/llvm/Analysis/LoopPass.h +++ b/include/llvm/Analysis/LoopPass.h @@ -82,6 +82,11 @@ public: /// deleteAnalysisValue - Delete analysis info associated with value V. virtual void deleteAnalysisValue(Value *V, Loop *L) {} + /// Delete analysis info associated with Loop L. + /// Called to notify a Pass that a loop has been deleted and any + /// associated analysis values can be deleted. + virtual void deleteAnalysisLoop(Loop *L) {} + protected: /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone /// and most transformation passes should skip it. @@ -152,6 +157,10 @@ public: /// that implement simple analysis interface. void deleteSimpleAnalysisValue(Value *V, Loop *L); + /// Invoke deleteAnalysisLoop hook for all passes that implement simple + /// analysis interface. + void deleteSimpleAnalysisLoop(Loop *L); + private: std::deque LQ; bool skipThisLoop; diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index 1c4441b..67fd70a 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -28,6 +28,7 @@ namespace llvm { class Instruction; class CallSite; class AliasAnalysis; + class AssumptionCache; class DataLayout; class MemoryDependenceAnalysis; class PredIteratorCache; @@ -281,12 +282,12 @@ namespace llvm { /// Size - The maximum size of the dereferences of the /// pointer. May be UnknownSize if the sizes are unknown. uint64_t Size; - /// TBAATag - The TBAA tag associated with dereferences of the - /// pointer. May be null if there are no tags or conflicting tags. - const MDNode *TBAATag; + /// AATags - The AA tags associated with dereferences of the + /// pointer. The members may be null if there are no tags or + /// conflicting tags. + AAMDNodes AATags; - NonLocalPointerInfo() - : Size(AliasAnalysis::UnknownSize), TBAATag(nullptr) {} + NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize) {} }; /// CachedNonLocalPointerInfo - This map stores the cached results of doing @@ -325,6 +326,7 @@ namespace llvm { AliasAnalysis *AA; const DataLayout *DL; DominatorTree *DT; + AssumptionCache *AC; std::unique_ptr PredCache; public: @@ -364,12 +366,16 @@ namespace llvm { /// getNonLocalPointerDependency - Perform a full dependency query for an - /// access to the specified (non-volatile) memory location, returning the - /// set of instructions that either define or clobber the value. + /// access to the QueryInst's specified memory location, returning the set + /// of instructions that either define or clobber the value. /// - /// This method assumes the pointer has a "NonLocal" dependency within BB. - void getNonLocalPointerDependency(const AliasAnalysis::Location &Loc, - bool isLoad, BasicBlock *BB, + /// Warning: For a volatile query instruction, the dependencies will be + /// accurate, and thus usable for reordering, but it is never legal to + /// remove the query instruction. + /// + /// This method assumes the pointer has a "NonLocal" dependency within + /// QueryInst's parent basic block. + void getNonLocalPointerDependency(Instruction *QueryInst, SmallVectorImpl &Result); /// removeInstruction - Remove an instruction from the dependence analysis, diff --git a/include/llvm/Analysis/PHITransAddr.h b/include/llvm/Analysis/PHITransAddr.h index 69f5907..38730d8 100644 --- a/include/llvm/Analysis/PHITransAddr.h +++ b/include/llvm/Analysis/PHITransAddr.h @@ -18,6 +18,7 @@ #include "llvm/IR/Instruction.h" namespace llvm { + class AssumptionCache; class DominatorTree; class DataLayout; class TargetLibraryInfo; @@ -41,12 +42,15 @@ class PHITransAddr { /// TLI - The target library info if known, otherwise null. const TargetLibraryInfo *TLI; - + + /// A cache of @llvm.assume calls used by SimplifyInstruction. + AssumptionCache *AC; + /// InstInputs - The inputs for our symbolic address. SmallVector InstInputs; public: - PHITransAddr(Value *addr, const DataLayout *DL) - : Addr(addr), DL(DL), TLI(nullptr) { + PHITransAddr(Value *addr, const DataLayout *DL, AssumptionCache *AC) + : Addr(addr), DL(DL), TLI(nullptr), AC(AC) { // If the address is an instruction, the whole thing is considered an input. if (Instruction *I = dyn_cast(Addr)) InstInputs.push_back(I); diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index fd65ae5..10a5605 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -66,6 +66,13 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createCFLAliasAnalysisPass - This pass implements a set-based approach to + // alias analysis. + // + ImmutablePass *createCFLAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // /// createLibCallAliasAnalysisPass - Create an alias analysis pass that knows /// about the semantics of a set of libcalls specified by LCI. The newly /// constructed pass takes ownership of the pointer that is provided. @@ -88,11 +95,20 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createScopedNoAliasAAPass - This pass implements metadata-based + // scoped noalias analysis. + // + ImmutablePass *createScopedNoAliasAAPass(); + + //===--------------------------------------------------------------------===// + // // createObjCARCAliasAnalysisPass - This pass implements ObjC-ARC-based // alias analysis. // ImmutablePass *createObjCARCAliasAnalysisPass(); + FunctionPass *createPAEvalPass(); + //===--------------------------------------------------------------------===// // /// createLazyValueInfoPass - This creates an instance of the LazyValueInfo diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index d330755..72cd357 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -19,7 +19,7 @@ namespace llvm { /// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to -/// compute the a post-dominator tree. +/// compute the post-dominator tree. /// struct PostDominatorTree : public FunctionPass { static char ID; // Pass identification, replacement for typeid diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 49c88fd..6ff7f97 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -424,8 +424,10 @@ public: void print(raw_ostream &OS, bool printTree = true, unsigned level = 0, PrintStyle Style = PrintNone) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// @brief Print the region to stderr. void dump() const; +#endif /// @brief Check if the region contains a BasicBlock. /// @@ -732,7 +734,9 @@ public: static typename RegionT::PrintStyle printStyle; void print(raw_ostream &OS) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) void dump() const; +#endif void releaseMemory(); diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index 4266b84..b0dc263 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -12,11 +12,11 @@ #ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H #define LLVM_ANALYSIS_REGIONINFOIMPL_H -#include "llvm/Analysis/RegionInfo.h" #include "llvm/ADT/PostOrderIterator.h" #include "llvm/Analysis/DominanceFrontier.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/RegionInfo.h" #include "llvm/Analysis/RegionIterator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -25,7 +25,7 @@ #include #include -using namespace llvm; +namespace llvm { #define DEBUG_TYPE "region" @@ -916,4 +916,8 @@ void RegionInfoBase::calculate(FuncT &F) { buildRegionsTree(DT->getNode(BB), TopLevelRegion); } +#undef DEBUG_TYPE + +} // end namespace llvm + #endif diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 617e545..f394e33 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -35,6 +35,7 @@ namespace llvm { class APInt; + class AssumptionCache; class Constant; class ConstantInt; class DominatorTree; @@ -128,9 +129,11 @@ namespace llvm { /// purposes. void print(raw_ostream &OS) const; +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) /// dump - This method is used for debugging. /// void dump() const; +#endif }; // Specialize FoldingSetTrait for SCEV to avoid needing to compute @@ -221,6 +224,9 @@ namespace llvm { /// Function *F; + /// The tracker for @llvm.assume intrinsics in this function. + AssumptionCache *AC; + /// LI - The loop information for the function we are currently analyzing. /// LoopInfo *LI; @@ -257,24 +263,13 @@ namespace llvm { /// loop exit's branch condition evaluates to the not-taken path. This is a /// temporary pair of exact and max expressions that are eventually /// summarized in ExitNotTakenInfo and BackedgeTakenInfo. - /// - /// If MustExit is true, then the exit must be taken when the BECount - /// reaches Exact (and before surpassing Max). If MustExit is false, then - /// BECount may exceed Exact or Max if the loop exits via another branch. In - /// either case, the loop may exit early via another branch. - /// - /// MustExit is true for most cases. However, an exit guarded by an - /// (in)equality on a nonunit stride may be skipped. struct ExitLimit { const SCEV *Exact; const SCEV *Max; - bool MustExit; - /*implicit*/ ExitLimit(const SCEV *E) - : Exact(E), Max(E), MustExit(true) {} + /*implicit*/ ExitLimit(const SCEV *E) : Exact(E), Max(E) {} - ExitLimit(const SCEV *E, const SCEV *M, bool MustExit) - : Exact(E), Max(M), MustExit(MustExit) {} + ExitLimit(const SCEV *E, const SCEV *M) : Exact(E), Max(M) {} /// hasAnyInfo - Test whether this ExitLimit contains any computed /// information, or whether it's all SCEVCouldNotCompute values. @@ -749,6 +744,13 @@ namespace llvm { bool isLoopBackedgeGuardedByCond(const Loop *L, ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS); + /// \brief Returns the maximum trip count of the loop if it is a single-exit + /// loop and we can compute a small maximum for that loop. + /// + /// Implemented in terms of the \c getSmallConstantTripCount overload with + /// the single exiting block passed to it. See that routine for details. + unsigned getSmallConstantTripCount(Loop *L); + /// getSmallConstantTripCount - Returns the maximum trip count of this loop /// as a normal unsigned value. Returns 0 if the trip count is unknown or /// not constant. This "trip count" assumes that control exits via @@ -758,6 +760,14 @@ namespace llvm { /// the loop exits prematurely via another branch. unsigned getSmallConstantTripCount(Loop *L, BasicBlock *ExitingBlock); + /// \brief Returns the largest constant divisor of the trip count of the + /// loop if it is a single-exit loop and we can compute a small maximum for + /// that loop. + /// + /// Implemented in terms of the \c getSmallConstantTripMultiple overload with + /// the single exiting block passed to it. See that routine for details. + unsigned getSmallConstantTripMultiple(Loop *L); + /// getSmallConstantTripMultiple - Returns the largest constant divisor of /// the trip count of this loop as a normal unsigned value, if /// possible. This means that the actual trip count is always a multiple of diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 2f1b1c3..ff82db1 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -14,8 +14,8 @@ #ifndef LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H #define LLVM_ANALYSIS_SCALAREVOLUTIONEXPRESSIONS_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/Support/ErrorHandling.h" @@ -577,7 +577,7 @@ namespace llvm { SmallPtrSet Visited; void push(const SCEV *S) { - if (Visited.insert(S) && Visitor.follow(S)) + if (Visited.insert(S).second && Visitor.follow(S)) Worklist.push_back(S); } public: @@ -624,7 +624,7 @@ namespace llvm { } }; - /// Use SCEVTraversal to visit all nodes in the givien expression tree. + /// Use SCEVTraversal to visit all nodes in the given expression tree. template void visitAll(const SCEV *Root, SV& Visitor) { SCEVTraversal T(Visitor); diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index f57f3eb..4bd5dd8 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -28,6 +28,7 @@ namespace llvm { +class Function; class GlobalValue; class Loop; class Type; @@ -183,7 +184,7 @@ public: /// should probably move to simpler cost metrics using the above. /// Alternatively, we could split the cost interface into distinct code-size /// and execution-speed costs. This would allow modelling the core of this - /// query more accurately as the a call is a single small instruction, but + /// query more accurately as a call is a single small instruction, but /// incurs significant execution cost. virtual bool isLoweredToCall(const Function *F) const; @@ -227,7 +228,8 @@ public: /// \brief Get target-customized preferences for the generic loop unrolling /// transformation. The caller will initialize UP with the current /// target-independent defaults. - virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) const; + virtual void getUnrollingPreferences(const Function *F, Loop *L, + UnrollingPreferences &UP) const; /// @} @@ -268,6 +270,13 @@ public: int64_t BaseOffset, bool HasBaseReg, int64_t Scale) const; + /// \brief Return true if the target works with masked instruction + /// AVX2 allows masks for consecutive load and store for i32 and i64 elements. + /// AVX-512 architecture will also allow masks for non-consecutive memory + /// accesses. + virtual bool isLegalMaskedStore(Type *DataType, int Consecutive) const; + virtual bool isLegalMaskedLoad (Type *DataType, int Consecutive) const; + /// \brief Return the cost of the scaling factor used in the addressing /// mode represented by AM for this target, for a load/store /// of the specified type. @@ -335,6 +344,9 @@ public: OK_NonUniformConstantValue // Operand is a non uniform constant value. }; + /// \brief Additional properties of an operand's values. + enum OperandValueProperties { OP_None = 0, OP_PowerOf2 = 1 }; + /// \return The number of scalar or vector registers that the target has. /// If 'Vectors' is true, it returns the number of vector registers. If it is /// set to false, it returns the number of scalar registers. @@ -343,15 +355,18 @@ public: /// \return The width of the largest scalar or vector register type. virtual unsigned getRegisterBitWidth(bool Vector) const; - /// \return The maximum unroll factor that the vectorizer should try to + /// \return The maximum interleave factor that any transform should try to /// perform for this target. This number depends on the level of parallelism /// and the number of execution units in the CPU. - virtual unsigned getMaximumUnrollFactor() const; + virtual unsigned getMaxInterleaveFactor() const; /// \return The expected cost of arithmetic ops, such as mul, xor, fsub, etc. - virtual unsigned getArithmeticInstrCost(unsigned Opcode, Type *Ty, - OperandValueKind Opd1Info = OK_AnyValue, - OperandValueKind Opd2Info = OK_AnyValue) const; + virtual unsigned + getArithmeticInstrCost(unsigned Opcode, Type *Ty, + OperandValueKind Opd1Info = OK_AnyValue, + OperandValueKind Opd2Info = OK_AnyValue, + OperandValueProperties Opd1PropInfo = OP_None, + OperandValueProperties Opd2PropInfo = OP_None) const; /// \return The cost of a shuffle instruction of kind Kind and of type Tp. /// The index and subtype parameters are used by the subvector insertion and @@ -416,6 +431,13 @@ public: virtual unsigned getAddressComputationCost(Type *Ty, bool IsComplex = false) const; + /// \returns The cost, if any, of keeping values of the given types alive + /// over a callsite. + /// + /// Some types may require the use of register classes that do not have + /// any callee-saved registers, so would require a spill and fill. + virtual unsigned getCostOfKeepingLiveOverCall(ArrayRef Tys) const; + /// @} /// Analysis group identification. diff --git a/include/llvm/Analysis/ValueTracking.h b/include/llvm/Analysis/ValueTracking.h index 83b5408..cc58838 100644 --- a/include/llvm/Analysis/ValueTracking.h +++ b/include/llvm/Analysis/ValueTracking.h @@ -25,6 +25,8 @@ namespace llvm { class DataLayout; class StringRef; class MDNode; + class AssumptionCache; + class DominatorTree; class TargetLibraryInfo; /// Determine which bits of V are known to be either zero or one and return @@ -35,8 +37,11 @@ namespace llvm { /// where V is a vector, the known zero and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0); + void computeKnownBits(Value *V, APInt &KnownZero, APInt &KnownOne, + const DataLayout *TD = nullptr, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// Compute known bits from the range metadata. /// \p KnownZero the set of bits that are known to be zero void computeKnownBitsFromRangeMetadata(const MDNode &Ranges, @@ -45,21 +50,29 @@ namespace llvm { /// ComputeSignBit - Determine whether the sign bit is known to be zero or /// one. Convenience wrapper around computeKnownBits. void ComputeSignBit(Value *V, bool &KnownZero, bool &KnownOne, - const DataLayout *TD = nullptr, unsigned Depth = 0); + const DataLayout *TD = nullptr, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// isKnownToBeAPowerOfTwo - Return true if the given value is known to have /// exactly one bit set when defined. For vectors return true if every /// element is known to be a power of two when defined. Supports values with /// integer or pointer type and vectors of integers. If 'OrZero' is set then /// returns true if the given value is either a power of two or zero. - bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0); + bool isKnownToBeAPowerOfTwo(Value *V, bool OrZero = false, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// isKnownNonZero - Return true if the given value is known to be non-zero /// when defined. For vectors return true if every element is known to be /// non-zero when defined. Supports values with integer or pointer type and /// vectors of integers. bool isKnownNonZero(Value *V, const DataLayout *TD = nullptr, - unsigned Depth = 0); + unsigned Depth = 0, AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// MaskedValueIsZero - Return true if 'V & Mask' is known to be zero. We use /// this predicate to simplify operations downstream. Mask is known to be @@ -70,10 +83,12 @@ namespace llvm { /// where V is a vector, the mask, known zero, and known one values are the /// same width as the vector element, and the bit is set only if it is true /// for all of the elements in the vector. - bool MaskedValueIsZero(Value *V, const APInt &Mask, - const DataLayout *TD = nullptr, unsigned Depth = 0); + bool MaskedValueIsZero(Value *V, const APInt &Mask, + const DataLayout *TD = nullptr, unsigned Depth = 0, + AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); - /// ComputeNumSignBits - Return the number of times the sign bit of the /// register is replicated into the other bits. We know that at least 1 bit /// is always equal to the sign bit (itself), but other cases can give us @@ -83,7 +98,9 @@ namespace llvm { /// 'Op' must have a scalar integer type. /// unsigned ComputeNumSignBits(Value *Op, const DataLayout *TD = nullptr, - unsigned Depth = 0); + unsigned Depth = 0, AssumptionCache *AC = nullptr, + const Instruction *CxtI = nullptr, + const DominatorTree *DT = nullptr); /// ComputeMultiple - This function computes the integer multiple of Base that /// equals V. If successful, it returns true and returns the multiple in @@ -191,6 +208,24 @@ namespace llvm { /// and byval arguments. bool isKnownNonNull(const Value *V, const TargetLibraryInfo *TLI = nullptr); + /// Return true if it is valid to use the assumptions provided by an + /// assume intrinsic, I, at the point in the control-flow identified by the + /// context instruction, CxtI. + bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, + const DataLayout *DL = nullptr, + const DominatorTree *DT = nullptr); + + enum class OverflowResult { AlwaysOverflows, MayOverflow, NeverOverflows }; + OverflowResult computeOverflowForUnsignedMul(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); + OverflowResult computeOverflowForUnsignedAdd(Value *LHS, Value *RHS, + const DataLayout *DL, + AssumptionCache *AC, + const Instruction *CxtI, + const DominatorTree *DT); } // end namespace llvm #endif diff --git a/include/llvm/AsmParser/Parser.h b/include/llvm/AsmParser/Parser.h index 165c46d..7ef78d7 100644 --- a/include/llvm/AsmParser/Parser.h +++ b/include/llvm/AsmParser/Parser.h @@ -14,12 +14,11 @@ #ifndef LLVM_ASMPARSER_PARSER_H #define LLVM_ASMPARSER_PARSER_H -#include +#include "llvm/Support/MemoryBuffer.h" namespace llvm { class Module; -class MemoryBuffer; class SMDiagnostic; class LLVMContext; @@ -29,11 +28,12 @@ class LLVMContext; /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. /// @brief Parse LLVM Assembly from a file -Module *ParseAssemblyFile( - const std::string &Filename, ///< The name of the file to parse - SMDiagnostic &Error, ///< Error result info. - LLVMContext &Context ///< Context in which to allocate globals info. -); +/// @param Filename The name of the file to parse +/// @param Error Error result info. +/// @param Context Context in which to allocate globals info. +std::unique_ptr parseAssemblyFile(StringRef Filename, + SMDiagnostic &Error, + LLVMContext &Context); /// The function is a secondary interface to the LLVM Assembly Parser. It parses /// an ASCII string that (presumably) contains LLVM Assembly code. It returns a @@ -41,23 +41,31 @@ Module *ParseAssemblyFile( /// that this does not verify that the generated Module is valid, so you should /// run the verifier after parsing the file to check that it is okay. /// @brief Parse LLVM Assembly from a string -Module *ParseAssemblyString( - const char *AsmString, ///< The string containing assembly - Module *M, ///< A module to add the assembly too. - SMDiagnostic &Error, ///< Error result info. - LLVMContext &Context -); +/// @param AsmString The string containing assembly +/// @param Error Error result info. +/// @param Context Context in which to allocate globals info. +std::unique_ptr parseAssemblyString(StringRef AsmString, + SMDiagnostic &Error, + LLVMContext &Context); + +/// parseAssemblyFile and parseAssemblyString are wrappers around this function. +/// @brief Parse LLVM Assembly from a MemoryBuffer. +/// @param F The MemoryBuffer containing assembly +/// @param Err Error result info. +/// @param Context Context in which to allocate globals info. +std::unique_ptr parseAssembly(MemoryBufferRef F, SMDiagnostic &Err, + LLVMContext &Context); /// This function is the low-level interface to the LLVM Assembly Parser. -/// ParseAssemblyFile and ParseAssemblyString are wrappers around this function. -/// @brief Parse LLVM Assembly from a MemoryBuffer. This function *always* -/// takes ownership of the MemoryBuffer. -Module *ParseAssembly( - MemoryBuffer *F, ///< The MemoryBuffer containing assembly - Module *M, ///< A module to add the assembly too. - SMDiagnostic &Err, ///< Error result info. - LLVMContext &Context -); +/// This is kept as an independent function instead of being inlined into +/// parseAssembly for the convenience of interactive users that want to add +/// recently parsed bits to an existing module. +/// +/// @param F The MemoryBuffer containing assembly +/// @param M The module to add data to. +/// @param Err Error result info. +/// @return true on error. +bool parseAssemblyInto(MemoryBufferRef F, Module &M, SMDiagnostic &Err); } // End llvm namespace diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index b510daf..ed2dcf8 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -18,6 +18,7 @@ #ifndef LLVM_BITCODE_BITCODES_H #define LLVM_BITCODE_BITCODES_H +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" @@ -161,16 +162,13 @@ template <> struct isPodLike { static const bool value=true; }; /// BitCodeAbbrev - This class represents an abbreviation record. An /// abbreviation allows a complex record that has redundancy to be stored in a /// specialized format instead of the fully-general, fully-vbr, format. -class BitCodeAbbrev { +class BitCodeAbbrev : public RefCountedBase { SmallVector OperandList; - unsigned char RefCount; // Number of things using this. ~BitCodeAbbrev() {} -public: - BitCodeAbbrev() : RefCount(1) {} - - void addRef() { ++RefCount; } - void dropRef() { if (--RefCount == 0) delete this; } + // Only RefCountedBase is allowed to delete. + friend class RefCountedBase; +public: unsigned getNumOperandInfos() const { return static_cast(OperandList.size()); } diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h index 898cd52..8fe9b7e 100644 --- a/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_BITCODE_BITCODE_WRITER_PASS_H -#define LLVM_BITCODE_BITCODE_WRITER_PASS_H +#ifndef LLVM_BITCODE_BITCODEWRITERPASS_H +#define LLVM_BITCODE_BITCODEWRITERPASS_H #include "llvm/ADT/StringRef.h" @@ -41,7 +41,7 @@ public: /// \brief Run the bitcode writer pass, and output the module to the selected /// output stream. - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "BitcodeWriterPass"; } }; diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h index 6f478b7..865a3e6 100644 --- a/include/llvm/Bitcode/BitstreamReader.h +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -17,39 +17,37 @@ #include "llvm/Bitcode/BitCodes.h" #include "llvm/Support/Endian.h" -#include "llvm/Support/StreamableMemoryObject.h" +#include "llvm/Support/StreamingMemoryObject.h" #include #include #include namespace llvm { - class Deserializer; +class Deserializer; -/// BitstreamReader - This class is used to read from an LLVM bitcode stream, -/// maintaining information that is global to decoding the entire file. While -/// a file is being read, multiple cursors can be independently advanced or -/// skipped around within the file. These are represented by the -/// BitstreamCursor class. +/// This class is used to read from an LLVM bitcode stream, maintaining +/// information that is global to decoding the entire file. While a file is +/// being read, multiple cursors can be independently advanced or skipped around +/// within the file. These are represented by the BitstreamCursor class. class BitstreamReader { public: - /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. - /// These describe abbreviations that all blocks of the specified ID inherit. + /// This contains information emitted to BLOCKINFO_BLOCK blocks. These + /// describe abbreviations that all blocks of the specified ID inherit. struct BlockInfo { unsigned BlockID; - std::vector Abbrevs; + std::vector> Abbrevs; std::string Name; std::vector > RecordNames; }; private: - std::unique_ptr BitcodeBytes; + std::unique_ptr BitcodeBytes; std::vector BlockInfoRecords; - /// IgnoreBlockInfoNames - This is set to true if we don't care about the - /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer - /// uses this. + /// This is set to true if we don't care about the block/record name + /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. bool IgnoreBlockInfoNames; BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; @@ -58,13 +56,24 @@ public: BitstreamReader() : IgnoreBlockInfoNames(true) { } - BitstreamReader(const unsigned char *Start, const unsigned char *End) { - IgnoreBlockInfoNames = true; + BitstreamReader(const unsigned char *Start, const unsigned char *End) + : IgnoreBlockInfoNames(true) { init(Start, End); } - BitstreamReader(StreamableMemoryObject *bytes) { - BitcodeBytes.reset(bytes); + BitstreamReader(std::unique_ptr BitcodeBytes) + : BitcodeBytes(std::move(BitcodeBytes)), IgnoreBlockInfoNames(true) {} + + BitstreamReader(BitstreamReader &&Other) { + *this = std::move(Other); + } + + BitstreamReader &operator=(BitstreamReader &&Other) { + BitcodeBytes = std::move(Other.BitcodeBytes); + // Explicitly swap block info, so that nothing gets destroyed twice. + std::swap(BlockInfoRecords, Other.BlockInfoRecords); + IgnoreBlockInfoNames = Other.IgnoreBlockInfoNames; + return *this; } void init(const unsigned char *Start, const unsigned char *End) { @@ -72,22 +81,9 @@ public: BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); } - StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; } + MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } - ~BitstreamReader() { - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } - } - - /// CollectBlockInfoNames - This is called by clients that want block/record - /// name information. + /// This is called by clients that want block/record name information. void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; } @@ -95,13 +91,13 @@ public: // Block Manipulation //===--------------------------------------------------------------------===// - /// hasBlockInfoRecords - Return true if we've already read and processed the - /// block info block for this Bitstream. We only process it for the first - /// cursor that walks over it. + /// Return true if we've already read and processed the block info block for + /// this Bitstream. We only process it for the first cursor that walks over + /// it. bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } - /// getBlockInfo - If there is block info for the specified ID, return it, - /// otherwise return null. + /// If there is block info for the specified ID, return it, otherwise return + /// null. const BlockInfo *getBlockInfo(unsigned BlockID) const { // Common case, the most recent entry matches BlockID. if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) @@ -123,23 +119,26 @@ public: BlockInfoRecords.back().BlockID = BlockID; return BlockInfoRecords.back(); } -}; + /// Takes block info from the other bitstream reader. + /// + /// This is a "take" operation because BlockInfo records are non-trivial, and + /// indeed rather expensive. + void takeBlockInfo(BitstreamReader &&Other) { + assert(!hasBlockInfoRecords()); + BlockInfoRecords = std::move(Other.BlockInfoRecords); + } +}; -/// BitstreamEntry - When advancing through a bitstream cursor, each advance can -/// discover a few different kinds of entries: -/// Error - Malformed bitcode was found. -/// EndBlock - We've reached the end of the current block, (or the end of the -/// file, which is treated like a series of EndBlock records. -/// SubBlock - This is the start of a new subblock of a specific ID. -/// Record - This is a record with a specific AbbrevID. -/// +/// When advancing through a bitstream cursor, each advance can discover a few +/// different kinds of entries: struct BitstreamEntry { enum { - Error, - EndBlock, - SubBlock, - Record + Error, // Malformed bitcode was found. + EndBlock, // We've reached the end of the current block, (or the end of the + // file, which is treated like a series of EndBlock records. + SubBlock, // This is the start of a new subblock of a specific ID. + Record // This is a record with a specific AbbrevID. } Kind; unsigned ID; @@ -158,9 +157,9 @@ struct BitstreamEntry { } }; -/// BitstreamCursor - This represents a position within a bitcode file. There -/// may be multiple independent cursors reading within one bitstream, each -/// maintaining their own local state. +/// This represents a position within a bitcode file. There may be multiple +/// independent cursors reading within one bitstream, each maintaining their own +/// local state. /// /// Unlike iterators, BitstreamCursors are heavy-weight objects that should not /// be passed by value. @@ -169,92 +168,74 @@ class BitstreamCursor { BitstreamReader *BitStream; size_t NextChar; + // The size of the bicode. 0 if we don't know it yet. + size_t Size; - /// CurWord/word_t - This is the current data we have pulled from the stream - /// but have not returned to the client. This is specifically and - /// intentionally defined to follow the word size of the host machine for - /// efficiency. We use word_t in places that are aware of this to make it - /// perfectly explicit what is going on. - typedef uint32_t word_t; + /// This is the current data we have pulled from the stream but have not + /// returned to the client. This is specifically and intentionally defined to + /// follow the word size of the host machine for efficiency. We use word_t in + /// places that are aware of this to make it perfectly explicit what is going + /// on. + typedef size_t word_t; word_t CurWord; - /// BitsInCurWord - This is the number of bits in CurWord that are valid. This - /// is always from [0...31/63] inclusive (depending on word size). + /// This is the number of bits in CurWord that are valid. This is always from + /// [0...bits_of(size_t)-1] inclusive. unsigned BitsInCurWord; - // CurCodeSize - This is the declared size of code values used for the current - // block, in bits. + // This is the declared size of code values used for the current block, in + // bits. unsigned CurCodeSize; - /// CurAbbrevs - Abbrevs installed at in this block. - std::vector CurAbbrevs; + /// Abbrevs installed at in this block. + std::vector> CurAbbrevs; struct Block { unsigned PrevCodeSize; - std::vector PrevAbbrevs; + std::vector> PrevAbbrevs; explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} }; - /// BlockScope - This tracks the codesize of parent blocks. + /// This tracks the codesize of parent blocks. SmallVector BlockScope; public: - BitstreamCursor() : BitStream(nullptr), NextChar(0) {} - BitstreamCursor(const BitstreamCursor &RHS) - : BitStream(nullptr), NextChar(0) { - operator=(RHS); - } + BitstreamCursor() { init(nullptr); } - explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { - NextChar = 0; - CurWord = 0; - BitsInCurWord = 0; - CurCodeSize = 2; - } + explicit BitstreamCursor(BitstreamReader &R) { init(&R); } - void init(BitstreamReader &R) { + void init(BitstreamReader *R) { freeState(); - BitStream = &R; + BitStream = R; NextChar = 0; - CurWord = 0; + Size = 0; BitsInCurWord = 0; CurCodeSize = 2; } - ~BitstreamCursor() { - freeState(); - } - - void operator=(const BitstreamCursor &RHS); - void freeState(); - bool isEndPos(size_t pos) { - return BitStream->getBitcodeBytes().isObjectEnd(static_cast(pos)); - } - bool canSkipToPos(size_t pos) const { // pos can be skipped to if it is a valid address or one byte past the end. return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( static_cast(pos - 1)); } - uint32_t getWord(size_t pos) { - uint8_t buf[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; - BitStream->getBitcodeBytes().readBytes(pos, sizeof(buf), buf); - return *reinterpret_cast(buf); - } - bool AtEndOfStream() { - return BitsInCurWord == 0 && isEndPos(NextChar); + if (BitsInCurWord != 0) + return false; + if (Size != 0) + return Size == NextChar; + fillCurWord(); + return BitsInCurWord == 0; } - /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + /// Return the number of bits used to encode an abbrev #. unsigned getAbbrevIDWidth() const { return CurCodeSize; } - /// GetCurrentBitNo - Return the bit # of the bit we are reading. + /// Return the bit # of the bit we are reading. uint64_t GetCurrentBitNo() const { return NextChar*CHAR_BIT - BitsInCurWord; } @@ -268,19 +249,17 @@ public: /// Flags that modify the behavior of advance(). enum { - /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does - /// not automatically pop the block scope when the end of a block is - /// reached. + /// If this flag is used, the advance() method does not automatically pop + /// the block scope when the end of a block is reached. AF_DontPopBlockAtEnd = 1, - /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are - /// returned just like normal records. + /// If this flag is used, abbrev entries are returned just like normal + /// records. AF_DontAutoprocessAbbrevs = 2 }; - /// advance - Advance the current bitstream, returning the next entry in the - /// stream. - BitstreamEntry advance(unsigned Flags = 0) { + /// Advance the current bitstream, returning the next entry in the stream. + BitstreamEntry advance(unsigned Flags = 0) { while (1) { unsigned Code = ReadCode(); if (Code == bitc::END_BLOCK) { @@ -305,8 +284,8 @@ public: } } - /// advanceSkippingSubblocks - This is a convenience function for clients that - /// don't expect any subblocks. This just skips over them automatically. + /// This is a convenience function for clients that don't expect any + /// subblocks. This just skips over them automatically. BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { while (1) { // If we found a normal entry, return it. @@ -320,7 +299,7 @@ public: } } - /// JumpToBit - Reset the stream to the specified bit number. + /// Reset the stream to the specified bit number. void JumpToBit(uint64_t BitNo) { uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); @@ -329,77 +308,74 @@ public: // Move the cursor to the right word. NextChar = ByteNo; BitsInCurWord = 0; - CurWord = 0; // Skip over any bits that are already consumed. - if (WordBitNo) { - if (sizeof(word_t) > 4) - Read64(WordBitNo); - else - Read(WordBitNo); + if (WordBitNo) + Read(WordBitNo); + } + + void fillCurWord() { + assert(Size == 0 || NextChar < (unsigned)Size); + + // Read the next word from the stream. + uint8_t Array[sizeof(word_t)] = {0}; + + uint64_t BytesRead = + BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar); + + // If we run out of data, stop at the end of the stream. + if (BytesRead == 0) { + Size = NextChar; + return; } + + CurWord = + support::endian::read( + Array); + NextChar += BytesRead; + BitsInCurWord = BytesRead * 8; } + word_t Read(unsigned NumBits) { + static const unsigned BitsInWord = sizeof(word_t) * 8; - uint32_t Read(unsigned NumBits) { - assert(NumBits && NumBits <= 32 && - "Cannot return zero or more than 32 bits!"); + assert(NumBits && NumBits <= BitsInWord && + "Cannot return zero or more than BitsInWord bits!"); + + static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f; // If the field is fully contained by CurWord, return it quickly. if (BitsInCurWord >= NumBits) { - uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); - CurWord >>= NumBits; + word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits)); + + // Use a mask to avoid undefined behavior. + CurWord >>= (NumBits & Mask); + BitsInCurWord -= NumBits; return R; } - // If we run out of data, stop at the end of the stream. - if (isEndPos(NextChar)) { - CurWord = 0; - BitsInCurWord = 0; - return 0; - } - - uint32_t R = uint32_t(CurWord); - - // Read the next word from the stream. - uint8_t Array[sizeof(word_t)] = {0}; + word_t R = BitsInCurWord ? CurWord : 0; + unsigned BitsLeft = NumBits - BitsInCurWord; - BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array); + fillCurWord(); - // Handle big-endian byte-swapping if necessary. - support::detail::packed_endian_specific_integral - EndianValue; - memcpy(&EndianValue, Array, sizeof(Array)); + // If we run out of data, stop at the end of the stream. + if (BitsLeft > BitsInCurWord) + return 0; - CurWord = EndianValue; + word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft)); - NextChar += sizeof(word_t); + // Use a mask to avoid undefined behavior. + CurWord >>= (BitsLeft & Mask); - // Extract NumBits-BitsInCurWord from what we just read. - unsigned BitsLeft = NumBits-BitsInCurWord; + BitsInCurWord -= BitsLeft; - // Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive. - R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft))) - << BitsInCurWord); + R |= R2 << (NumBits - BitsLeft); - // BitsLeft bits have just been used up from CurWord. BitsLeft is in the - // range [1..32]/[1..64] so be careful how we shift. - if (BitsLeft != sizeof(word_t)*8) - CurWord >>= BitsLeft; - else - CurWord = 0; - BitsInCurWord = sizeof(word_t)*8-BitsLeft; return R; } - uint64_t Read64(unsigned NumBits) { - if (NumBits <= 32) return Read(NumBits); - - uint64_t V = Read(32); - return V | (uint64_t)Read(NumBits-32) << 32; - } - uint32_t ReadVBR(unsigned NumBits) { uint32_t Piece = Read(NumBits); if ((Piece & (1U << (NumBits-1))) == 0) @@ -418,8 +394,8 @@ public: } } - // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The - // chunk size of the VBR must still be <= 32 bits though. + // Read a VBR that may have a value up to 64-bits in size. The chunk size of + // the VBR must still be <= 32 bits though. uint64_t ReadVBR64(unsigned NumBits) { uint32_t Piece = Read(NumBits); if ((Piece & (1U << (NumBits-1))) == 0) @@ -450,7 +426,6 @@ private: } BitsInCurWord = 0; - CurWord = 0; } public: @@ -462,15 +437,13 @@ public: // Block header: // [ENTER_SUBBLOCK, blockid, newcodelen, , blocklen] - /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for - /// the block. + /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. unsigned ReadSubBlockID() { return ReadVBR(bitc::BlockIDWidth); } - /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip - /// over the body of this block. If the block record is malformed, return - /// true. + /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body + /// of this block. If the block record is malformed, return true. bool SkipBlock() { // Read and ignore the codelen value. Since we are skipping this block, we // don't care what code widths are used inside of it. @@ -488,8 +461,8 @@ public: return false; } - /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter - /// the block, and return true if the block has an error. + /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true + /// if the block has an error. bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); bool ReadBlockEnd() { @@ -508,12 +481,7 @@ private: void popBlockScope() { CurCodeSize = BlockScope.back().PrevCodeSize; - // Delete abbrevs from popped scope. - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs); BlockScope.pop_back(); } @@ -521,23 +489,16 @@ private: // Record Processing //===--------------------------------------------------------------------===// -private: - void readAbbreviatedLiteral(const BitCodeAbbrevOp &Op, - SmallVectorImpl &Vals); - void readAbbreviatedField(const BitCodeAbbrevOp &Op, - SmallVectorImpl &Vals); - void skipAbbreviatedField(const BitCodeAbbrevOp &Op); - public: - /// getAbbrev - Return the abbreviation for the specified AbbrevId. + /// Return the abbreviation for the specified AbbrevId. const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); - return CurAbbrevs[AbbrevNo]; + return CurAbbrevs[AbbrevNo].get(); } - /// skipRecord - Read the current record and discard it. + /// Read the current record and discard it. void skipRecord(unsigned AbbrevID); unsigned readRecord(unsigned AbbrevID, SmallVectorImpl &Vals, diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index dcfebd9..9e2c2fa 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -40,12 +40,12 @@ class BitstreamWriter { unsigned BlockInfoCurBID; /// CurAbbrevs - Abbrevs installed at in this block. - std::vector CurAbbrevs; + std::vector> CurAbbrevs; struct Block { unsigned PrevCodeSize; unsigned StartSizeWord; - std::vector PrevAbbrevs; + std::vector> PrevAbbrevs; Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} }; @@ -56,7 +56,7 @@ class BitstreamWriter { /// These describe abbreviations that all blocks of the specified ID inherit. struct BlockInfo { unsigned BlockID; - std::vector Abbrevs; + std::vector> Abbrevs; }; std::vector BlockInfoRecords; @@ -99,16 +99,6 @@ public: ~BitstreamWriter() { assert(CurBit == 0 && "Unflushed data remaining"); assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); - - // Free the BlockInfoRecords. - while (!BlockInfoRecords.empty()) { - BlockInfo &Info = BlockInfoRecords.back(); - // Free blockinfo abbrev info. - for (unsigned i = 0, e = static_cast(Info.Abbrevs.size()); - i != e; ++i) - Info.Abbrevs[i]->dropRef(); - BlockInfoRecords.pop_back(); - } } /// \brief Retrieve the current position in the stream, in bits. @@ -231,22 +221,13 @@ public: // If there is a blockinfo for this BlockID, add all the predefined abbrevs // to the abbrev list. if (BlockInfo *Info = getBlockInfo(BlockID)) { - for (unsigned i = 0, e = static_cast(Info->Abbrevs.size()); - i != e; ++i) { - CurAbbrevs.push_back(Info->Abbrevs[i]); - Info->Abbrevs[i]->addRef(); - } + CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(), + Info->Abbrevs.end()); } } void ExitBlock() { assert(!BlockScope.empty() && "Block scope imbalance!"); - - // Delete all abbrevs. - for (unsigned i = 0, e = static_cast(CurAbbrevs.size()); - i != e; ++i) - CurAbbrevs[i]->dropRef(); - const Block &B = BlockScope.back(); // Block tail: @@ -263,7 +244,7 @@ public: // Restore the inner block's code size and abbrev table. CurCodeSize = B.PrevCodeSize; - BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + CurAbbrevs = std::move(B.PrevAbbrevs); BlockScope.pop_back(); } @@ -317,7 +298,7 @@ private: unsigned BlobLen = (unsigned) Blob.size(); unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); - BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get(); EmitCode(Abbrev); diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index ee2efa2..043ecd3 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -137,14 +137,14 @@ namespace bitc { enum MetadataCodes { METADATA_STRING = 1, // MDSTRING: [values] - // 2 is unused. - // 3 is unused. + METADATA_VALUE = 2, // VALUE: [type num, value num] + METADATA_NODE = 3, // NODE: [n x md num] METADATA_NAME = 4, // STRING: [values] - // 5 is unused. + METADATA_DISTINCT_NODE = 5, // DISTINCT_NODE: [n x md num] METADATA_KIND = 6, // [n x [id, name]] - // 7 is unused. - METADATA_NODE = 8, // NODE: [n x (type num, value num)] - METADATA_FN_NODE = 9, // FN_NODE: [n x (type num, value num)] + METADATA_LOCATION = 7, // [distinct, line, col, scope, inlined-at?] + METADATA_OLD_NODE = 8, // OLD_NODE: [n x (type num, value num)] + METADATA_OLD_FN_NODE = 9, // OLD_FN_NODE: [n x (type num, value num)] METADATA_NAMED_NODE = 10, // NAMED_NODE: [n x mdnodes] METADATA_ATTACHMENT = 11 // [m x [value, [n x [id, mdnode]]] }; @@ -330,7 +330,8 @@ namespace bitc { }; enum UseListCodes { - USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD. + USELIST_CODE_DEFAULT = 1, // DEFAULT: [index..., value-id] + USELIST_CODE_BB = 2 // BB: [index..., bb-id] }; enum AttributeKindCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 8cf5735..48bdabc 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -14,12 +14,14 @@ #ifndef LLVM_BITCODE_READERWRITER_H #define LLVM_BITCODE_READERWRITER_H +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include #include namespace llvm { class BitstreamWriter; - class MemoryBuffer; class DataStreamer; class LLVMContext; class Module; @@ -27,30 +29,30 @@ namespace llvm { class raw_ostream; /// Read the header of the specified bitcode buffer and prepare for lazy - /// deserialization of function bodies. If successful, this takes ownership - /// of 'buffer. On error, this *does not* take ownership of Buffer. - ErrorOr getLazyBitcodeModule(MemoryBuffer *Buffer, - LLVMContext &Context); - - /// getStreamedBitcodeModule - Read the header of the specified stream - /// and prepare for lazy deserialization and streaming of function bodies. - /// On error, this returns null, and fills in *ErrMsg with an error - /// description if ErrMsg is non-null. - Module *getStreamedBitcodeModule(const std::string &name, - DataStreamer *streamer, - LLVMContext &Context, - std::string *ErrMsg = nullptr); + /// deserialization of function bodies. If successful, this moves Buffer. On + /// error, this *does not* move Buffer. + ErrorOr + getLazyBitcodeModule(std::unique_ptr &&Buffer, + LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + + /// Read the header of the specified stream and prepare for lazy + /// deserialization and streaming of function bodies. + ErrorOr> getStreamedBitcodeModule( + StringRef Name, DataStreamer *Streamer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the header of the specified bitcode buffer and extract just the - /// triple information. If successful, this returns a string and *does not* - /// take ownership of 'buffer'. On error, this returns "". - std::string getBitcodeTargetTriple(MemoryBuffer *Buffer, - LLVMContext &Context); + /// triple information. If successful, this returns a string. On error, this + /// returns "". + std::string + getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// Read the specified bitcode file, returning the module. - /// This method *never* takes ownership of Buffer. - ErrorOr parseBitcodeFile(MemoryBuffer *Buffer, - LLVMContext &Context); + ErrorOr + parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); /// WriteBitcodeToFile - Write the specified module to the specified /// raw output stream. For streams where it matters, the given stream @@ -139,6 +141,32 @@ namespace llvm { BufEnd = BufPtr+Size; return false; } + + const std::error_category &BitcodeErrorCategory(); + enum class BitcodeError { InvalidBitcodeSignature, CorruptedBitcode }; + inline std::error_code make_error_code(BitcodeError E) { + return std::error_code(static_cast(E), BitcodeErrorCategory()); + } + + class BitcodeDiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; + std::error_code EC; + + public: + BitcodeDiagnosticInfo(std::error_code EC, DiagnosticSeverity Severity, + const Twine &Msg); + void print(DiagnosticPrinter &DP) const override; + std::error_code getError() const { return EC; }; + + static bool classof(const DiagnosticInfo *DI) { + return DI->getKind() == DK_Bitcode; + } + }; + } // End llvm namespace +namespace std { +template <> struct is_error_code_enum : std::true_type {}; +} + #endif diff --git a/include/llvm/CMakeLists.txt b/include/llvm/CMakeLists.txt index ca4fd13..ff80539 100644 --- a/include/llvm/CMakeLists.txt +++ b/include/llvm/CMakeLists.txt @@ -1,18 +1,5 @@ add_subdirectory(IR) -if( MSVC_IDE OR XCODE ) - # Creates a dummy target containing all headers for the benefit of - # XCode and Visual Studio users. - file(GLOB_RECURSE headers *.h) - add_td_sources(headers) - add_library(llvm_headers_do_not_build EXCLUDE_FROM_ALL - # We need at least one source file: - ${LLVM_MAIN_SRC_DIR}/lib/Transforms/Hello/Hello.cpp - ${headers}) - set_target_properties(llvm_headers_do_not_build PROPERTIES FOLDER "Misc" - EXCLUDE_FROM_DEFAULT_BUILD ON) -endif() - # If we're doing an out-of-tree build, copy a module map for generated # header files into the build area. if (NOT "${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") diff --git a/include/llvm/CodeGen/Analysis.h b/include/llvm/CodeGen/Analysis.h index b791ba0..c4b94ed 100644 --- a/include/llvm/CodeGen/Analysis.h +++ b/include/llvm/CodeGen/Analysis.h @@ -22,7 +22,7 @@ #include "llvm/IR/Instructions.h" namespace llvm { -class GlobalVariable; +class GlobalValue; class TargetLoweringBase; class TargetLowering; class TargetMachine; @@ -31,10 +31,21 @@ class SDValue; class SelectionDAG; struct EVT; -/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence -/// of insertvalue or extractvalue indices that identify a member, return -/// the linearized index of the start of the member. +/// \brief Compute the linearized index of a member in a nested +/// aggregate/struct/array. /// +/// Given an LLVM IR aggregate type and a sequence of insertvalue or +/// extractvalue indices that identify a member, return the linearized index of +/// the start of the member, i.e the number of element in memory before the +/// seeked one. This is disconnected from the number of bytes. +/// +/// \param Ty is the type indexed by \p Indices. +/// \param Indices is an optional pointer in the indices list to the current +/// index. +/// \param IndicesEnd is the end of the indices list. +/// \param CurIndex is the current index in the recursion. +/// +/// \returns \p CurIndex plus the linear index in \p Ty the indices list. unsigned ComputeLinearIndex(Type *Ty, const unsigned *Indices, const unsigned *IndicesEnd, @@ -59,7 +70,7 @@ void ComputeValueVTs(const TargetLowering &TLI, Type *Ty, uint64_t StartingOffset = 0); /// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V. -GlobalVariable *ExtractTypeInfo(Value *V); +GlobalValue *ExtractTypeInfo(Value *V); /// hasInlineAsmMemConstraint - Return true if the inline asm instruction being /// processed uses a memory 'm' constraint. @@ -97,6 +108,13 @@ bool returnTypeIsEligibleForTailCall(const Function *F, const ReturnInst *Ret, const TargetLoweringBase &TLI); +// True if GV can be left out of the object symbol table. This is the case +// for linkonce_odr values whose address is not significant. While legal, it is +// not normally profitable to omit them from the .o symbol table. Using this +// analysis makes sense when the information can be passed down to the linker +// or we are in LTO. +bool canBeOmittedFromSymbolTable(const GlobalValue *GV); + } // End llvm namespace #endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index e1c9a14..e3ce57a 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -44,6 +44,7 @@ class MachineModuleInfo; class MCAsmInfo; class MCCFIInstruction; class MCContext; +class MCExpr; class MCInst; class MCInstrInfo; class MCSection; @@ -132,6 +133,7 @@ public: virtual ~AsmPrinter(); DwarfDebug *getDwarfDebug() { return DD; } + DwarfDebug *getDwarfDebug() const { return DD; } /// Return true if assembly output should contain comments. /// @@ -203,6 +205,8 @@ public: void emitCFIInstruction(const MachineInstr &MI); + void emitFrameAlloc(const MachineInstr &MI); + enum CFIMoveType { CFI_M_None, CFI_M_EH, CFI_M_Debug }; CFIMoveType needsCFIMoves(); @@ -238,6 +242,9 @@ public: /// alignment (if present) and a comment describing it if appropriate. void EmitBasicBlockStart(const MachineBasicBlock &MBB) const; + /// Lower the specified LLVM Constant to an MCExpr. + const MCExpr *lowerConstant(const Constant *CV); + /// \brief Print a general LLVM constant to the .s file. void EmitGlobalConstant(const Constant *CV); @@ -264,6 +271,9 @@ public: /// function. virtual void EmitFunctionBodyEnd() {} + /// Targets can override this to emit stuff at the end of a basic block. + virtual void EmitBasicBlockEnd(const MachineBasicBlock &MBB) {} + /// Targets should implement this to emit instructions. virtual void EmitInstruction(const MachineInstr *) { llvm_unreachable("EmitInstruction not implemented"); @@ -346,12 +356,6 @@ public: void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const; - /// Emit something like ".long Hi+Offset-Lo" where the size in bytes of the - /// directive is specified by Size and Hi/Lo specify the labels. This - /// implicitly uses .set if it is available. - void EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, - const MCSymbol *Lo, unsigned Size) const; - /// Emit something like ".long Label+Offset" where the size in bytes of the /// directive is specified by Size and Label specifies the label. This /// implicitly uses .set if it is available. @@ -402,6 +406,13 @@ public: /// Get the value for DW_AT_APPLE_isa. Zero if no isa encoding specified. virtual unsigned getISAEncoding() { return 0; } + /// Emit a dwarf register operation for describing + /// - a small value occupying only part of a register or + /// - a register representing only part of a value. + void EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits, + unsigned OffsetInBits = 0) const; + + /// \brief Emit a partial DWARF register operation. /// \param MLoc the register /// \param PieceSize size and @@ -418,7 +429,7 @@ public: unsigned PieceSize = 0, unsigned PieceOffset = 0) const; - /// Emit dwarf register operation. + /// EmitDwarfRegOp - Emit a dwarf register operation. /// \param Indirect whether this is a register-indirect address virtual void EmitDwarfRegOp(ByteStreamer &BS, const MachineLocation &MLoc, bool Indirect) const; @@ -461,6 +472,10 @@ public: unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS); + /// Let the target do anything it needs to do before emitting inlineasm. + /// \p StartInfo - the subtarget info before parsing inline asm + virtual void emitInlineAsmStart(const MCSubtargetInfo &StartInfo) const; + /// Let the target do anything it needs to do after emitting inlineasm. /// This callback can be used restore the original mode in case the /// inlineasm contains directives to switch modes. diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index 0d79b1d..91fb0a9 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -30,8 +30,10 @@ namespace llvm { /// @param UseDefFreq Expected number of executed use and def instructions /// per function call. Derived from block frequencies. /// @param Size Size of live interval as returnexd by getSize() + /// @param NumInstr Number of instructions using this live interval /// - static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size) { + static inline float normalizeSpillWeight(float UseDefFreq, unsigned Size, + unsigned NumInstr) { // The constant 25 instructions is added to avoid depending too much on // accidental SlotIndex gaps for small intervals. The effect is that small // intervals have a spill weight that is mostly proportional to the number @@ -44,7 +46,7 @@ namespace llvm { /// spill weight and allocation hint. class VirtRegAuxInfo { public: - typedef float (*NormalizingFn)(float, unsigned); + typedef float (*NormalizingFn)(float, unsigned, unsigned); private: MachineFunction &MF; diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index abe00a1..dd7703b 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -35,18 +35,18 @@ public: SExt, // The value is sign extended in the location. ZExt, // The value is zero extended in the location. AExt, // The value is extended with undefined upper bits. - BCvt, // The value is bit-converted in the location. - VExt, // The value is vector-widened in the location. - // FIXME: Not implemented yet. Code that uses AExt to mean - // vector-widen should be fixed to use VExt instead. - FPExt, // The floating-point value is fp-extended in the location. - Indirect, // The location contains pointer to the value. SExtUpper, // The value is in the upper bits of the location and should be // sign extended when retrieved. ZExtUpper, // The value is in the upper bits of the location and should be // zero extended when retrieved. - AExtUpper // The value is in the upper bits of the location and should be + AExtUpper, // The value is in the upper bits of the location and should be // extended with undefined upper bits when retrieved. + BCvt, // The value is bit-converted in the location. + VExt, // The value is vector-widened in the location. + // FIXME: Not implemented yet. Code that uses AExt to mean + // vector-widen should be fixed to use VExt instead. + FPExt, // The floating-point value is fp-extended in the location. + Indirect // The location contains pointer to the value. // TODO: a subset of the value is in the location. }; @@ -158,6 +158,16 @@ public: } }; +/// Describes a register that needs to be forwarded from the prologue to a +/// musttail call. +struct ForwardedRegister { + ForwardedRegister(unsigned VReg, MCPhysReg PReg, MVT VT) + : VReg(VReg), PReg(PReg), VT(VT) {} + unsigned VReg; + MCPhysReg PReg; + MVT VT; +}; + /// CCAssignFn - This function assigns a location for Val, updating State to /// reflect the change. It returns 'true' if it failed to handle Val. typedef bool CCAssignFn(unsigned ValNo, MVT ValVT, @@ -184,7 +194,6 @@ private: CallingConv::ID CallingConv; bool IsVarArg; MachineFunction &MF; - const TargetMachine &TM; const TargetRegisterInfo &TRI; SmallVectorImpl &Locs; LLVMContext &Context; @@ -248,15 +257,13 @@ protected: public: CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - const TargetMachine &TM, SmallVectorImpl &locs, - LLVMContext &C); + SmallVectorImpl &locs, LLVMContext &C); void addLoc(const CCValAssign &V) { Locs.push_back(V); } LLVMContext &getContext() const { return Context; } - const TargetMachine &getTarget() const { return TM; } MachineFunction &getMachineFunction() const { return MF; } CallingConv::ID getCallingConv() const { return CallingConv; } bool isVarArg() const { return IsVarArg; } @@ -348,8 +355,12 @@ public: /// AllocateRegBlock - Attempt to allocate a block of RegsRequired consecutive /// registers. If this is not possible, return zero. Otherwise, return the first /// register of the block that were allocated, marking the entire block as allocated. - unsigned AllocateRegBlock(const uint16_t *Regs, unsigned NumRegs, unsigned RegsRequired) { - for (unsigned StartIdx = 0; StartIdx <= NumRegs - RegsRequired; ++StartIdx) { + unsigned AllocateRegBlock(ArrayRef Regs, unsigned RegsRequired) { + if (RegsRequired > Regs.size()) + return 0; + + for (unsigned StartIdx = 0; StartIdx <= Regs.size() - RegsRequired; + ++StartIdx) { bool BlockAvailable = true; // Check for already-allocated regs in this block for (unsigned BlockIdx = 0; BlockIdx < RegsRequired; ++BlockIdx) { @@ -387,8 +398,8 @@ public: /// AllocateStack - Allocate a chunk of stack space with the specified size /// and alignment. unsigned AllocateStack(unsigned Size, unsigned Align) { - assert(Align && ((Align-1) & Align) == 0); // Align is power of 2. - StackOffset = ((StackOffset + Align-1) & ~(Align-1)); + assert(Align && ((Align - 1) & Align) == 0); // Align is power of 2. + StackOffset = ((StackOffset + Align - 1) & ~(Align - 1)); unsigned Result = StackOffset; StackOffset += Size; MF.getFrameInfo()->ensureMaxAlignment(Align); @@ -469,6 +480,19 @@ public: return PendingLocs; } + /// Compute the remaining unused register parameters that would be used for + /// the given value type. This is useful when varargs are passed in the + /// registers that normal prototyped parameters would be passed in, or for + /// implementing perfect forwarding. + void getRemainingRegParmsForType(SmallVectorImpl &Regs, MVT VT, + CCAssignFn Fn); + + /// Compute the set of registers that need to be preserved and forwarded to + /// any musttail calls. + void analyzeMustTailForwardedRegisters( + SmallVectorImpl &Forwards, ArrayRef RegParmTypes, + CCAssignFn Fn); + private: /// MarkAllocated - Mark a register and all of its aliases as allocated. void MarkAllocated(unsigned Reg); diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 449d934..973c595 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -54,6 +54,16 @@ RelocModel("relocation-model", "Relocatable external references, non-relocatable code"), clEnumValEnd)); +cl::opt +TMModel("thread-model", + cl::desc("Choose threading model"), + cl::init(ThreadModel::POSIX), + cl::values(clEnumValN(ThreadModel::POSIX, "posix", + "POSIX thread model"), + clEnumValN(ThreadModel::Single, "single", + "Single thread model"), + clEnumValEnd)); + cl::opt CMModel("code-model", cl::desc("Choose code model"), @@ -83,11 +93,6 @@ FileType("filetype", cl::init(TargetMachine::CGFT_AssemblyFile), clEnumValEnd)); cl::opt -DisableRedZone("disable-red-zone", - cl::desc("Do not emit code that uses the red zone."), - cl::init(false)); - -cl::opt EnableFPMAD("enable-fp-mad", cl::desc("Enable less precise MAD instructions to be generated"), cl::init(false)); @@ -180,8 +185,8 @@ EnablePIE("enable-pie", cl::init(false)); cl::opt -UseInitArray("use-init-array", - cl::desc("Use .init_array instead of .ctors."), +UseCtors("use-ctors", + cl::desc("Use .ctors instead of .init_array."), cl::init(false)); cl::opt StopAfter("stop-after", @@ -217,6 +222,44 @@ JTableType("jump-table-type", "Create one table per unique function type."), clEnumValEnd)); +cl::opt +FCFI("fcfi", + cl::desc("Apply forward-edge control-flow integrity"), + cl::init(false)); + +cl::opt +CFIType("cfi-type", + cl::desc("Choose the type of Control-Flow Integrity check to add"), + cl::init(CFIntegrity::Sub), + cl::values( + clEnumValN(CFIntegrity::Sub, "sub", + "Subtract the pointer from the table base, then mask."), + clEnumValN(CFIntegrity::Ror, "ror", + "Use rotate to check the offset from a table base."), + clEnumValN(CFIntegrity::Add, "add", + "Mask out the high bits and add to an aligned base."), + clEnumValEnd)); + +cl::opt +CFIEnforcing("cfi-enforcing", + cl::desc("Enforce CFI or pass the violation to a function."), + cl::init(false)); + +// Note that this option is linked to the cfi-enforcing option above: if +// cfi-enforcing is set, then the cfi-func-name option is entirely ignored. If +// cfi-enforcing is false and no cfi-func-name is set, then a default function +// will be generated that ignores all CFI violations. The expected signature for +// functions called with CFI violations is +// +// void (i8*, i8*) +// +// The first pointer is a C string containing the name of the function in which +// the violation occurs, and the second pointer is the pointer that violated +// CFI. +cl::opt +CFIFuncName("cfi-func-name", cl::desc("The name of the CFI function to call"), + cl::init("")); + // Common utility function tightly tied to the options listed here. Initializes // a TargetOptions object with CodeGen flags and returns it. static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { @@ -238,12 +281,18 @@ static inline TargetOptions InitTargetOptionsFromCodeGenFlags() { Options.StackAlignmentOverride = OverrideStackAlignment; Options.TrapFuncName = TrapFuncName; Options.PositionIndependentExecutable = EnablePIE; - Options.UseInitArray = UseInitArray; + Options.UseInitArray = !UseCtors; Options.DataSections = DataSections; Options.FunctionSections = FunctionSections; Options.MCOptions = InitMCTargetOptionsFromFlags(); Options.JTType = JTableType; + Options.FCFI = FCFI; + Options.CFIType = CFIType; + Options.CFIEnforcing = CFIEnforcing; + Options.CFIFuncName = CFIFuncName; + + Options.ThreadModel = TMModel; return Options; } diff --git a/include/llvm/CodeGen/DFAPacketizer.h b/include/llvm/CodeGen/DFAPacketizer.h index 9d25fd3..f9cdc2a 100644 --- a/include/llvm/CodeGen/DFAPacketizer.h +++ b/include/llvm/CodeGen/DFAPacketizer.h @@ -91,7 +91,6 @@ public: // API call is made to prune the dependence. class VLIWPacketizerList { protected: - const TargetMachine &TM; const MachineFunction &MF; const TargetInstrInfo *TII; @@ -107,9 +106,7 @@ protected: std::map MIToSUnit; public: - VLIWPacketizerList( - MachineFunction &MF, MachineLoopInfo &MLI, MachineDominatorTree &MDT, - bool IsPostRA); + VLIWPacketizerList(MachineFunction &MF, MachineLoopInfo &MLI, bool IsPostRA); virtual ~VLIWPacketizerList(); diff --git a/include/llvm/CodeGen/DIE.h b/include/llvm/CodeGen/DIE.h new file mode 100644 index 0000000..e310aef --- /dev/null +++ b/include/llvm/CodeGen/DIE.h @@ -0,0 +1,587 @@ +//===--- lib/CodeGen/DIE.h - DWARF Info Entries -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures for DWARF info entries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Dwarf.h" +#include + +namespace llvm { +class AsmPrinter; +class MCExpr; +class MCSymbol; +class raw_ostream; +class DwarfTypeUnit; + +//===--------------------------------------------------------------------===// +/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a +/// Dwarf abbreviation. +class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + dwarf::Attribute Attribute; + + /// Form - Dwarf form code. + /// + dwarf::Form Form; + +public: + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + + // Accessors. + dwarf::Attribute getAttribute() const { return Attribute; } + dwarf::Form getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +//===--------------------------------------------------------------------===// +/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug +/// information object. +class DIEAbbrev : public FoldingSetNode { + /// Unique number for node. + /// + unsigned Number; + + /// Tag - Dwarf tag code. + /// + dwarf::Tag Tag; + + /// Children - Whether or not this node has children. + /// + // This cheats a bit in all of the uses since the values in the standard + // are 0 and 1 for no children and children respectively. + bool Children; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector Data; + +public: + DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {} + + // Accessors. + dwarf::Tag getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + bool hasChildren() const { return Children; } + const SmallVectorImpl &getData() const { return Data; } + void setChildrenFlag(bool hasChild) { Children = hasChild; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(AsmPrinter *AP) const; + +#ifndef NDEBUG + void print(raw_ostream &O); + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIE - A structured debug information entry. Has an abbreviation which +/// describes its organization. +class DIEValue; + +class DIE { +protected: + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Children DIEs. + /// + // This can't be a vector because pointer validity is requirent for the + // Parent pointer and DIEEntry. + // It can't be a list because some clients need pointer validity before + // the object has been added to any child list + // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may + // be more convoluted than beneficial. + std::vector> Children; + + DIE *Parent; + + /// Attribute values. + /// + SmallVector Values; + +protected: + DIE() + : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + +public: + explicit DIE(dwarf::Tag Tag) + : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + const DIEAbbrev &getAbbrev() const { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + dwarf::Tag getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector> &getChildren() const { + return Children; + } + const SmallVectorImpl &getValues() const { return Values; } + DIE *getParent() const { return Parent; } + /// Climb up the parent chain to get the compile or type unit DIE this DIE + /// belongs to. + const DIE *getUnit() const; + /// Similar to getUnit, returns null when DIE is not added to an + /// owner yet. + const DIE *getUnitOrNull() const; + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// addChild - Add a child to the DIE. + /// + void addChild(std::unique_ptr Child) { + assert(!Child->getParent()); + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Child->Parent = this; + Children.push_back(std::move(Child)); + } + + /// findAttribute - Find a value in the DIE with the attribute given, + /// returns NULL if no such attribute exists. + DIEValue *findAttribute(dwarf::Attribute Attribute) const; + +#ifndef NDEBUG + void print(raw_ostream &O, unsigned IndentCount = 0) const; + void dump(); +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. Some of these roughly correlate +/// to DWARF attribute classes. +/// +class DIEValue { + virtual void anchor(); + +public: + enum Type { + isInteger, + isString, + isExpr, + isLabel, + isDelta, + isEntry, + isTypeSignature, + isBlock, + isLoc, + isLocList, + }; + +protected: + /// Ty - Type of data stored in the value. + /// + Type Ty; + + explicit DIEValue(Type T) : Ty(T) {} + virtual ~DIEValue() {} + +public: + // Accessors + Type getType() const { return Ty; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; + +#ifndef NDEBUG + virtual void print(raw_ostream &O) const = 0; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEInteger - An integer value DIE. +/// +class DIEInteger : public DIEValue { + uint64_t Integer; + +public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + const int64_t SignedInt = Int; + if ((char)Int == SignedInt) + return dwarf::DW_FORM_data1; + if ((short)Int == SignedInt) + return dwarf::DW_FORM_data2; + if ((int)Int == SignedInt) + return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) + return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) + return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) + return dwarf::DW_FORM_data4; + } + return dwarf::DW_FORM_data8; + } + + /// EmitValue - Emit integer of appropriate size. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + uint64_t getValue() const { return Integer; } + + /// SizeOf - Determine size of integer value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEExpr - An expression DIE. +// +class DIEExpr : public DIEValue { + const MCExpr *Expr; + +public: + explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} + + /// EmitValue - Emit expression value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCExpr. + /// + const MCExpr *getValue() const { return Expr; } + + /// SizeOf - Determine size of expression value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isExpr; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELabel - A label DIE. +// +class DIELabel : public DIEValue { + const MCSymbol *Label; + +public: + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} + + /// EmitValue - Emit label value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// getValue - Get MCSymbol. + /// + const MCSymbol *getValue() const { return Label; } + + /// SizeOf - Determine size of label value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEDelta - A simple label difference DIE. +/// +class DIEDelta : public DIEValue { + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; + +public: + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) + : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEString - A container for string values. +/// +class DIEString : public DIEValue { + const DIEValue *Access; + StringRef Str; + +public: + DIEString(const DIEValue *Acc, StringRef S) + : DIEValue(isString), Access(Acc), Str(S) {} + + /// getString - Grab the string out of the object. + StringRef getString() const { return Str; } + + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isString; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEEntry - A pointer to another debug information entry. An instance of +/// this class can also be used as a proxy for a debug information entry not +/// yet defined (ie. types.) +class DIEEntry : public DIEValue { + DIE &Entry; + +public: + explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { + } + + DIE &getEntry() const { return Entry; } + + /// EmitValue - Emit debug information entry offset. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of debug information entry in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) + : sizeof(int32_t); + } + + /// Returns size of a ref_addr entry. + static unsigned getRefAddrSize(AsmPrinter *AP); + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// \brief A signature reference to a type unit. +class DIETypeSignature : public DIEValue { + const DwarfTypeUnit &Unit; + +public: + explicit DIETypeSignature(const DwarfTypeUnit &Unit) + : DIEValue(isTypeSignature), Unit(Unit) {} + + /// \brief Emit type unit signature. + void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override; + + /// Returns size of a ref_sig8 entry. + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + assert(Form == dwarf::DW_FORM_ref_sig8); + return 8; + } + + // \brief Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { + return E->getType() == isTypeSignature; + } +#ifndef NDEBUG + void print(raw_ostream &O) const override; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELoc - Represents an expression location. +// +class DIELoc : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIELoc() : DIEValue(isLoc), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm(unsigned DwarfVersion) const { + if (DwarfVersion > 3) + return dwarf::DW_FORM_exprloc; + // Pre-DWARF4 location expressions were blocks and not exprloc. + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLoc; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIEBlock - Represents a block of values. +// +class DIEBlock : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIEBlock() : DIEValue(isBlock), Size(0) {} + + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; + + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm() const { + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELocList - Represents a pointer to a location list in the debug_loc +/// section. +// +class DIELocList : public DIEValue { + // Index into the .debug_loc vector. + size_t Index; + +public: + DIELocList(size_t I) : DIEValue(isLocList), Index(I) {} + + /// getValue - Grab the current index out. + size_t getValue() const { return Index; } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLocList; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 0d1b1dc..1dca2ce 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -18,72 +18,52 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/Target/TargetLowering.h" #include "llvm/IR/CallingConv.h" +#include "llvm/IR/IntrinsicInst.h" +#include "llvm/Target/TargetLowering.h" namespace llvm { -class AllocaInst; -class Constant; -class ConstantFP; -class CallInst; -class DataLayout; -class FunctionLoweringInfo; -class Instruction; -class IntrinsicInst; -class LoadInst; -class MVT; -class MachineConstantPool; -class MachineFrameInfo; -class MachineFunction; -class MachineInstr; -class MachineRegisterInfo; -class TargetInstrInfo; -class TargetLibraryInfo; -class TargetLowering; -class TargetMachine; -class TargetRegisterClass; -class TargetRegisterInfo; -class User; -class Value; - -/// This is a fast-path instruction selection class that generates poor code and -/// doesn't support illegal types or non-trivial lowering, but runs quickly. +/// \brief This is a fast-path instruction selection class that generates poor +/// code and doesn't support illegal types or non-trivial lowering, but runs +/// quickly. class FastISel { - public: +public: struct ArgListEntry { Value *Val; Type *Ty; - bool isSExt : 1; - bool isZExt : 1; - bool isInReg : 1; - bool isSRet : 1; - bool isNest : 1; - bool isByVal : 1; - bool isInAlloca : 1; - bool isReturned : 1; + bool IsSExt : 1; + bool IsZExt : 1; + bool IsInReg : 1; + bool IsSRet : 1; + bool IsNest : 1; + bool IsByVal : 1; + bool IsInAlloca : 1; + bool IsReturned : 1; uint16_t Alignment; ArgListEntry() - : Val(nullptr), Ty(nullptr), isSExt(false), isZExt(false), isInReg(false), - isSRet(false), isNest(false), isByVal(false), isInAlloca(false), - isReturned(false), Alignment(0) { } + : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false), + IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false), + IsInAlloca(false), IsReturned(false), Alignment(0) {} + /// \brief Set CallLoweringInfo attribute flags based on a call instruction + /// and called function attributes. void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); }; typedef std::vector ArgListTy; struct CallLoweringInfo { Type *RetTy; - bool RetSExt : 1; - bool RetZExt : 1; - bool IsVarArg : 1; - bool IsInReg : 1; - bool DoesNotReturn : 1; + bool RetSExt : 1; + bool RetZExt : 1; + bool IsVarArg : 1; + bool IsInReg : 1; + bool DoesNotReturn : 1; bool IsReturnValueUsed : 1; - // IsTailCall should be modified by implementations of - // FastLowerCall that perform tail call conversions. + // \brief IsTailCall Should be modified by implementations of FastLowerCall + // that perform tail call conversions. bool IsTailCall; unsigned NumFixedArgs; @@ -96,6 +76,8 @@ class FastISel { unsigned ResultReg; unsigned NumResultRegs; + bool IsPatchPoint; + SmallVector OutVals; SmallVector OutFlags; SmallVector OutRegs; @@ -103,12 +85,11 @@ class FastISel { SmallVector InRegs; CallLoweringInfo() - : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), - IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), - IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), - Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), - ResultReg(0), NumResultRegs(0) - {} + : RetTy(nullptr), RetSExt(false), RetZExt(false), IsVarArg(false), + IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), + IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), + Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), + ResultReg(0), NumResultRegs(0), IsPatchPoint(false) {} CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, const Value *Target, ArgListTy &&ArgsList, @@ -124,8 +105,8 @@ class FastISel { RetZExt = Call.paramHasAttr(0, Attribute::ZExt); CallConv = Call.getCallingConv(); - NumFixedArgs = FuncTy->getNumParams(); Args = std::move(ArgsList); + NumFixedArgs = FuncTy->getNumParams(); CS = &Call; @@ -148,8 +129,8 @@ class FastISel { RetZExt = Call.paramHasAttr(0, Attribute::ZExt); CallConv = Call.getCallingConv(); - NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs; Args = std::move(ArgsList); + NumFixedArgs = (FixedArgs == ~0U) ? FuncTy->getNumParams() : FixedArgs; CS = &Call; @@ -162,8 +143,19 @@ class FastISel { RetTy = ResultTy; Callee = Target; CallConv = CC; + Args = std::move(ArgsList); NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; + return *this; + } + + CallLoweringInfo &setCallee(CallingConv::ID CC, Type *ResultTy, + const char *Target, ArgListTy &&ArgsList, + unsigned FixedArgs = ~0U) { + RetTy = ResultTy; + SymName = Target; + CallConv = CC; Args = std::move(ArgsList); + NumFixedArgs = (FixedArgs == ~0U) ? Args.size() : FixedArgs; return *this; } @@ -172,10 +164,13 @@ class FastISel { return *this; } - ArgListTy &getArgs() { - return Args; + CallLoweringInfo &setIsPatchPoint(bool Value = true) { + IsPatchPoint = Value; + return *this; } + ArgListTy &getArgs() { return Args; } + void clearOuts() { OutVals.clear(); OutFlags.clear(); @@ -202,61 +197,64 @@ protected: const TargetLowering &TLI; const TargetRegisterInfo &TRI; const TargetLibraryInfo *LibInfo; + bool SkipTargetIndependentISel; - /// The position of the last instruction for materializing constants for use - /// in the current block. It resets to EmitStartPt when it makes sense (for - /// example, it's usually profitable to avoid function calls between the + /// \brief The position of the last instruction for materializing constants + /// for use in the current block. It resets to EmitStartPt when it makes sense + /// (for example, it's usually profitable to avoid function calls between the /// definition and the use) MachineInstr *LastLocalValue; - /// The top most instruction in the current block that is allowed for emitting - /// local variables. LastLocalValue resets to EmitStartPt when it makes sense - /// (for example, on function calls) + /// \brief The top most instruction in the current block that is allowed for + /// emitting local variables. LastLocalValue resets to EmitStartPt when it + /// makes sense (for example, on function calls) MachineInstr *EmitStartPt; public: - /// Return the position of the last instruction emitted for materializing - /// constants for use in the current block. + /// \brief Return the position of the last instruction emitted for + /// materializing constants for use in the current block. MachineInstr *getLastLocalValue() { return LastLocalValue; } - /// Update the position of the last instruction emitted for materializing - /// constants for use in the current block. + /// \brief Update the position of the last instruction emitted for + /// materializing constants for use in the current block. void setLastLocalValue(MachineInstr *I) { EmitStartPt = I; LastLocalValue = I; } - /// Set the current block to which generated machine instructions will be - /// appended, and clear the local CSE map. + /// \brief Set the current block to which generated machine instructions will + /// be appended, and clear the local CSE map. void startNewBlock(); - /// Return current debug location information. + /// \brief Return current debug location information. DebugLoc getCurDebugLoc() const { return DbgLoc; } - - /// Do "fast" instruction selection for function arguments and append machine - /// instructions to the current block. Return true if it is successful. - bool LowerArguments(); - /// Do "fast" instruction selection for the given LLVM IR instruction, and - /// append generated machine instructions to the current block. Return true if - /// selection was successful. - bool SelectInstruction(const Instruction *I); + /// \brief Do "fast" instruction selection for function arguments and append + /// the machine instructions to the current block. Returns true when + /// successful. + bool lowerArguments(); - /// Do "fast" instruction selection for the given LLVM IR operator + /// \brief Do "fast" instruction selection for the given LLVM IR instruction + /// and append the generated machine instructions to the current block. + /// Returns true if selection was successful. + bool selectInstruction(const Instruction *I); + + /// \brief Do "fast" instruction selection for the given LLVM IR operator /// (Instruction or ConstantExpr), and append generated machine instructions /// to the current block. Return true if selection was successful. - bool SelectOperator(const User *I, unsigned Opcode); + bool selectOperator(const User *I, unsigned Opcode); - /// Create a virtual register and arrange for it to be assigned the value for - /// the given LLVM value. + /// \brief Create a virtual register and arrange for it to be assigned the + /// value for the given LLVM value. unsigned getRegForValue(const Value *V); - /// Look up the value to see if its value is already cached in a register. It - /// may be defined by instructions across blocks or defined locally. + /// \brief Look up the value to see if its value is already cached in a + /// register. It may be defined by instructions across blocks or defined + /// locally. unsigned lookUpRegForValue(const Value *V); - /// This is a wrapper around getRegForValue that also takes care of truncating - /// or sign-extending the given getelementptr index value. + /// \brief This is a wrapper around getRegForValue that also takes care of + /// truncating or sign-extending the given getelementptr index value. std::pair getRegForGEPIndex(const Value *V); /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note @@ -284,11 +282,11 @@ public: return false; } - /// Reset InsertPt to prepare for inserting instructions into the current - /// block. + /// \brief Reset InsertPt to prepare for inserting instructions into the + /// current block. void recomputeInsertPt(); - /// Remove all dead instructions between the I and E. + /// \brief Remove all dead instructions between the I and E. void removeDeadCode(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E); @@ -297,221 +295,195 @@ public: DebugLoc DL; }; - /// Prepare InsertPt to begin inserting instructions into the local value area - /// and return the old insert position. + /// \brief Prepare InsertPt to begin inserting instructions into the local + /// value area and return the old insert position. SavePoint enterLocalValueArea(); - /// Reset InsertPt to the given old insert position. + /// \brief Reset InsertPt to the given old insert position. void leaveLocalValueArea(SavePoint Old); virtual ~FastISel(); protected: - explicit FastISel(FunctionLoweringInfo &funcInfo, - const TargetLibraryInfo *libInfo); - - /// This method is called by target-independent code when the normal FastISel - /// process fails to select an instruction. This gives targets a chance to - /// emit code for anything that doesn't fit into FastISel's framework. It - /// returns true if it was successful. - virtual bool TargetSelectInstruction(const Instruction *I) = 0; - - /// This method is called by target-independent code to do target specific - /// argument lowering. It returns true if it was successful. - virtual bool FastLowerArguments(); - - /// \brief This method is called by target-independent code to do target + explicit FastISel(FunctionLoweringInfo &FuncInfo, + const TargetLibraryInfo *LibInfo, + bool SkipTargetIndependentISel = false); + + /// \brief This method is called by target-independent code when the normal + /// FastISel process fails to select an instruction. This gives targets a + /// chance to emit code for anything that doesn't fit into FastISel's + /// framework. It returns true if it was successful. + virtual bool fastSelectInstruction(const Instruction *I) = 0; + + /// \brief This method is called by target-independent code to do target- + /// specific argument lowering. It returns true if it was successful. + virtual bool fastLowerArguments(); + + /// \brief This method is called by target-independent code to do target- /// specific call lowering. It returns true if it was successful. - virtual bool FastLowerCall(CallLoweringInfo &CLI); + virtual bool fastLowerCall(CallLoweringInfo &CLI); - /// \brief This method is called by target-independent code to do target + /// \brief This method is called by target-independent code to do target- /// specific intrinsic lowering. It returns true if it was successful. - virtual bool FastLowerIntrinsicCall(const IntrinsicInst *II); + virtual bool fastLowerIntrinsicCall(const IntrinsicInst *II); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type and opcode be emitted. - virtual unsigned FastEmit_(MVT VT, - MVT RetVT, - unsigned Opcode); + virtual unsigned fastEmit_(MVT VT, MVT RetVT, unsigned Opcode); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register operand be emitted. - virtual unsigned FastEmit_r(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill); + virtual unsigned fastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register operands be emitted. - virtual unsigned FastEmit_rr(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill); + virtual unsigned fastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register and immediate - /// operands be emitted. - virtual unsigned FastEmit_ri(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - uint64_t Imm); + // operands be emitted. + virtual unsigned fastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill, uint64_t Imm); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register and floating-point /// immediate operands be emitted. - virtual unsigned FastEmit_rf(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - const ConstantFP *FPImm); + virtual unsigned fastEmit_rf(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, + bool Op0IsKill, const ConstantFP *FPImm); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and register and immediate /// operands be emitted. - virtual unsigned FastEmit_rri(MVT VT, - MVT RetVT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, - uint64_t Imm); - - /// \brief This method is a wrapper of FastEmit_ri. - /// + virtual unsigned fastEmit_rri(MVT VT, MVT RetVT, unsigned Opcode, + unsigned Op0, bool Op0IsKill, unsigned Op1, + bool Op1IsKill, uint64_t Imm); + + /// \brief This method is a wrapper of fastEmit_ri. + /// /// It first tries to emit an instruction with an immediate operand using - /// FastEmit_ri. If that fails, it materializes the immediate into a register - /// and try FastEmit_rr instead. - unsigned FastEmit_ri_(MVT VT, - unsigned Opcode, - unsigned Op0, bool Op0IsKill, + /// fastEmit_ri. If that fails, it materializes the immediate into a register + /// and try fastEmit_rr instead. + unsigned fastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm, MVT ImmType); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and immediate operand be emitted. - virtual unsigned FastEmit_i(MVT VT, - MVT RetVT, - unsigned Opcode, - uint64_t Imm); + virtual unsigned fastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm); - /// This method is called by target-independent code to request that an + /// \brief This method is called by target-independent code to request that an /// instruction with the given type, opcode, and floating-point immediate /// operand be emitted. - virtual unsigned FastEmit_f(MVT VT, - MVT RetVT, - unsigned Opcode, + virtual unsigned fastEmit_f(MVT VT, MVT RetVT, unsigned Opcode, const ConstantFP *FPImm); - /// Emit a MachineInstr with no operands and a result register in the given - /// register class. - unsigned FastEmitInst_(unsigned MachineInstOpcode, + /// \brief Emit a MachineInstr with no operands and a result register in the + /// given register class. + unsigned fastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass *RC); - /// Emit a MachineInstr with one register operand and a result register in the - /// given register class. - unsigned FastEmitInst_r(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill); - - /// Emit a MachineInstr with two register operands and a result register in - /// the given register class. - unsigned FastEmitInst_rr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill); - - /// Emit a MachineInstr with three register operands and a result register in - /// the given register class. - unsigned FastEmitInst_rrr(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, - unsigned Op2, bool Op2IsKill); - - /// Emit a MachineInstr with a register operand, an immediate, and a result + /// \brief Emit a MachineInstr with one register operand and a result register + /// in the given register class. + unsigned fastEmitInst_r(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill); + + /// \brief Emit a MachineInstr with two register operands and a result + /// register in the given register class. + unsigned fastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill); + + /// \brief Emit a MachineInstr with three register operands and a result /// register in the given register class. - unsigned FastEmitInst_ri(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - uint64_t Imm); - - /// Emit a MachineInstr with one register operand and two immediate operands. - unsigned FastEmitInst_rii(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - uint64_t Imm1, uint64_t Imm2); - - /// Emit a MachineInstr with two register operands and a result register in - /// the given register class. - unsigned FastEmitInst_rf(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - const ConstantFP *FPImm); - - /// Emit a MachineInstr with two register operands, an immediate, and a result + unsigned fastEmitInst_rrr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill, + unsigned Op2, bool Op2IsKill); + + /// \brief Emit a MachineInstr with a register operand, an immediate, and a + /// result register in the given register class. + unsigned fastEmitInst_ri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, uint64_t Imm); + + /// \brief Emit a MachineInstr with one register operand and two immediate + /// operands. + unsigned fastEmitInst_rii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, uint64_t Imm1, uint64_t Imm2); + + /// \brief Emit a MachineInstr with two register operands and a result /// register in the given register class. - unsigned FastEmitInst_rri(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, + unsigned fastEmitInst_rf(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, const ConstantFP *FPImm); + + /// \brief Emit a MachineInstr with two register operands, an immediate, and a + /// result register in the given register class. + unsigned fastEmitInst_rri(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm); - /// Emit a MachineInstr with two register operands, two immediates operands, - /// and a result register in the given register class. - unsigned FastEmitInst_rrii(unsigned MachineInstOpcode, - const TargetRegisterClass *RC, - unsigned Op0, bool Op0IsKill, - unsigned Op1, bool Op1IsKill, + /// \brief Emit a MachineInstr with two register operands, two immediates + /// operands, and a result register in the given register class. + unsigned fastEmitInst_rrii(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, unsigned Op0, + bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm1, uint64_t Imm2); - /// Emit a MachineInstr with a single immediate operand, and a result register - /// in the given register class. - unsigned FastEmitInst_i(unsigned MachineInstrOpcode, - const TargetRegisterClass *RC, - uint64_t Imm); - - /// Emit a MachineInstr with a two immediate operands. - unsigned FastEmitInst_ii(unsigned MachineInstrOpcode, - const TargetRegisterClass *RC, - uint64_t Imm1, uint64_t Imm2); - - /// Emit a MachineInstr for an extract_subreg from a specified index of a - /// superregister to a specified type. - unsigned FastEmitInst_extractsubreg(MVT RetVT, - unsigned Op0, bool Op0IsKill, + /// \brief Emit a MachineInstr with a single immediate operand, and a result + /// register in the given register class. + unsigned fastEmitInst_i(unsigned MachineInstrOpcode, + const TargetRegisterClass *RC, uint64_t Imm); + + /// \brief Emit a MachineInstr with a two immediate operands. + unsigned fastEmitInst_ii(unsigned MachineInstrOpcode, + const TargetRegisterClass *RC, uint64_t Imm1, + uint64_t Imm2); + + /// \brief Emit a MachineInstr for an extract_subreg from a specified index of + /// a superregister to a specified type. + unsigned fastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx); - /// Emit MachineInstrs to compute the value of Op with all but the least - /// significant bit set to zero. - unsigned FastEmitZExtFromI1(MVT VT, - unsigned Op0, bool Op0IsKill); + /// \brief Emit MachineInstrs to compute the value of Op with all but the + /// least significant bit set to zero. + unsigned fastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill); - /// Emit an unconditional branch to the given block, unless it is the + /// \brief Emit an unconditional branch to the given block, unless it is the /// immediate (fall-through) successor, and update the CFG. - void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); + void fastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); - void UpdateValueMap(const Value* I, unsigned Reg, unsigned NumRegs = 1); + /// \brief Update the value map to include the new mapping for this + /// instruction, or insert an extra copy to get the result in a previous + /// determined register. + /// + /// NOTE: This is only necessary because we might select a block that uses a + /// value before we select the block that defines the value. It might be + /// possible to fix this by selecting blocks in reverse postorder. + void updateValueMap(const Value *I, unsigned Reg, unsigned NumRegs = 1); unsigned createResultReg(const TargetRegisterClass *RC); - /// Try to constrain Op so that it is usable by argument OpNum of the provided - /// MCInstrDesc. If this fails, create a new virtual register in the correct - /// class and COPY the value there. + /// \brief Try to constrain Op so that it is usable by argument OpNum of the + /// provided MCInstrDesc. If this fails, create a new virtual register in the + /// correct class and COPY the value there. unsigned constrainOperandRegClass(const MCInstrDesc &II, unsigned Op, unsigned OpNum); - /// Emit a constant in a register using target-specific logic, such as + /// \brief Emit a constant in a register using target-specific logic, such as /// constant pool loads. - virtual unsigned TargetMaterializeConstant(const Constant* C) { - return 0; - } + virtual unsigned fastMaterializeConstant(const Constant *C) { return 0; } - /// Emit an alloca address in a register using target-specific logic. - virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) { - return 0; - } + /// \brief Emit an alloca address in a register using target-specific logic. + virtual unsigned fastMaterializeAlloca(const AllocaInst *C) { return 0; } - virtual unsigned TargetMaterializeFloatZero(const ConstantFP* CF) { + /// \brief Emit the floating-point constant +0.0 in a register using target- + /// specific logic. + virtual unsigned fastMaterializeFloatZero(const ConstantFP *CF) { return 0; } @@ -524,36 +496,46 @@ protected: /// - \c Add has a constant operand. bool canFoldAddIntoGEP(const User *GEP, const Value *Add); - /// Test whether the given value has exactly one use. - bool hasTrivialKill(const Value *V) const; + /// \brief Test whether the given value has exactly one use. + bool hasTrivialKill(const Value *V); /// \brief Create a machine mem operand from the given instruction. MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const; - bool LowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); - bool LowerCallTo(CallLoweringInfo &CLI); - -private: - bool SelectBinaryOp(const User *I, unsigned ISDOpcode); - - bool SelectFNeg(const User *I); - - bool SelectGetElementPtr(const User *I); + CmpInst::Predicate optimizeCmpPredicate(const CmpInst *CI) const; - bool SelectStackmap(const CallInst *I); - bool SelectPatchpoint(const CallInst *I); - bool LowerCall(const CallInst *I); - bool SelectCall(const User *Call); - bool SelectIntrinsicCall(const IntrinsicInst *II); + bool lowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); + bool lowerCallTo(CallLoweringInfo &CLI); - bool SelectBitCast(const User *I); - - bool SelectCast(const User *I, unsigned Opcode); + bool isCommutativeIntrinsic(IntrinsicInst const *II) { + switch (II->getIntrinsicID()) { + case Intrinsic::sadd_with_overflow: + case Intrinsic::uadd_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::umul_with_overflow: + return true; + default: + return false; + } + } - bool SelectExtractValue(const User *I); - bool SelectInsertValue(const User *I); + bool lowerCall(const CallInst *I); + /// \brief Select and emit code for a binary operator instruction, which has + /// an opcode which directly corresponds to the given ISD opcode. + bool selectBinaryOp(const User *I, unsigned ISDOpcode); + bool selectFNeg(const User *I); + bool selectGetElementPtr(const User *I); + bool selectStackmap(const CallInst *I); + bool selectPatchpoint(const CallInst *I); + bool selectCall(const User *Call); + bool selectIntrinsicCall(const IntrinsicInst *II); + bool selectBitCast(const User *I); + bool selectCast(const User *I, unsigned Opcode); + bool selectExtractValue(const User *I); + bool selectInsertValue(const User *I); +private: /// \brief Handle PHI nodes in successor blocks. /// /// Emit code to ensure constants are copied into registers when needed. @@ -561,18 +543,27 @@ private: /// nodes as input. We cannot just directly add them, because expansion might /// result in multiple MBB's for one BB. As such, the start of the BB might /// correspond to a different MBB than the end. - bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); + bool handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); + + /// \brief Helper for materializeRegForValue to materialize a constant in a + /// target-independent way. + unsigned materializeConstant(const Value *V, MVT VT); - /// Helper for getRegForVale. This function is called when the value isn't - /// already available in a register and must be materialized with new + /// \brief Helper for getRegForVale. This function is called when the value + /// isn't already available in a register and must be materialized with new /// instructions. unsigned materializeRegForValue(const Value *V, MVT VT); - /// Clears LocalValueMap and moves the area for the new local variables to the - /// beginning of the block. It helps to avoid spilling cached variables across - /// heavy instructions like calls. + /// \brief Clears LocalValueMap and moves the area for the new local variables + /// to the beginning of the block. It helps to avoid spilling cached variables + /// across heavy instructions like calls. void flushLocalValueMap(); + /// \brief Insertion point before trying to select the current instruction. + MachineBasicBlock::iterator SavedInsertPt; + + /// \brief Add a stackmap or patchpoint intrinsic call's live variable + /// operands to a stackmap or patchpoint machine instruction. bool addStackMapLiveVars(SmallVectorImpl &Ops, const CallInst *CI, unsigned StartIdx); bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs, @@ -580,6 +571,6 @@ private: CallLoweringInfo &CLI); }; -} +} // end namespace llvm #endif diff --git a/include/llvm/CodeGen/ForwardControlFlowIntegrity.h b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h new file mode 100644 index 0000000..ec8e2ef --- /dev/null +++ b/include/llvm/CodeGen/ForwardControlFlowIntegrity.h @@ -0,0 +1,122 @@ +//===-- ForwardControlFlowIntegrity.h: Forward-Edge CFI ---------*- C++ -*-===// +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass instruments indirect calls with checks to ensure that these calls +// pass through the appropriate jump-instruction table generated by +// JumpInstrTables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H +#define LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetOptions.h" +#include + +namespace llvm { + +class AnalysisUsage; +class BasicBlock; +class Constant; +class Function; +class Instruction; +class Module; +class Value; + +/// ForwardControlFlowIntegrity uses the information from JumpInstrTableInfo to +/// prepend checks to indirect calls to make sure that these calls target valid +/// locations. +class ForwardControlFlowIntegrity : public ModulePass { +public: + static char ID; + + ForwardControlFlowIntegrity(); + ForwardControlFlowIntegrity(JumpTable::JumpTableType JTT, + CFIntegrity CFIType, + bool CFIEnforcing, std::string CFIFuncName); + ~ForwardControlFlowIntegrity() override; + + /// Runs the CFI pass on a given module. This works best if the module in + /// question is the result of link-time optimization (see lib/LTO). + bool runOnModule(Module &M) override; + const char *getPassName() const override { + return "Forward Control-Flow Integrity"; + } + void getAnalysisUsage(AnalysisUsage &AU) const override; + +private: + typedef SmallVector CallSet; + + /// A structure that is used to keep track of constant table information. + struct CFIConstants { + Constant *StartValue; + Constant *MaskValue; + Constant *Size; + }; + + /// A map from function type to the base of the table for this type and a mask + /// for the table + typedef DenseMap CFITables; + + CallSet IndirectCalls; + + /// The type of jumptable implementation. + JumpTable::JumpTableType JTType; + + /// The type of CFI check to add before each indirect call. + CFIntegrity CFIType; + + /// A value that controls whether or not CFI violations cause a halt. + bool CFIEnforcing; + + /// The name of the function to call in case of a CFI violation when + /// CFIEnforcing is false. There is a default function that ignores + /// violations. + std::string CFIFuncName; + + /// The alignment of each entry in the table, from JumpInstrTableInfo. The + /// JumpInstrTableInfo class always makes this a power of two. + uint64_t ByteAlignment; + + /// The base-2 logarithm of ByteAlignment, needed for some of the transforms + /// (like CFIntegrity::Ror) + unsigned LogByteAlignment; + + /// Adds checks to each indirect call site to make sure that it is calling a + /// function in our jump table. + void updateIndirectCalls(Module &M, CFITables &CFIT); + + /// Walks the instructions to find all the indirect calls. + void getIndirectCalls(Module &M); + + /// Adds a function that handles violations in non-enforcing mode + /// (!CFIEnforcing). The default warning function simply returns, since the + /// exact details of how to handle CFI violations depend on the application. + void addWarningFunction(Module &M); + + /// Rewrites a function pointer in a call/invoke instruction to force it into + /// a table. + void rewriteFunctionPointer(Module &M, Instruction *I, Value *FunPtr, + Constant *JumpTableStart, Constant *JumpTableMask, + Constant *JumpTableSize); + + /// Inserts a check and a call to a warning function at a given instruction + /// that must be an indirect call. + void insertWarning(Module &M, BasicBlock *Block, Instruction *I, + Value *FunPtr); +}; + +ModulePass * +createForwardControlFlowIntegrityPass(JumpTable::JumpTableType JTT, + CFIntegrity CFIType, + bool CFIEnforcing, StringRef CFIFuncName); +} + +#endif // LLVM_CODEGEN_FORWARDCONTROLFLOWINTEGRITY_H diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 9636b51..7c574df 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -20,6 +20,7 @@ #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" @@ -50,10 +51,10 @@ class Value; /// function that is used when lowering a region of the function. /// class FunctionLoweringInfo { - const TargetMachine &TM; public: const Function *Fn; MachineFunction *MF; + const TargetLowering *TLI; MachineRegisterInfo *RegInfo; BranchProbabilityInfo *BPI; /// CanLowerReturn - true iff the function's return value can be lowered to @@ -87,6 +88,12 @@ public: /// RegFixups - Registers which need to be replaced after isel is done. DenseMap RegFixups; + /// StatepointStackSlots - A list of temporary stack slots (frame indices) + /// used to spill values at a statepoint. We store them here to enable + /// reuse of the same stack slots across different statepoints in different + /// basic blocks. + SmallVector StatepointStackSlots; + /// MBB - The current block. MachineBasicBlock *MBB; @@ -106,6 +113,10 @@ public: KnownZero(1, 0) {} }; + /// Record the preferred extend type (ISD::SIGN_EXTEND or ISD::ZERO_EXTEND) + /// for a value. + DenseMap PreferredExtendType; + /// VisitedBBs - The set of basic blocks visited thus far by instruction /// selection. SmallPtrSet VisitedBBs; @@ -115,14 +126,13 @@ public: /// TODO: This isn't per-function state, it's per-basic-block state. But /// there's no other convenient place for it to live right now. std::vector > PHINodesToUpdate; + unsigned OrigNumPHINodesToUpdate; /// If the current MBB is a landing pad, the exception pointer and exception /// selector registers are copied into these virtual registers by /// SelectionDAGISel::PrepareEHLandingPad(). unsigned ExceptionPointerVirtReg, ExceptionSelectorVirtReg; - explicit FunctionLoweringInfo(const TargetMachine &TM) : TM(TM) {} - /// set - Initialize this FunctionLoweringInfo with the given Function /// and its associated MachineFunction. /// @@ -196,6 +206,9 @@ public: return; unsigned Reg = It->second; + if (Reg == 0) + return; + LiveOutRegInfo.grow(Reg); LiveOutRegInfo[Reg].IsValid = false; } diff --git a/include/llvm/CodeGen/GCMetadata.h b/include/llvm/CodeGen/GCMetadata.h index ddcc823..c7f1ab8 100644 --- a/include/llvm/CodeGen/GCMetadata.h +++ b/include/llvm/CodeGen/GCMetadata.h @@ -37,7 +37,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Pass.h" - #include namespace llvm { @@ -80,8 +79,8 @@ namespace llvm { }; - /// GCFunctionInfo - Garbage collection metadata for a single function. - /// + /// Garbage collection metadata for a single function. Currently, this + /// information only applies to GCStrategies which use GCRoot. class GCFunctionInfo { public: typedef std::vector::iterator iterator; @@ -160,21 +159,37 @@ namespace llvm { size_t live_size(const iterator &p) const { return roots_size(); } }; - - /// GCModuleInfo - Garbage collection metadata for a whole module. - /// + /// An analysis pass which caches information about the entire Module. + /// Records both the function level information used by GCRoots and a + /// cache of the 'active' gc strategy objects for the current Module. class GCModuleInfo : public ImmutablePass { typedef StringMap strategy_map_type; typedef std::vector> list_type; - typedef DenseMap finfo_map_type; strategy_map_type StrategyMap; list_type StrategyList; - finfo_map_type FInfoMap; GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name); public: + /// List of per function info objects. In theory, Each of these + /// may be associated with a different GC. + typedef std::vector> FuncInfoVec; + + FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } + FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } + + + private: + /// Owning list of all GCFunctionInfos associated with this Module + FuncInfoVec Functions; + + /// Non-owning map to bypass linear search when finding the GCFunctionInfo + /// associated with a particular Function. + typedef DenseMap finfo_map_type; + finfo_map_type FInfoMap; + public: + typedef list_type::const_iterator iterator; static char ID; @@ -191,8 +206,9 @@ namespace llvm { iterator begin() const { return StrategyList.begin(); } iterator end() const { return StrategyList.end(); } - /// get - Look up function metadata. - /// + /// get - Look up function metadata. This is currently assumed + /// have the side effect of initializing the associated GCStrategy. That + /// will soon change. GCFunctionInfo &getFunctionInfo(const Function &F); }; diff --git a/include/llvm/CodeGen/GCMetadataPrinter.h b/include/llvm/CodeGen/GCMetadataPrinter.h index 4a6b5ac..25fafba 100644 --- a/include/llvm/CodeGen/GCMetadataPrinter.h +++ b/include/llvm/CodeGen/GCMetadataPrinter.h @@ -32,16 +32,11 @@ namespace llvm { /// defaults from Registry. typedef Registry GCMetadataPrinterRegistry; - /// GCMetadataPrinter - Emits GC metadata as assembly code. - /// + /// GCMetadataPrinter - Emits GC metadata as assembly code. Instances are + /// created, managed, and owned by the AsmPrinter. class GCMetadataPrinter { - public: - typedef GCStrategy::list_type list_type; - typedef GCStrategy::iterator iterator; - private: GCStrategy *S; - friend class AsmPrinter; protected: @@ -55,16 +50,15 @@ namespace llvm { public: GCStrategy &getStrategy() { return *S; } - const Module &getModule() const { return S->getModule(); } - - /// begin/end - Iterate over the collected function metadata. - iterator begin() { return S->begin(); } - iterator end() { return S->end(); } - - /// beginAssembly/finishAssembly - Emit module metadata as assembly code. - virtual void beginAssembly(AsmPrinter &AP); - virtual void finishAssembly(AsmPrinter &AP); + /// Called before the assembly for the module is generated by + /// the AsmPrinter (but after target specific hooks.) + virtual void beginAssembly(Module &M, GCModuleInfo &Info, + AsmPrinter &AP) {} + /// Called after the assembly for the module is generated by + /// the AsmPrinter (but before target specific hooks) + virtual void finishAssembly(Module &M, GCModuleInfo &Info, + AsmPrinter &AP) {} virtual ~GCMetadataPrinter(); }; diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 81e1f85..0b0c312 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -12,9 +12,14 @@ // specified in a function's 'gc' attribute. Algorithms are enabled by setting // flags in a subclass's constructor, and some virtual methods can be // overridden. +// +// GCStrategy is relevant for implementations using either gc.root or +// gc.statepoint based lowering strategies, but is currently focused mostly on +// options for gc.root. This will change over time. // -// When requested, the GCStrategy will be populated with data about each -// function which uses it. Specifically: +// When requested by a subclass of GCStrategy, the gc.root implementation will +// populate GCModuleInfo and GCFunctionInfo with that about each Function in +// the Module that opts in to garbage collection. Specifically: // // - Safe points // Garbage collection is generally only possible at certain points in code. @@ -31,40 +36,42 @@ // This information can used to emit the metadata tables which are required by // the target garbage collector runtime. // +// When used with gc.statepoint, information about safepoint and roots can be +// found in the binary StackMap section after code generation. Safepoint +// placement is currently the responsibility of the frontend, though late +// insertion support is planned. gc.statepoint does not currently support +// custom stack map formats; such can be generated by parsing the standard +// stack map section if desired. +// +// The read and write barrier support can be used with either implementation. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_GCSTRATEGY_H #define LLVM_CODEGEN_GCSTRATEGY_H +#include "llvm/ADT/Optional.h" #include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/Support/Registry.h" #include namespace llvm { - - class GCStrategy; - - /// The GC strategy registry uses all the defaults from Registry. - /// - typedef Registry GCRegistry; - /// GCStrategy describes a garbage collector algorithm's code generation /// requirements, and provides overridable hooks for those needs which cannot - /// be abstractly described. + /// be abstractly described. GCStrategy objects currently must be looked up + /// through the GCModuleInfo analysis pass. They are owned by the analysis + /// pass and recreated every time that pass is invalidated. class GCStrategy { - public: - typedef std::vector> list_type; - typedef list_type::iterator iterator; - private: - friend class GCModuleInfo; - const Module *M; std::string Name; - - list_type Functions; + friend class GCModuleInfo; protected: + bool UseStatepoints; /// Uses gc.statepoints as opposed to gc.roots, + /// if set, none of the other options can be + /// anything but their default values. + unsigned NeededSafePoints; ///< Bitmask of required safe points. bool CustomReadBarriers; ///< Default is to insert loads. bool CustomWriteBarriers; ///< Default is to insert stores. @@ -76,78 +83,114 @@ namespace llvm { public: GCStrategy(); - virtual ~GCStrategy() {} - - /// getName - The name of the GC strategy, for debugging. - /// + /// Return the name of the GC strategy. This is the value of the collector + /// name string specified on functions which use this strategy. const std::string &getName() const { return Name; } - /// getModule - The module within which the GC strategy is operating. - /// - const Module &getModule() const { return *M; } + /// By default, write barriers are replaced with simple store + /// instructions. If true, then performCustomLowering must instead lower + /// them. + bool customWriteBarrier() const { return CustomWriteBarriers; } + + /// By default, read barriers are replaced with simple load + /// instructions. If true, then performCustomLowering must instead lower + /// them. + bool customReadBarrier() const { return CustomReadBarriers; } + + /// Returns true if this strategy is expecting the use of gc.statepoints, + /// and false otherwise. + bool useStatepoints() const { return UseStatepoints; } + + /** @name Statepoint Specific Properties */ + ///@{ - /// needsSafePoitns - True if safe points of any kind are required. By - // default, none are recorded. + /// If the value specified can be reliably distinguished, returns true for + /// pointers to GC managed locations and false for pointers to non-GC + /// managed locations. Note a GCStrategy can always return 'None' (i.e. an + /// empty optional indicating it can't reliably distinguish. + virtual Optional isGCManagedPointer(const Value *V) const { + return None; + } + ///@} + + /** @name GCRoot Specific Properties + * These properties and overrides only apply to collector strategies using + * GCRoot. + */ + ///@{ + + /// True if safe points of any kind are required. By default, none are + /// recorded. bool needsSafePoints() const { return CustomSafePoints || NeededSafePoints != 0; } - /// needsSafePoint(Kind) - True if the given kind of safe point is - // required. By default, none are recorded. + /// True if the given kind of safe point is required. By default, none are + /// recorded. bool needsSafePoint(GC::PointKind Kind) const { return (NeededSafePoints & 1 << Kind) != 0; } - - /// customWriteBarrier - By default, write barriers are replaced with simple - /// store instructions. If true, then - /// performCustomLowering must instead lower them. - bool customWriteBarrier() const { return CustomWriteBarriers; } - - /// customReadBarrier - By default, read barriers are replaced with simple - /// load instructions. If true, then - /// performCustomLowering must instead lower them. - bool customReadBarrier() const { return CustomReadBarriers; } - - /// customRoots - By default, roots are left for the code generator so it - /// can generate a stack map. If true, then - // performCustomLowering must delete them. + + /// By default, roots are left for the code generator so it can generate a + /// stack map. If true, then performCustomLowering must delete them. bool customRoots() const { return CustomRoots; } - /// customSafePoints - By default, the GC analysis will find safe - /// points according to NeededSafePoints. If true, - /// then findCustomSafePoints must create them. + /// By default, the GC analysis will find safe points according to + /// NeededSafePoints. If true, then findCustomSafePoints must create them. bool customSafePoints() const { return CustomSafePoints; } - /// initializeRoots - If set, gcroot intrinsics should initialize their - // allocas to null before the first use. This is - // necessary for most GCs and is enabled by default. + /// If set, gcroot intrinsics should initialize their allocas to null + /// before the first use. This is necessary for most GCs and is enabled by + /// default. bool initializeRoots() const { return InitRoots; } - /// usesMetadata - If set, appropriate metadata tables must be emitted by - /// the back-end (assembler, JIT, or otherwise). + /// If set, appropriate metadata tables must be emitted by the back-end + /// (assembler, JIT, or otherwise). For statepoint, this method is + /// currently unsupported. The stackmap information can be found in the + /// StackMap section as described in the documentation. bool usesMetadata() const { return UsesMetadata; } - - /// begin/end - Iterators for function metadata. - /// - iterator begin() { return Functions.begin(); } - iterator end() { return Functions.end(); } - - /// insertFunctionMetadata - Creates metadata for a function. - /// - GCFunctionInfo *insertFunctionInfo(const Function &F); + ///@} + /// initializeCustomLowering/performCustomLowering - If any of the actions /// are set to custom, performCustomLowering must be overriden to transform /// the corresponding actions to LLVM IR. initializeCustomLowering is /// optional to override. These are the only GCStrategy methods through - /// which the LLVM IR can be modified. - virtual bool initializeCustomLowering(Module &F); - virtual bool performCustomLowering(Function &F); - virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF); + /// which the LLVM IR can be modified. These methods apply mostly to + /// gc.root based implementations, but can be overriden to provide custom + /// barrier lowerings with gc.statepoint as well. + ///@{ + virtual bool initializeCustomLowering(Module &F) { + // No changes made + return false; + } + virtual bool performCustomLowering(Function &F) { + llvm_unreachable("GCStrategy subclass specified a configuration which" + "requires a custom lowering without providing one"); + } + ///@} + /// Called if customSafepoints returns true, used only by gc.root + /// implementations. + virtual bool findCustomSafePoints(GCFunctionInfo& FI, MachineFunction& MF) { + llvm_unreachable("GCStrategy subclass specified a configuration which" + "requests custom safepoint identification without" + "providing an implementation for such"); + } }; - + + /// Subclasses of GCStrategy are made available for use during compilation by + /// adding them to the global GCRegistry. This can done either within the + /// LLVM source tree or via a loadable plugin. An example registeration + /// would be: + /// static GCRegistry::Add X("custom-name", + /// "my custom supper fancy gc strategy"); + /// + /// Note that to use a custom GCMetadataPrinter w/gc.roots, you must also + /// register your GCMetadataPrinter subclass with the + /// GCMetadataPrinterRegistery as well. + typedef Registry GCRegistry; } #endif diff --git a/include/llvm/CodeGen/GCs.h b/include/llvm/CodeGen/GCs.h index bb170c8..51a3184 100644 --- a/include/llvm/CodeGen/GCs.h +++ b/include/llvm/CodeGen/GCs.h @@ -36,6 +36,8 @@ namespace llvm { /// Creates a shadow stack garbage collector. This collector requires no code /// generator support. void linkShadowStackGC(); + + void linkStatepointExampleGC(); } #endif diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 8444761..952362e 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -72,6 +72,11 @@ namespace ISD { /// the parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + /// FRAME_ALLOC_RECOVER - Represents the llvm.framerecover + /// intrinsic. Materializes the offset from the frame pointer of another + /// function to the result of llvm.frameallocate. + FRAME_ALLOC_RECOVER, + /// READ_REGISTER, WRITE_REGISTER - This node represents llvm.register on /// the DAG, which implements the named register global variables extension. READ_REGISTER, @@ -485,7 +490,8 @@ namespace ISD { FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, FPOW, FLOG, FLOG2, FLOG10, FEXP, FEXP2, FCEIL, FTRUNC, FRINT, FNEARBYINT, FROUND, FFLOOR, - + FMINNUM, FMAXNUM, + /// FSINCOS - Compute both fsin and fcos as a single operation. FSINCOS, @@ -674,6 +680,9 @@ namespace ISD { ATOMIC_LOAD_UMIN, ATOMIC_LOAD_UMAX, + // Masked load and store + MLOAD, MSTORE, + /// This corresponds to the llvm.lifetime.* intrinsics. The first operand /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, @@ -744,7 +753,7 @@ namespace ISD { LAST_LOADEXT_TYPE }; - NodeType getExtForLoadExtType(LoadExtType); + NodeType getExtForLoadExtType(bool IsFP, LoadExtType); //===--------------------------------------------------------------------===// /// ISD::CondCode enum - These are ordered carefully to make the bitfields diff --git a/include/llvm/CodeGen/JITCodeEmitter.h b/include/llvm/CodeGen/JITCodeEmitter.h deleted file mode 100644 index dc2a027..0000000 --- a/include/llvm/CodeGen/JITCodeEmitter.h +++ /dev/null @@ -1,344 +0,0 @@ -//===-- llvm/CodeGen/JITCodeEmitter.h - Code emission ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an abstract interface that is used by the machine code -// emission framework to output the code. This allows machine code emission to -// be separated from concerns such as resolution of call targets, and where the -// machine code will be written (memory or disk, f.e.). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_JITCODEEMITTER_H -#define LLVM_CODEGEN_JITCODEEMITTER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/CodeGen/MachineCodeEmitter.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/MathExtras.h" -#include - -namespace llvm { - -class MachineBasicBlock; -class MachineConstantPool; -class MachineJumpTableInfo; -class MachineFunction; -class MachineModuleInfo; -class MachineRelocation; -class Value; -class GlobalValue; -class Function; - -/// JITCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxiliary -/// structures, such as jump tables, relocations, etc. -/// -/// Emission of machine code is complicated by the fact that we don't (in -/// general) know the size of the machine code that we're about to emit before -/// we emit it. As such, we preallocate a certain amount of memory, and set the -/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we -/// emit machine instructions, we advance the CurBufferPtr to indicate the -/// location of the next byte to emit. In the case of a buffer overflow (we -/// need to emit more machine code than we have allocated space for), the -/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire -/// function has been emitted, the overflow condition is checked, and if it has -/// occurred, more memory is allocated, and we reemit the code into it. -/// -class JITCodeEmitter : public MachineCodeEmitter { - void anchor() override; -public: - virtual ~JITCodeEmitter() {} - - /// startFunction - This callback is invoked when the specified function is - /// about to be code generated. This initializes the BufferBegin/End/Ptr - /// fields. - /// - void startFunction(MachineFunction &F) override = 0; - - /// finishFunction - This callback is invoked when the specified function has - /// finished code generation. If a buffer overflow has occurred, this method - /// returns true (the callee is required to try again), otherwise it returns - /// false. - /// - bool finishFunction(MachineFunction &F) override = 0; - - /// allocIndirectGV - Allocates and fills storage for an indirect - /// GlobalValue, and returns the address. - virtual void *allocIndirectGV(const GlobalValue *GV, - const uint8_t *Buffer, size_t Size, - unsigned Alignment) = 0; - - /// emitByte - This callback is invoked when a byte needs to be written to the - /// output stream. - /// - void emitByte(uint8_t B) { - if (CurBufferPtr != BufferEnd) - *CurBufferPtr++ = B; - } - - /// emitWordLE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitWordLE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitWordBE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitWordBE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordLE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitDWordLE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 56); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordBE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitDWordBE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 56); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitAlignment - Move the CurBufferPtr pointer up to the specified - /// alignment (saturated to BufferEnd of course). - void emitAlignment(unsigned Alignment) { - if (Alignment == 0) Alignment = 1; - uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, - Alignment); - CurBufferPtr = std::min(NewPtr, BufferEnd); - } - - /// emitAlignmentWithFill - Similar to emitAlignment, except that the - /// extra bytes are filled with the provided byte. - void emitAlignmentWithFill(unsigned Alignment, uint8_t Fill) { - if (Alignment == 0) Alignment = 1; - uint8_t *NewPtr = (uint8_t*)RoundUpToAlignment((uintptr_t)CurBufferPtr, - Alignment); - // Fail if we don't have room. - if (NewPtr > BufferEnd) { - CurBufferPtr = BufferEnd; - return; - } - while (CurBufferPtr < NewPtr) { - *CurBufferPtr++ = Fill; - } - } - - /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be - /// written to the output stream. - void emitULEB128Bytes(uint64_t Value, unsigned PadTo = 0) { - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - if (Value || PadTo != 0) Byte |= 0x80; - emitByte(Byte); - } while (Value); - - if (PadTo) { - do { - uint8_t Byte = (PadTo > 1) ? 0x80 : 0x0; - emitByte(Byte); - } while (--PadTo); - } - } - - /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be - /// written to the output stream. - void emitSLEB128Bytes(int64_t Value) { - int32_t Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - emitByte(Byte); - } while (IsMore); - } - - /// emitString - This callback is invoked when a String needs to be - /// written to the output stream. - void emitString(const std::string &String) { - for (size_t i = 0, N = String.size(); i < N; ++i) { - uint8_t C = String[i]; - emitByte(C); - } - emitByte(0); - } - - /// emitInt32 - Emit a int32 directive. - void emitInt32(uint32_t Value) { - if (4 <= BufferEnd-CurBufferPtr) { - *((uint32_t*)CurBufferPtr) = Value; - CurBufferPtr += 4; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt64 - Emit a int64 directive. - void emitInt64(uint64_t Value) { - if (8 <= BufferEnd-CurBufferPtr) { - *((uint64_t*)CurBufferPtr) = Value; - CurBufferPtr += 8; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt32At - Emit the Int32 Value in Addr. - void emitInt32At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint32_t*)Addr) = (uint32_t)Value; - } - - /// emitInt64At - Emit the Int64 Value in Addr. - void emitInt64At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint64_t*)Addr) = (uint64_t)Value; - } - - - /// emitLabel - Emits a label - void emitLabel(MCSymbol *Label) override = 0; - - /// allocateSpace - Allocate a block of space in the current output buffer, - /// returning null (and setting conditions to indicate buffer overflow) on - /// failure. Alignment is the alignment in bytes of the buffer desired. - void *allocateSpace(uintptr_t Size, unsigned Alignment) override { - emitAlignment(Alignment); - void *Result; - - // Check for buffer overflow. - if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { - CurBufferPtr = BufferEnd; - Result = nullptr; - } else { - // Allocate the space. - Result = CurBufferPtr; - CurBufferPtr += Size; - } - - return Result; - } - - /// allocateGlobal - Allocate memory for a global. Unlike allocateSpace, - /// this method does not allocate memory in the current output buffer, - /// because a global may live longer than the current function. - virtual void *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; - - /// StartMachineBasicBlock - This should be called by the target when a new - /// basic block is about to be emitted. This way the MCE knows where the - /// start of the block is, and can implement getMachineBasicBlockAddress. - void StartMachineBasicBlock(MachineBasicBlock *MBB) override = 0; - - /// getCurrentPCValue - This returns the address that the next emitted byte - /// will be output to. - /// - uintptr_t getCurrentPCValue() const override { - return (uintptr_t)CurBufferPtr; - } - - /// getCurrentPCOffset - Return the offset from the start of the emitted - /// buffer that we are currently writing to. - uintptr_t getCurrentPCOffset() const override { - return CurBufferPtr-BufferBegin; - } - - /// earlyResolveAddresses - True if the code emitter can use symbol addresses - /// during code emission time. The JIT is capable of doing this because it - /// creates jump tables or constant pools in memory on the fly while the - /// object code emitters rely on a linker to have real addresses and should - /// use relocations instead. - bool earlyResolveAddresses() const override { return true; } - - /// addRelocation - Whenever a relocatable address is needed, it should be - /// noted with this interface. - void addRelocation(const MachineRelocation &MR) override = 0; - - /// FIXME: These should all be handled with relocations! - - /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in - /// the constant pool that was last emitted with the emitConstantPool method. - /// - uintptr_t getConstantPoolEntryAddress(unsigned Index) const override = 0; - - /// getJumpTableEntryAddress - Return the address of the jump table with index - /// 'Index' in the function that last called initJumpTableInfo. - /// - uintptr_t getJumpTableEntryAddress(unsigned Index) const override = 0; - - /// getMachineBasicBlockAddress - Return the address of the specified - /// MachineBasicBlock, only usable after the label for the MBB has been - /// emitted. - /// - uintptr_t - getMachineBasicBlockAddress(MachineBasicBlock *MBB) const override = 0; - - /// getLabelAddress - Return the address of the specified Label, only usable - /// after the Label has been emitted. - /// - uintptr_t getLabelAddress(MCSymbol *Label) const override = 0; - - /// Specifies the MachineModuleInfo object. This is used for exception handling - /// purposes. - void setModuleInfo(MachineModuleInfo* Info) override = 0; - - /// getLabelLocations - Return the label locations map of the label IDs to - /// their address. - virtual DenseMap *getLabelLocations() { - return nullptr; - } -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/CodeGen/JumpInstrTables.h b/include/llvm/CodeGen/JumpInstrTables.h index 6ca3d7d..005bc1e 100644 --- a/include/llvm/CodeGen/JumpInstrTables.h +++ b/include/llvm/CodeGen/JumpInstrTables.h @@ -39,13 +39,14 @@ class Module; /// jmp f_orig@PLT /// \endverbatim /// -/// Support for an architecture depends on two functions in TargetInstrInfo: -/// getUnconditionalBranch, and getTrap. AsmPrinter uses these to generate the -/// appropriate instructions for the jump statement (an unconditional branch) -/// and for padding to make the table have a size that is a power of two. This -/// padding uses a trap instruction to ensure that calls to this area halt the -/// program. The default implementations of these functions call -/// llvm_unreachable. +/// Support for an architecture depends on three functions in TargetInstrInfo: +/// getUnconditionalBranch, getTrap, and getJumpInstrTableEntryBound. AsmPrinter +/// uses these to generate the appropriate instructions for the jump statement +/// (an unconditional branch) and for padding to make the table have a size that +/// is a power of two. This padding uses a trap instruction to ensure that calls +/// to this area halt the program. The default implementations of these +/// functions call llvm_unreachable, except for getJumpInstrTableEntryBound, +/// which returns 0 by default. class JumpInstrTables : public ModulePass { public: static char ID; @@ -64,6 +65,14 @@ public: /// Checks to see if there is already a table for the given FunctionType. bool hasTable(FunctionType *FunTy); + /// Maps the function into a subset of function types, depending on the + /// jump-instruction table style selected from JumpTableTypes in + /// JumpInstrTables.cpp. The choice of mapping determines the number of + /// jump-instruction tables generated by this pass. E.g., the simplest mapping + /// converts every function type into void f(); so, all functions end up in a + /// single table. + static FunctionType *transformType(JumpTable::JumpTableType JTT, + FunctionType *FunTy); private: /// The metadata used while a jump table is being built struct TableMeta { @@ -76,14 +85,6 @@ private: typedef DenseMap JumpMap; - /// Maps the function into a subset of function types, depending on the - /// jump-instruction table style selected from JumpTableTypes in - /// JumpInstrTables.cpp. The choice of mapping determines the number of - /// jump-instruction tables generated by this pass. E.g., the simplest mapping - /// converts every function type into void f(); so, all functions end up in a - /// single table. - FunctionType *transformType(FunctionType *FunTy); - /// The current state of functions and jump entries in the table(s). JumpMap Metadata; diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index 036aea3..11a360a 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -19,14 +19,14 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/ValueHandle.h" -#include #include +#include namespace llvm { class MachineInstr; @@ -48,6 +48,8 @@ public: LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { + assert((!D || D->isResolved()) && "Expected resolved node"); + assert((!I || I->isResolved()) && "Expected resolved node"); if (Parent) Parent->addChild(this); } @@ -116,8 +118,8 @@ public: private: LexicalScope *Parent; // Parent to this scope. - AssertingVH Desc; // Debug info descriptor. - AssertingVH InlinedAtLocation; // Location at which this + const MDNode *Desc; // Debug info descriptor. + const MDNode *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector Children; // Scopes defined in scope. @@ -148,12 +150,6 @@ public: /// empty - Return true if there is any lexical scope information available. bool empty() { return CurrentFnLexicalScope == nullptr; } - /// isCurrentFunctionScope - Return true if given lexical scope represents - /// current function. - bool isCurrentFunctionScope(const LexicalScope *LS) { - return LS == CurrentFnLexicalScope; - } - /// getCurrentFunctionScope - Return lexical scope for the current function. LexicalScope *getCurrentFunctionScope() const { return CurrentFnLexicalScope; @@ -163,7 +159,7 @@ public: /// which have machine instructions that belong to lexical scope identified by /// DebugLoc. void getMachineBasicBlocks(DebugLoc DL, - SmallPtrSet &MBBs); + SmallPtrSetImpl &MBBs); /// dominates - Return true if DebugLoc's lexical scope dominates at least one /// machine instruction's lexical scope in a given machine basic block. diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 372c294..e7ccbfa 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -39,6 +39,7 @@ namespace { llvm::linkOcamlGC(); llvm::linkErlangGC(); llvm::linkShadowStackGC(); + llvm::linkStatepointExampleGC(); (void) llvm::createBURRListDAGScheduler(nullptr, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 6629e60..ce9845e 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -119,6 +119,12 @@ namespace llvm { return isDeadDef() ? nullptr : LateVal; } + /// Returns the value alive at the end of the instruction, if any. This can + /// be a live-through value, a live def or a dead def. + VNInfo *valueOutOrDead() const { + return LateVal; + } + /// Return the value defined by this instruction, if any. This includes /// dead defs, it is the value created by the instruction's def operands. VNInfo *valueDefined() const { @@ -204,6 +210,23 @@ namespace llvm { const_vni_iterator vni_begin() const { return valnos.begin(); } const_vni_iterator vni_end() const { return valnos.end(); } + /// Constructs a new LiveRange object. + LiveRange() { + } + + /// Constructs a new LiveRange object by copying segments and valnos from + /// another LiveRange. + LiveRange(const LiveRange &Other, BumpPtrAllocator &Allocator) { + // Duplicate valnos. + for (const VNInfo *VNI : Other.valnos) { + createValueCopy(VNI, Allocator); + } + // Now we can copy segments and remap their valnos. + for (const Segment &S : Other.segments) { + segments.push_back(Segment(S.start, S.end, valnos[S.valno->id])); + } + } + /// advanceTo - Advance the specified iterator to point to the Segment /// containing the specified position, or end() if the position is past the /// end of the range. If no Segment contains this position, but the @@ -217,6 +240,14 @@ namespace llvm { return I; } + const_iterator advanceTo(const_iterator I, SlotIndex Pos) const { + assert(I != end()); + if (Pos >= endIndex()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + /// find - Return an iterator pointing to the first segment that ends after /// Pos, or end(). This is the same as advanceTo(begin(), Pos), but faster /// when searching large ranges. @@ -397,6 +428,12 @@ namespace llvm { /// scanning the Other range starting at I. bool overlapsFrom(const LiveRange &Other, const_iterator I) const; + /// Returns true if all segments of the @p Other live range are completely + /// covered by this live range. + /// Adjacent live ranges do not affect the covering:the liverange + /// [1,5](5,10] covers (3,7]. + bool covers(const LiveRange &Other) const; + /// Add the specified Segment to this range, merging segments as /// appropriate. This returns an iterator to the inserted segment (which /// may have grown since it was inserted). @@ -435,6 +472,12 @@ namespace llvm { removeSegment(S.start, S.end, RemoveDeadValNo); } + /// Remove segment pointed to by iterator @p I from this range. This does + /// not remove dead value numbers. + iterator removeSegment(iterator I) { + return segments.erase(I); + } + /// Query Liveness at Idx. /// The sub-instruction slot of Idx doesn't matter, only the instruction /// it refers to is considered. @@ -484,9 +527,9 @@ namespace llvm { /// Returns true if the live range is zero length, i.e. no live segments /// span instructions. It doesn't pay to spill such a range. bool isZeroLength(SlotIndexes *Indexes) const { - for (const_iterator i = begin(), e = end(); i != e; ++i) - if (Indexes->getNextNonNullIndex(i->start).getBaseIndex() < - i->end.getBaseIndex()) + for (const Segment &S : segments) + if (Indexes->getNextNonNullIndex(S.start).getBaseIndex() < + S.end.getBaseIndex()) return false; return true; } @@ -509,6 +552,10 @@ namespace llvm { void verify() const; #endif + protected: + /// Append a segment to the list of segments. + void append(const LiveRange::Segment S); + private: iterator addSegmentFrom(Segment S, iterator From); @@ -529,11 +576,122 @@ namespace llvm { public: typedef LiveRange super; + /// A live range for subregisters. The LaneMask specifies which parts of the + /// super register are covered by the interval. + /// (@sa TargetRegisterInfo::getSubRegIndexLaneMask()). + class SubRange : public LiveRange { + public: + SubRange *Next; + unsigned LaneMask; + + /// Constructs a new SubRange object. + SubRange(unsigned LaneMask) + : Next(nullptr), LaneMask(LaneMask) { + } + + /// Constructs a new SubRange object by copying liveness from @p Other. + SubRange(unsigned LaneMask, const LiveRange &Other, + BumpPtrAllocator &Allocator) + : LiveRange(Other, Allocator), Next(nullptr), LaneMask(LaneMask) { + } + }; + + private: + SubRange *SubRanges; ///< Single linked list of subregister live ranges. + + public: const unsigned reg; // the register or stack slot of this interval. float weight; // weight of this interval LiveInterval(unsigned Reg, float Weight) - : reg(Reg), weight(Weight) {} + : SubRanges(nullptr), reg(Reg), weight(Weight) {} + + template + class SingleLinkedListIterator { + T *P; + public: + SingleLinkedListIterator(T *P) : P(P) {} + SingleLinkedListIterator &operator++() { + P = P->Next; + return *this; + } + SingleLinkedListIterator &operator++(int) { + SingleLinkedListIterator res = *this; + ++*this; + return res; + } + bool operator!=(const SingleLinkedListIterator &Other) { + return P != Other.operator->(); + } + bool operator==(const SingleLinkedListIterator &Other) { + return P == Other.operator->(); + } + T &operator*() const { + return *P; + } + T *operator->() const { + return P; + } + }; + + typedef SingleLinkedListIterator subrange_iterator; + subrange_iterator subrange_begin() { + return subrange_iterator(SubRanges); + } + subrange_iterator subrange_end() { + return subrange_iterator(nullptr); + } + + typedef SingleLinkedListIterator const_subrange_iterator; + const_subrange_iterator subrange_begin() const { + return const_subrange_iterator(SubRanges); + } + const_subrange_iterator subrange_end() const { + return const_subrange_iterator(nullptr); + } + + iterator_range subranges() { + return make_range(subrange_begin(), subrange_end()); + } + + iterator_range subranges() const { + return make_range(subrange_begin(), subrange_end()); + } + + /// Creates a new empty subregister live range. The range is added at the + /// beginning of the subrange list; subrange iterators stay valid. + SubRange *createSubRange(BumpPtrAllocator &Allocator, unsigned LaneMask) { + SubRange *Range = new (Allocator) SubRange(LaneMask); + appendSubRange(Range); + return Range; + } + + /// Like createSubRange() but the new range is filled with a copy of the + /// liveness information in @p CopyFrom. + SubRange *createSubRangeFrom(BumpPtrAllocator &Allocator, unsigned LaneMask, + const LiveRange &CopyFrom) { + SubRange *Range = new (Allocator) SubRange(LaneMask, CopyFrom, Allocator); + appendSubRange(Range); + return Range; + } + + /// Returns true if subregister liveness information is available. + bool hasSubRanges() const { + return SubRanges != nullptr; + } + + /// Removes all subregister liveness information. + void clearSubRanges() { + SubRanges = nullptr; + } + + /// Removes all subranges without any segments (subranges without segments + /// are not considered valid and should only exist temporarily). + void removeEmptySubRanges(); + + /// Construct main live range by merging the SubRanges of @p LI. + void constructMainRangeFromSubranges(const SlotIndexes &Indexes, + VNInfo::Allocator &VNIAllocator); /// getSize - Returns the sum of sizes of all the LiveRange's. /// @@ -558,9 +716,23 @@ namespace llvm { void print(raw_ostream &OS) const; void dump() const; + /// \brief Walks the interval and assert if any invariants fail to hold. + /// + /// Note that this is a no-op when asserts are disabled. +#ifdef NDEBUG + void verify(const MachineRegisterInfo *MRI = nullptr) const {} +#else + void verify(const MachineRegisterInfo *MRI = nullptr) const; +#endif + private: LiveInterval& operator=(const LiveInterval& rhs) LLVM_DELETED_FUNCTION; + /// Appends @p Range to SubRanges list. + void appendSubRange(SubRange *Range) { + Range->Next = SubRanges; + SubRanges = Range; + } }; inline raw_ostream &operator<<(raw_ostream &OS, const LiveInterval &LI) { diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 176665b..d8c921f 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -17,8 +17,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H -#define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H +#ifndef LLVM_CODEGEN_LIVEINTERVALANALYSIS_H +#define LLVM_CODEGEN_LIVEINTERVALANALYSIS_H #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/SmallVector.h" @@ -50,7 +50,6 @@ namespace llvm { class LiveIntervals : public MachineFunctionPass { MachineFunction* MF; MachineRegisterInfo* MRI; - const TargetMachine* TM; const TargetRegisterInfo* TRI; const TargetInstrInfo* TII; AliasAnalysis *AA; @@ -155,16 +154,11 @@ namespace llvm { bool shrinkToUses(LiveInterval *li, SmallVectorImpl *dead = nullptr); - /// \brief Walk the values in the given interval and compute which ones - /// are dead. Dead values are not deleted, however: - /// - Dead PHIDef values are marked as unused. - /// - New dead machine instructions are added to the dead vector. - /// - CanSeparate is set to true if the interval may have been separated - /// into multiple connected components. - void computeDeadValues(LiveInterval *li, - LiveRange &LR, - bool *CanSeparate, - SmallVectorImpl *dead); + /// Specialized version of + /// shrinkToUses(LiveInterval *li, SmallVectorImpl *dead) + /// that works on a subregister live range and only looks at uses matching + /// the lane mask of the subregister range. + void shrinkToUses(LiveInterval::SubRange &SR, unsigned Reg); /// extendToIndices - Extend the live range of LI to reach all points in /// Indices. The points in the Indices array must be jointly dominated by @@ -176,14 +170,21 @@ namespace llvm { /// See also LiveRangeCalc::extend(). void extendToIndices(LiveRange &LR, ArrayRef Indices); - /// pruneValue - If an LI value is live at Kill, prune its live range by - /// removing any liveness reachable from Kill. Add live range end points to + + /// If @p LR has a live value at @p Kill, prune its live range by removing + /// any liveness reachable from Kill. Add live range end points to /// EndPoints such that extendToIndices(LI, EndPoints) will reconstruct the /// value's live range. /// /// Calling pruneValue() and extendToIndices() can be used to reconstruct /// SSA form after adding defs to a virtual register. - void pruneValue(LiveInterval *LI, SlotIndex Kill, + void pruneValue(LiveRange &LR, SlotIndex Kill, + SmallVectorImpl *EndPoints); + + /// Subregister aware variant of pruneValue(LiveRange &LR, SlotIndex Kill, + /// SmallVectorImpl &EndPoints). Prunes the value in the main + /// range and all sub ranges. + void pruneValue(LiveInterval &LI, SlotIndex Kill, SmallVectorImpl *EndPoints); SlotIndexes *getSlotIndexes() const { @@ -405,6 +406,16 @@ namespace llvm { /// Compute RegMaskSlots and RegMaskBits. void computeRegMasks(); + /// Walk the values in @p LI and check for dead values: + /// - Dead PHIDef values are marked as unused. + /// - Dead operands are marked as such. + /// - Completely dead machine instructions are added to the @p dead vector + /// if it is not nullptr. + /// Returns true if any PHI value numbers have been removed which may + /// have separated the interval into multiple connected components. + bool computeDeadValues(LiveInterval &LI, + SmallVectorImpl *dead); + static LiveInterval* createInterval(unsigned Reg); void printInstrs(raw_ostream &O) const; @@ -414,6 +425,16 @@ namespace llvm { void computeRegUnitRange(LiveRange&, unsigned Unit); void computeVirtRegInterval(LiveInterval&); + + /// Helper function for repairIntervalsInRange(), walks backwards and + /// creates/modifies live segments in @p LR to match the operands found. + /// Only full operands or operands with subregisters matching @p LaneMask + /// are considered. + void repairOldRegInRange(MachineBasicBlock::iterator Begin, + MachineBasicBlock::iterator End, + const SlotIndex endIdx, LiveRange &LR, + unsigned Reg, unsigned LaneMask = ~0u); + class HMEditor; }; } // End llvm namespace diff --git a/include/llvm/CodeGen/LiveIntervalUnion.h b/include/llvm/CodeGen/LiveIntervalUnion.h index 2f40509..1381c46 100644 --- a/include/llvm/CodeGen/LiveIntervalUnion.h +++ b/include/llvm/CodeGen/LiveIntervalUnion.h @@ -84,10 +84,16 @@ public: bool changedSince(unsigned tag) const { return tag != Tag; } // Add a live virtual register to this union and merge its segments. - void unify(LiveInterval &VirtReg); + void unify(LiveInterval &VirtReg, const LiveRange &Range); + void unify(LiveInterval &VirtReg) { + unify(VirtReg, VirtReg); + } // Remove a live virtual register's segments from this union. - void extract(LiveInterval &VirtReg); + void extract(LiveInterval &VirtReg, const LiveRange &Range); + void extract(LiveInterval &VirtReg) { + extract(VirtReg, VirtReg); + } // Remove all inserted virtual registers. void clear() { Segments.clear(); ++Tag; } diff --git a/include/llvm/CodeGen/LivePhysRegs.h b/include/llvm/CodeGen/LivePhysRegs.h index 847092b..91e4ddc 100644 --- a/include/llvm/CodeGen/LivePhysRegs.h +++ b/include/llvm/CodeGen/LivePhysRegs.h @@ -26,8 +26,8 @@ // %XMM0 = ..., %YMM0 (%YMM0 and all its sub-registers are alive) //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_LIVE_PHYS_REGS_H -#define LLVM_CODEGEN_LIVE_PHYS_REGS_H +#ifndef LLVM_CODEGEN_LIVEPHYSREGS_H +#define LLVM_CODEGEN_LIVEPHYSREGS_H #include "llvm/ADT/SparseSet.h" #include "llvm/CodeGen/MachineBasicBlock.h" @@ -143,4 +143,4 @@ inline raw_ostream &operator<<(raw_ostream &OS, const LivePhysRegs& LR) { } // namespace llvm -#endif // LLVM_CODEGEN_LIVE_PHYS_REGS_H +#endif diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 5767cab..44c3c4e 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -24,6 +24,7 @@ #include "llvm/CodeGen/LiveInterval.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" namespace llvm { @@ -111,18 +112,15 @@ public: /// @param vrm Map of virtual registers to physical registers for this /// function. If NULL, no virtual register map updates will /// be done. This could be the case if called before Regalloc. - LiveRangeEdit(LiveInterval *parent, - SmallVectorImpl &newRegs, - MachineFunction &MF, - LiveIntervals &lis, - VirtRegMap *vrm, + LiveRangeEdit(LiveInterval *parent, SmallVectorImpl &newRegs, + MachineFunction &MF, LiveIntervals &lis, VirtRegMap *vrm, Delegate *delegate = nullptr) - : Parent(parent), NewRegs(newRegs), - MRI(MF.getRegInfo()), LIS(lis), VRM(vrm), - TII(*MF.getTarget().getInstrInfo()), - TheDelegate(delegate), - FirstNew(newRegs.size()), - ScannedRemattable(false) { MRI.setDelegate(this); } + : Parent(parent), NewRegs(newRegs), MRI(MF.getRegInfo()), LIS(lis), + VRM(vrm), TII(*MF.getSubtarget().getInstrInfo()), + TheDelegate(delegate), FirstNew(newRegs.size()), + ScannedRemattable(false) { + MRI.setDelegate(this); + } ~LiveRangeEdit() { MRI.resetDelegate(this); } diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index a4a5fcc..55b97dc 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -134,14 +134,14 @@ private: // Intermediate data structures // PhysRegInfo - Keep track of which instruction was the last def of a // physical register. This is a purely local property, because all physical // register references are presumed dead across basic blocks. - MachineInstr **PhysRegDef; + std::vector PhysRegDef; // PhysRegInfo - Keep track of which instruction was the last use of a // physical register. This is a purely local property, because all physical // register references are presumed dead across basic blocks. - MachineInstr **PhysRegUse; + std::vector PhysRegUse; - SmallVector *PHIVarInfo; + std::vector> PHIVarInfo; // DistanceMap - Keep track the distance of a MI from the start of the // current basic block. @@ -175,6 +175,10 @@ private: // Intermediate data structures /// register which is used in a PHI node. We map that to the BB the vreg /// is coming from. void analyzePHINodes(const MachineFunction& Fn); + + void runOnInstr(MachineInstr *MI, SmallVectorImpl &Defs); + + void runOnBlock(MachineBasicBlock *MBB, unsigned NumRegs); public: bool runOnMachineFunction(MachineFunction &MF) override; diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index a08cc2e..1440b96 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -486,11 +486,15 @@ public: /// Insert a range of instructions into the instruction list before I. template void insert(iterator I, IT S, IT E) { + assert((I == end() || I->getParent() == this) && + "iterator points outside of basic block"); Insts.insert(I.getInstrIterator(), S, E); } /// Insert MI into the instruction list before I. iterator insert(iterator I, MachineInstr *MI) { + assert((I == end() || I->getParent() == this) && + "iterator points outside of basic block"); assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && "Cannot insert instruction with bundle flags"); return Insts.insert(I.getInstrIterator(), MI); @@ -498,6 +502,8 @@ public: /// Insert MI into the instruction list after I. iterator insertAfter(iterator I, MachineInstr *MI) { + assert((I == end() || I->getParent() == this) && + "iterator points outside of basic block"); assert(!MI->isBundledWithPred() && !MI->isBundledWithSucc() && "Cannot insert instruction with bundle flags"); return Insts.insertAfter(I.getInstrIterator(), MI); diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h deleted file mode 100644 index 81b0ba1..0000000 --- a/include/llvm/CodeGen/MachineCodeEmitter.h +++ /dev/null @@ -1,334 +0,0 @@ -//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an abstract interface that is used by the machine code -// emission framework to output the code. This allows machine code emission to -// be separated from concerns such as resolution of call targets, and where the -// machine code will be written (memory or disk, f.e.). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H -#define LLVM_CODEGEN_MACHINECODEEMITTER_H - -#include "llvm/IR/DebugLoc.h" -#include "llvm/Support/DataTypes.h" -#include - -namespace llvm { - -class MachineBasicBlock; -class MachineConstantPool; -class MachineJumpTableInfo; -class MachineFunction; -class MachineModuleInfo; -class MachineRelocation; -class Value; -class GlobalValue; -class Function; -class MCSymbol; - -/// MachineCodeEmitter - This class defines two sorts of methods: those for -/// emitting the actual bytes of machine code, and those for emitting auxiliary -/// structures, such as jump tables, relocations, etc. -/// -/// Emission of machine code is complicated by the fact that we don't (in -/// general) know the size of the machine code that we're about to emit before -/// we emit it. As such, we preallocate a certain amount of memory, and set the -/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we -/// emit machine instructions, we advance the CurBufferPtr to indicate the -/// location of the next byte to emit. In the case of a buffer overflow (we -/// need to emit more machine code than we have allocated space for), the -/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire -/// function has been emitted, the overflow condition is checked, and if it has -/// occurred, more memory is allocated, and we reemit the code into it. -/// -class MachineCodeEmitter { - virtual void anchor(); -protected: - /// BufferBegin/BufferEnd - Pointers to the start and end of the memory - /// allocated for this code buffer. - uint8_t *BufferBegin, *BufferEnd; - /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting - /// code. This is guaranteed to be in the range [BufferBegin,BufferEnd]. If - /// this pointer is at BufferEnd, it will never move due to code emission, and - /// all code emission requests will be ignored (this is the buffer overflow - /// condition). - uint8_t *CurBufferPtr; - -public: - virtual ~MachineCodeEmitter() {} - - /// startFunction - This callback is invoked when the specified function is - /// about to be code generated. This initializes the BufferBegin/End/Ptr - /// fields. - /// - virtual void startFunction(MachineFunction &F) = 0; - - /// finishFunction - This callback is invoked when the specified function has - /// finished code generation. If a buffer overflow has occurred, this method - /// returns true (the callee is required to try again), otherwise it returns - /// false. - /// - virtual bool finishFunction(MachineFunction &F) = 0; - - /// emitByte - This callback is invoked when a byte needs to be written to the - /// output stream. - /// - void emitByte(uint8_t B) { - if (CurBufferPtr != BufferEnd) - *CurBufferPtr++ = B; - } - - /// emitWordLE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitWordLE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - emitWordLEInto(CurBufferPtr, W); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitWordLEInto - This callback is invoked when a 32-bit word needs to be - /// written to an arbitrary buffer in little-endian format. Buf must have at - /// least 4 bytes of available space. - /// - static void emitWordLEInto(uint8_t *&Buf, uint32_t W) { - *Buf++ = (uint8_t)(W >> 0); - *Buf++ = (uint8_t)(W >> 8); - *Buf++ = (uint8_t)(W >> 16); - *Buf++ = (uint8_t)(W >> 24); - } - - /// emitWordBE - This callback is invoked when a 32-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitWordBE(uint32_t W) { - if (4 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordLE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in little-endian format. - /// - void emitDWordLE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 0); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 56); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitDWordBE - This callback is invoked when a 64-bit word needs to be - /// written to the output stream in big-endian format. - /// - void emitDWordBE(uint64_t W) { - if (8 <= BufferEnd-CurBufferPtr) { - *CurBufferPtr++ = (uint8_t)(W >> 56); - *CurBufferPtr++ = (uint8_t)(W >> 48); - *CurBufferPtr++ = (uint8_t)(W >> 40); - *CurBufferPtr++ = (uint8_t)(W >> 32); - *CurBufferPtr++ = (uint8_t)(W >> 24); - *CurBufferPtr++ = (uint8_t)(W >> 16); - *CurBufferPtr++ = (uint8_t)(W >> 8); - *CurBufferPtr++ = (uint8_t)(W >> 0); - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitAlignment - Move the CurBufferPtr pointer up to the specified - /// alignment (saturated to BufferEnd of course). - void emitAlignment(unsigned Alignment) { - if (Alignment == 0) Alignment = 1; - - if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) { - // Move the current buffer ptr up to the specified alignment. - CurBufferPtr = - (uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) & - ~(uintptr_t)(Alignment-1)); - } else { - CurBufferPtr = BufferEnd; - } - } - - - /// emitULEB128Bytes - This callback is invoked when a ULEB128 needs to be - /// written to the output stream. - void emitULEB128Bytes(uint64_t Value) { - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - if (Value) Byte |= 0x80; - emitByte(Byte); - } while (Value); - } - - /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be - /// written to the output stream. - void emitSLEB128Bytes(uint64_t Value) { - uint64_t Sign = Value >> (8 * sizeof(Value) - 1); - bool IsMore; - - do { - uint8_t Byte = Value & 0x7f; - Value >>= 7; - IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0; - if (IsMore) Byte |= 0x80; - emitByte(Byte); - } while (IsMore); - } - - /// emitString - This callback is invoked when a String needs to be - /// written to the output stream. - void emitString(const std::string &String) { - for (unsigned i = 0, N = static_cast(String.size()); - i < N; ++i) { - uint8_t C = String[i]; - emitByte(C); - } - emitByte(0); - } - - /// emitInt32 - Emit a int32 directive. - void emitInt32(int32_t Value) { - if (4 <= BufferEnd-CurBufferPtr) { - *((uint32_t*)CurBufferPtr) = Value; - CurBufferPtr += 4; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt64 - Emit a int64 directive. - void emitInt64(uint64_t Value) { - if (8 <= BufferEnd-CurBufferPtr) { - *((uint64_t*)CurBufferPtr) = Value; - CurBufferPtr += 8; - } else { - CurBufferPtr = BufferEnd; - } - } - - /// emitInt32At - Emit the Int32 Value in Addr. - void emitInt32At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint32_t*)Addr) = (uint32_t)Value; - } - - /// emitInt64At - Emit the Int64 Value in Addr. - void emitInt64At(uintptr_t *Addr, uintptr_t Value) { - if (Addr >= (uintptr_t*)BufferBegin && Addr < (uintptr_t*)BufferEnd) - (*(uint64_t*)Addr) = (uint64_t)Value; - } - - /// processDebugLoc - Records debug location information about a - /// MachineInstruction. This is called before emitting any bytes associated - /// with the instruction. Even if successive instructions have the same debug - /// location, this method will be called for each one. - virtual void processDebugLoc(DebugLoc DL, bool BeforePrintintInsn) {} - - /// emitLabel - Emits a label - virtual void emitLabel(MCSymbol *Label) = 0; - - /// allocateSpace - Allocate a block of space in the current output buffer, - /// returning null (and setting conditions to indicate buffer overflow) on - /// failure. Alignment is the alignment in bytes of the buffer desired. - virtual void *allocateSpace(uintptr_t Size, unsigned Alignment) { - emitAlignment(Alignment); - void *Result; - - // Check for buffer overflow. - if (Size >= (uintptr_t)(BufferEnd-CurBufferPtr)) { - CurBufferPtr = BufferEnd; - Result = nullptr; - } else { - // Allocate the space. - Result = CurBufferPtr; - CurBufferPtr += Size; - } - - return Result; - } - - /// StartMachineBasicBlock - This should be called by the target when a new - /// basic block is about to be emitted. This way the MCE knows where the - /// start of the block is, and can implement getMachineBasicBlockAddress. - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; - - /// getCurrentPCValue - This returns the address that the next emitted byte - /// will be output to. - /// - virtual uintptr_t getCurrentPCValue() const { - return (uintptr_t)CurBufferPtr; - } - - /// getCurrentPCOffset - Return the offset from the start of the emitted - /// buffer that we are currently writing to. - virtual uintptr_t getCurrentPCOffset() const { - return CurBufferPtr-BufferBegin; - } - - /// earlyResolveAddresses - True if the code emitter can use symbol addresses - /// during code emission time. The JIT is capable of doing this because it - /// creates jump tables or constant pools in memory on the fly while the - /// object code emitters rely on a linker to have real addresses and should - /// use relocations instead. - virtual bool earlyResolveAddresses() const = 0; - - /// addRelocation - Whenever a relocatable address is needed, it should be - /// noted with this interface. - virtual void addRelocation(const MachineRelocation &MR) = 0; - - /// FIXME: These should all be handled with relocations! - - /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in - /// the constant pool that was last emitted with the emitConstantPool method. - /// - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; - - /// getJumpTableEntryAddress - Return the address of the jump table with index - /// 'Index' in the function that last called initJumpTableInfo. - /// - virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const = 0; - - /// getMachineBasicBlockAddress - Return the address of the specified - /// MachineBasicBlock, only usable after the label for the MBB has been - /// emitted. - /// - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; - - /// getLabelAddress - Return the address of the specified Label, only usable - /// after the LabelID has been emitted. - /// - virtual uintptr_t getLabelAddress(MCSymbol *Label) const = 0; - - /// Specifies the MachineModuleInfo object. This is used for exception handling - /// purposes. - virtual void setModuleInfo(MachineModuleInfo* Info) = 0; -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/CodeGen/MachineCodeInfo.h b/include/llvm/CodeGen/MachineCodeInfo.h deleted file mode 100644 index 820bc87..0000000 --- a/include/llvm/CodeGen/MachineCodeInfo.h +++ /dev/null @@ -1,53 +0,0 @@ -//===-- MachineCodeInfo.h - Class used to report JIT info -------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines MachineCodeInfo, a class used by the JIT ExecutionEngine -// to report information about the generated machine code. -// -// See JIT::runJITOnFunction for usage. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINECODEINFO_H -#define LLVM_CODEGEN_MACHINECODEINFO_H - -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -class MachineCodeInfo { -private: - size_t Size; // Number of bytes in memory used - void *Address; // The address of the function in memory - -public: - MachineCodeInfo() : Size(0), Address(nullptr) {} - - void setSize(size_t s) { - Size = s; - } - - void setAddress(void *a) { - Address = a; - } - - size_t size() const { - return Size; - } - - void *address() const { - return Address; - } - -}; - -} - -#endif - diff --git a/include/llvm/CodeGen/MachineCombinerPattern.h b/include/llvm/CodeGen/MachineCombinerPattern.h new file mode 100644 index 0000000..176af14 --- /dev/null +++ b/include/llvm/CodeGen/MachineCombinerPattern.h @@ -0,0 +1,29 @@ +//===-- llvm/CodeGen/MachineCombinerPattern.h - Instruction pattern supported by +// combiner ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines instruction pattern supported by combiner +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECOMBINERPATTERN_H +#define LLVM_CODEGEN_MACHINECOMBINERPATTERN_H + +namespace llvm { + +/// Enumeration of instruction pattern supported by machine combiner +/// +/// +namespace MachineCombinerPattern { +// Forward declaration +enum MC_PATTERN : int; +} // end namespace MachineCombinerPattern +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index f1ae0bf..a6980a6 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_MACHINEDOMINATORS_H #define LLVM_CODEGEN_MACHINEDOMINATORS_H +#include "llvm/ADT/SmallSet.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -38,6 +39,103 @@ typedef DomTreeNodeBase MachineDomTreeNode; /// compute a normal dominator tree. /// class MachineDominatorTree : public MachineFunctionPass { + /// \brief Helper structure used to hold all the basic blocks + /// involved in the split of a critical edge. + struct CriticalEdge { + MachineBasicBlock *FromBB; + MachineBasicBlock *ToBB; + MachineBasicBlock *NewBB; + CriticalEdge(MachineBasicBlock *FromBB, MachineBasicBlock *ToBB, + MachineBasicBlock *NewBB) + : FromBB(FromBB), ToBB(ToBB), NewBB(NewBB) {} + }; + + /// \brief Pile up all the critical edges to be split. + /// The splitting of a critical edge is local and thus, it is possible + /// to apply several of those changes at the same time. + mutable SmallVector CriticalEdgesToSplit; + /// \brief Remember all the basic blocks that are inserted during + /// edge splitting. + /// Invariant: NewBBs == all the basic blocks contained in the NewBB + /// field of all the elements of CriticalEdgesToSplit. + /// I.e., forall elt in CriticalEdgesToSplit, it exists BB in NewBBs + /// such as BB == elt.NewBB. + mutable SmallSet NewBBs; + + /// \brief Apply all the recorded critical edges to the DT. + /// This updates the underlying DT information in a way that uses + /// the fast query path of DT as much as possible. + /// + /// \post CriticalEdgesToSplit.empty(). + void applySplitCriticalEdges() const { + // Bail out early if there is nothing to do. + if (CriticalEdgesToSplit.empty()) + return; + + // For each element in CriticalEdgesToSplit, remember whether or + // not element is the new immediate domminator of its successor. + // The mapping is done by index, i.e., the information for the ith + // element of CriticalEdgesToSplit is the ith element of IsNewIDom. + SmallVector IsNewIDom; + IsNewIDom.resize(CriticalEdgesToSplit.size()); + size_t Idx = 0; + + // Collect all the dominance properties info, before invalidating + // the underlying DT. + for (CriticalEdge &Edge : CriticalEdgesToSplit) { + // Update dominator information. + MachineBasicBlock *Succ = Edge.ToBB; + MachineDomTreeNode *SucccDTNode = DT->getNode(Succ); + + IsNewIDom[Idx] = true; + for (MachineBasicBlock *PredBB : Succ->predecessors()) { + if (PredBB == Edge.NewBB) + continue; + // If we are in this situation: + // FromBB1 FromBB2 + // + + + // + + + + + // + + + + + // ... Split1 Split2 ... + // + + + // + + + // + + // Succ + // Instead of checking the domiance property with Split2, we + // check it with FromBB2 since Split2 is still unknown of the + // underlying DT structure. + if (NewBBs.count(PredBB)) { + assert(PredBB->pred_size() == 1 && "A basic block resulting from a " + "critical edge split has more " + "than one predecessor!"); + PredBB = *PredBB->pred_begin(); + } + if (!DT->dominates(SucccDTNode, DT->getNode(PredBB))) { + IsNewIDom[Idx] = false; + break; + } + } + ++Idx; + } + + // Now, update DT with the collected dominance properties info. + Idx = 0; + for (CriticalEdge &Edge : CriticalEdgesToSplit) { + // We know FromBB dominates NewBB. + MachineDomTreeNode *NewDTNode = DT->addNewBlock(Edge.NewBB, Edge.FromBB); + MachineDomTreeNode *SucccDTNode = DT->getNode(Edge.ToBB); + + // If all the other predecessors of "Succ" are dominated by "Succ" itself + // then the new block is the new immediate dominator of "Succ". Otherwise, + // the new block doesn't dominate anything. + if (IsNewIDom[Idx]) + DT->changeImmediateDominator(SucccDTNode, NewDTNode); + ++Idx; + } + NewBBs.clear(); + CriticalEdgesToSplit.clear(); + } + public: static char ID; // Pass ID, replacement for typeid DominatorTreeBase* DT; @@ -46,7 +144,10 @@ public: ~MachineDominatorTree(); - DominatorTreeBase& getBase() { return *DT; } + DominatorTreeBase &getBase() { + applySplitCriticalEdges(); + return *DT; + } void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -55,14 +156,17 @@ public: /// dominators, this will always be a single block (the entry node). /// inline const std::vector &getRoots() const { + applySplitCriticalEdges(); return DT->getRoots(); } inline MachineBasicBlock *getRoot() const { + applySplitCriticalEdges(); return DT->getRoot(); } inline MachineDomTreeNode *getRootNode() const { + applySplitCriticalEdges(); return DT->getRootNode(); } @@ -70,17 +174,20 @@ public: inline bool dominates(const MachineDomTreeNode* A, const MachineDomTreeNode* B) const { + applySplitCriticalEdges(); return DT->dominates(A, B); } inline bool dominates(const MachineBasicBlock* A, const MachineBasicBlock* B) const { + applySplitCriticalEdges(); return DT->dominates(A, B); } // dominates - Return true if A dominates B. This performs the // special checks necessary if A and B are in the same basic block. bool dominates(const MachineInstr *A, const MachineInstr *B) const { + applySplitCriticalEdges(); const MachineBasicBlock *BBA = A->getParent(), *BBB = B->getParent(); if (BBA != BBB) return DT->dominates(BBA, BBB); @@ -100,11 +207,13 @@ public: inline bool properlyDominates(const MachineDomTreeNode* A, const MachineDomTreeNode* B) const { + applySplitCriticalEdges(); return DT->properlyDominates(A, B); } inline bool properlyDominates(const MachineBasicBlock* A, const MachineBasicBlock* B) const { + applySplitCriticalEdges(); return DT->properlyDominates(A, B); } @@ -112,10 +221,12 @@ public: /// for basic block A and B. If there is no such block then return NULL. inline MachineBasicBlock *findNearestCommonDominator(MachineBasicBlock *A, MachineBasicBlock *B) { + applySplitCriticalEdges(); return DT->findNearestCommonDominator(A, B); } inline MachineDomTreeNode *operator[](MachineBasicBlock *BB) const { + applySplitCriticalEdges(); return DT->getNode(BB); } @@ -123,6 +234,7 @@ public: /// block. This is the same as using operator[] on this class. /// inline MachineDomTreeNode *getNode(MachineBasicBlock *BB) const { + applySplitCriticalEdges(); return DT->getNode(BB); } @@ -131,6 +243,7 @@ public: /// the children list of the immediate dominator. inline MachineDomTreeNode *addNewBlock(MachineBasicBlock *BB, MachineBasicBlock *DomBB) { + applySplitCriticalEdges(); return DT->addNewBlock(BB, DomBB); } @@ -139,11 +252,13 @@ public: /// inline void changeImmediateDominator(MachineBasicBlock *N, MachineBasicBlock* NewIDom) { + applySplitCriticalEdges(); DT->changeImmediateDominator(N, NewIDom); } inline void changeImmediateDominator(MachineDomTreeNode *N, MachineDomTreeNode* NewIDom) { + applySplitCriticalEdges(); DT->changeImmediateDominator(N, NewIDom); } @@ -151,24 +266,49 @@ public: /// dominate any other blocks. Removes node from its immediate dominator's /// children list. Deletes dominator node associated with basic block BB. inline void eraseNode(MachineBasicBlock *BB) { + applySplitCriticalEdges(); DT->eraseNode(BB); } /// splitBlock - BB is split and now it has one successor. Update dominator /// tree to reflect this change. inline void splitBlock(MachineBasicBlock* NewBB) { + applySplitCriticalEdges(); DT->splitBlock(NewBB); } /// isReachableFromEntry - Return true if A is dominated by the entry /// block of the function containing it. bool isReachableFromEntry(const MachineBasicBlock *A) { + applySplitCriticalEdges(); return DT->isReachableFromEntry(A); } void releaseMemory() override; void print(raw_ostream &OS, const Module*) const override; + + /// \brief Record that the critical edge (FromBB, ToBB) has been + /// split with NewBB. + /// This is best to use this method instead of directly update the + /// underlying information, because this helps mitigating the + /// number of time the DT information is invalidated. + /// + /// \note Do not use this method with regular edges. + /// + /// \note To benefit from the compile time improvement incurred by this + /// method, the users of this method have to limit the queries to the DT + /// interface between two edges splitting. In other words, they have to + /// pack the splitting of critical edges as much as possible. + void recordSplitCriticalEdge(MachineBasicBlock *FromBB, + MachineBasicBlock *ToBB, + MachineBasicBlock *NewBB) { + bool Inserted = NewBBs.insert(NewBB).second; + (void)Inserted; + assert(Inserted && + "A basic block inserted via edge splitting cannot appear twice"); + CriticalEdgesToSplit.push_back(CriticalEdge(FromBB, ToBB, NewBB)); + } }; //===------------------------------------- diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index c51f8fe..6677360 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -109,13 +109,23 @@ class MachineFrameInfo { // block and doesn't need additional handling for allocation beyond that. bool PreAllocated; + // If true, an LLVM IR value might point to this object. + // Normally, spill slots and fixed-offset objects don't alias IR-accessible + // objects, but there are exceptions (on PowerPC, for example, some byval + // arguments have ABI-prescribed offsets). + bool isAliased; + StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, - bool isSS, const AllocaInst *Val) + bool isSS, const AllocaInst *Val, bool A) : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), - isSpillSlot(isSS), Alloca(Val), PreAllocated(false) {} + isSpillSlot(isSS), Alloca(Val), PreAllocated(false), isAliased(A) {} }; - const TargetMachine &TM; + /// StackAlignment - The alignment of the stack. + unsigned StackAlignment; + + /// StackRealignable - Can the stack be realigned. + bool StackRealignable; /// Objects - The list of stack objects allocated... /// @@ -230,10 +240,17 @@ class MachineFrameInfo { /// pointer. bool HasInlineAsmWithSPAdjust; - const TargetFrameLowering *getFrameLowering() const; + /// True if the function contains a call to the llvm.vastart intrinsic. + bool HasVAStart; + + /// True if this is a varargs function that contains a musttail call. + bool HasMustTailInVarArgFunc; + public: - explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) - : TM(TM), RealignOption(RealignOpt) { + explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign, + bool RealignOpt) + : StackAlignment(StackAlign), StackRealignable(isStackRealign), + RealignOption(RealignOpt) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; @@ -250,6 +267,8 @@ public: LocalFrameMaxAlign = 0; UseLocalStackAllocationBlock = false; HasInlineAsmWithSPAdjust = false; + HasVAStart = false; + HasMustTailInVarArgFunc = false; } /// hasStackObjects - Return true if there are any stack objects in this @@ -469,6 +488,14 @@ public: bool hasInlineAsmWithSPAdjust() const { return HasInlineAsmWithSPAdjust; } void setHasInlineAsmWithSPAdjust(bool B) { HasInlineAsmWithSPAdjust = B; } + /// Returns true if the function calls the llvm.va_start intrinsic. + bool hasVAStart() const { return HasVAStart; } + void setHasVAStart(bool B) { HasVAStart = B; } + + /// Returns true if the function is variadic and contains a musttail call. + bool hasMustTailInVarArgFunc() const { return HasMustTailInVarArgFunc; } + void setHasMustTailInVarArgFunc(bool B) { HasMustTailInVarArgFunc = B; } + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be /// allocated for an outgoing function call. This is only available if /// CallFrameSetup/Destroy pseudo instructions are used by the target, and @@ -479,21 +506,34 @@ public: /// CreateFixedObject - Create a new object at a fixed location on the stack. /// All fixed objects should be created before other objects are created for - /// efficiency. By default, fixed objects are immutable. This returns an - /// index with a negative value. + /// efficiency. By default, fixed objects are not pointed to by LLVM IR + /// values. This returns an index with a negative value. /// - int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable); + int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable, + bool isAliased = false); /// CreateFixedSpillStackObject - Create a spill slot at a fixed location /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); + /// Allocates memory at a fixed, target-specific offset from the frame + /// pointer. Marks the function as having its frame address taken. + int CreateFrameAllocation(uint64_t Size); + /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); } + /// isAliasedObjectIndex - Returns true if the specified index corresponds + /// to an object that might be pointed to by an LLVM IR value. + bool isAliasedObjectIndex(int ObjectIdx) const { + assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && + "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].isAliased; + } + /// isImmutableObjectIndex - Returns true if the specified index corresponds /// to an immutable object. bool isImmutableObjectIndex(int ObjectIdx) const { diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 042c62b..4e9ff9e 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -21,6 +21,7 @@ #include "llvm/ADT/ilist.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Metadata.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/ArrayRecycler.h" #include "llvm/Support/Recycler.h" @@ -38,6 +39,7 @@ class MachineModuleInfo; class MCContext; class Pass; class TargetMachine; +class TargetSubtargetInfo; class TargetRegisterClass; struct MachinePointerInfo; @@ -70,15 +72,24 @@ private: /// MachineFunction is destroyed. struct MachineFunctionInfo { virtual ~MachineFunctionInfo(); + + /// \brief Factory function: default behavior is to call new using the + /// supplied allocator. + /// + /// This function can be overridden in a derive class. + template + static Ty *create(BumpPtrAllocator &Allocator, MachineFunction &MF) { + return new (Allocator.Allocate()) Ty(MF); + } }; class MachineFunction { const Function *Fn; const TargetMachine &Target; + const TargetSubtargetInfo *STI; MCContext &Ctx; MachineModuleInfo &MMI; - GCModuleInfo *GMI; - + // RegInfo - Information about each register in use in the function. MachineRegisterInfo *RegInfo; @@ -138,12 +149,10 @@ class MachineFunction { void operator=(const MachineFunction&) LLVM_DELETED_FUNCTION; public: MachineFunction(const Function *Fn, const TargetMachine &TM, - unsigned FunctionNum, MachineModuleInfo &MMI, - GCModuleInfo* GMI); + unsigned FunctionNum, MachineModuleInfo &MMI); ~MachineFunction(); MachineModuleInfo &getMMI() const { return MMI; } - GCModuleInfo *getGMI() const { return GMI; } MCContext &getContext() const { return Ctx; } /// getFunction - Return the LLVM function that this machine code represents @@ -162,6 +171,11 @@ public: /// const TargetMachine &getTarget() const { return Target; } + /// getSubtarget - Return the subtarget for which this machine code is being + /// compiled. + const TargetSubtargetInfo &getSubtarget() const { return *STI; } + void setSubtarget(const TargetSubtargetInfo *ST) { STI = ST; } + /// getRegInfo - Return information about the registers currently in use. /// MachineRegisterInfo &getRegInfo() { return *RegInfo; } @@ -234,7 +248,7 @@ public: template Ty *getInfo() { if (!MFInfo) - MFInfo = new (Allocator.Allocate()) Ty(*this); + MFInfo = Ty::template create(Allocator, *this); return static_cast(MFInfo); } @@ -399,7 +413,7 @@ public: MachineMemOperand *getMachineMemOperand(MachinePointerInfo PtrInfo, unsigned f, uint64_t s, unsigned base_alignment, - const MDNode *TBAAInfo = nullptr, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); /// getMachineMemOperand - Allocate a new MachineMemOperand by copying diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 3c82811..bcf1f5c 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -244,12 +244,22 @@ public: /// DebugLoc getDebugLoc() const { return debugLoc; } - /// getDebugVariable() - Return the debug variable referenced by + /// \brief Return the debug variable referenced by /// this DBG_VALUE instruction. DIVariable getDebugVariable() const { assert(isDebugValue() && "not a DBG_VALUE"); - const MDNode *Var = getOperand(getNumOperands() - 1).getMetadata(); - return DIVariable(Var); + DIVariable Var(getOperand(2).getMetadata()); + assert(Var.Verify() && "not a DIVariable"); + return Var; + } + + /// \brief Return the complex address expression referenced by + /// this DBG_VALUE instruction. + DIExpression getDebugExpression() const { + assert(isDebugValue() && "not a DBG_VALUE"); + DIExpression Expr(getOperand(3).getMetadata()); + assert(Expr.Verify() && "not a DIExpression"); + return Expr; } /// emitError - Emit an error referring to the source location of this @@ -510,6 +520,49 @@ public: return hasProperty(MCID::FoldableAsLoad, Type); } + /// \brief Return true if this instruction behaves + /// the same way as the generic REG_SEQUENCE instructions. + /// E.g., on ARM, + /// dX VMOVDRR rY, rZ + /// is equivalent to + /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1. + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be + /// override accordingly. + bool isRegSequenceLike(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::RegSequence, Type); + } + + /// \brief Return true if this instruction behaves + /// the same way as the generic EXTRACT_SUBREG instructions. + /// E.g., on ARM, + /// rX, rY VMOVRRD dZ + /// is equivalent to two EXTRACT_SUBREG: + /// rX = EXTRACT_SUBREG dZ, ssub_0 + /// rY = EXTRACT_SUBREG dZ, ssub_1 + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be + /// override accordingly. + bool isExtractSubregLike(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::ExtractSubreg, Type); + } + + /// \brief Return true if this instruction behaves + /// the same way as the generic INSERT_SUBREG instructions. + /// E.g., on ARM, + /// dX = VSETLNi32 dY, rZ, Imm + /// is equivalent to a INSERT_SUBREG: + /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm) + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be + /// override accordingly. + bool isInsertSubregLike(QueryType Type = IgnoreBundle) const { + return hasProperty(MCID::InsertSubreg, Type); + } + //===--------------------------------------------------------------------===// // Side Effect Analysis //===--------------------------------------------------------------------===// @@ -614,7 +667,6 @@ public: /// are not marking copies from and to the same register class with this flag. bool isAsCheapAsAMove(QueryType Type = AllInBundle) const { // Only returns true for a bundle if all bundled instructions are cheap. - // FIXME: This probably requires a target hook. return hasProperty(MCID::CheapAsAMove, Type); } @@ -672,6 +724,12 @@ public: /// eraseFromBundle() to erase individual bundled instructions. void eraseFromParent(); + /// Unlink 'this' from the containing basic block and delete it. + /// + /// For all definitions mark their uses in DBG_VALUE nodes + /// as undefined. Otherwise like eraseFromParent(). + void eraseFromParentAndMarkDBGValuesForRemoval(); + /// Unlink 'this' form its basic block and delete it. /// /// If the instruction is part of a bundle, the other instructions in the @@ -1081,7 +1139,10 @@ public: /// setDebugLoc - Replace current source information with new such. /// Avoid using this, the constructor argument is preferable. /// - void setDebugLoc(const DebugLoc dl) { debugLoc = dl; } + void setDebugLoc(const DebugLoc dl) { + debugLoc = dl; + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + } /// RemoveOperand - Erase an operand from an instruction, leaving it with one /// fewer operand than it started with. diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 21a482c..8859b6a 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -58,6 +58,10 @@ public: MachineInstr *operator->() const { return MI; } operator MachineBasicBlock::iterator() const { return MI; } + /// If conversion operators fail, use this method to get the MachineInstr + /// explicitly. + MachineInstr *getInstr() const { return MI; } + /// addReg - Add a new virtual register operand... /// const @@ -170,6 +174,8 @@ public: const MachineInstrBuilder &addMetadata(const MDNode *MD) const { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); + assert((MI->isDebugValue() ? MI->getDebugVariable().Verify() : true) && + "first MDNode argument of a DBG_VALUE not a DIVariable"); return *this; } @@ -345,24 +351,25 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, /// address. The convention is that a DBG_VALUE is indirect iff the /// second operand is an immediate. /// -inline MachineInstrBuilder BuildMI(MachineFunction &MF, - DebugLoc DL, - const MCInstrDesc &MCID, - bool IsIndirect, - unsigned Reg, - unsigned Offset, - const MDNode *MD) { +inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, + const MCInstrDesc &MCID, bool IsIndirect, + unsigned Reg, unsigned Offset, + const MDNode *Variable, const MDNode *Expr) { + assert(DIVariable(Variable).Verify() && "not a DIVariable"); + assert(DIExpression(Expr).Verify() && "not a DIExpression"); if (IsIndirect) return BuildMI(MF, DL, MCID) - .addReg(Reg, RegState::Debug) - .addImm(Offset) - .addMetadata(MD); + .addReg(Reg, RegState::Debug) + .addImm(Offset) + .addMetadata(Variable) + .addMetadata(Expr); else { assert(Offset == 0 && "A direct address cannot have an offset."); return BuildMI(MF, DL, MCID) - .addReg(Reg, RegState::Debug) - .addReg(0U, RegState::Debug) - .addMetadata(MD); + .addReg(Reg, RegState::Debug) + .addReg(0U, RegState::Debug) + .addMetadata(Variable) + .addMetadata(Expr); } } @@ -371,15 +378,15 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, /// address and inserts it at position I. /// inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, - MachineBasicBlock::iterator I, - DebugLoc DL, - const MCInstrDesc &MCID, - bool IsIndirect, - unsigned Reg, - unsigned Offset, - const MDNode *MD) { + MachineBasicBlock::iterator I, DebugLoc DL, + const MCInstrDesc &MCID, bool IsIndirect, + unsigned Reg, unsigned Offset, + const MDNode *Variable, const MDNode *Expr) { + assert(DIVariable(Variable).Verify() && "not a DIVariable"); + assert(DIExpression(Expr).Verify() && "not a DIExpression"); MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, MD); + MachineInstr *MI = + BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr); BB.insert(I, MI); return MachineInstrBuilder(MF, MI); } diff --git a/include/llvm/CodeGen/MachineMemOperand.h b/include/llvm/CodeGen/MachineMemOperand.h index 2532c16..eb5086c 100644 --- a/include/llvm/CodeGen/MachineMemOperand.h +++ b/include/llvm/CodeGen/MachineMemOperand.h @@ -18,6 +18,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" // PointerLikeTypeTraits #include "llvm/Support/DataTypes.h" @@ -91,7 +92,7 @@ class MachineMemOperand { MachinePointerInfo PtrInfo; uint64_t Size; unsigned Flags; - const MDNode *TBAAInfo; + AAMDNodes AAInfo; const MDNode *Ranges; public: @@ -117,7 +118,8 @@ public: /// MachineMemOperand - Construct an MachineMemOperand object with the /// specified PtrInfo, flags, size, and base alignment. MachineMemOperand(MachinePointerInfo PtrInfo, unsigned flags, uint64_t s, - unsigned base_alignment, const MDNode *TBAAInfo = nullptr, + unsigned base_alignment, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); const MachinePointerInfo &getPointerInfo() const { return PtrInfo; } @@ -161,8 +163,8 @@ public: /// base address, without the offset. uint64_t getBaseAlignment() const { return (1u << (Flags >> MOMaxBits)) >> 1; } - /// getTBAAInfo - Return the TBAA tag for the memory reference. - const MDNode *getTBAAInfo() const { return TBAAInfo; } + /// getAAInfo - Return the AA tags for the memory reference. + AAMDNodes getAAInfo() const { return AAInfo; } /// getRanges - Return the range tag for the memory reference. const MDNode *getRanges() const { return Ranges; } diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 6d8d056..f0d0b2d 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -66,6 +66,7 @@ struct LandingPadInfo { MachineBasicBlock *LandingPadBlock; // Landing pad block. SmallVector BeginLabels; // Labels prior to invoke. SmallVector EndLabels; // Labels after invoke. + SmallVector ClauseLabels; // Labels for each clause. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. const Function *Personality; // Personality function. std::vector TypeIds; // List of type ids (filters negative) @@ -110,10 +111,6 @@ class MachineModuleInfo : public ImmutablePass { /// by debug and exception handling consumers. std::vector FrameInstructions; - /// CompactUnwindEncoding - If the target supports it, this is the compact - /// unwind encoding. It replaces a function's CIE and FDE. - uint32_t CompactUnwindEncoding; - /// LandingPads - List of LandingPadInfo describing the landing pad /// information in the current function. std::vector LandingPads; @@ -131,7 +128,7 @@ class MachineModuleInfo : public ImmutablePass { unsigned CurCallSite; /// TypeInfos - List of C++ TypeInfo used in the current function. - std::vector TypeInfos; + std::vector TypeInfos; /// FilterIds - List of typeids encoding filters used in the current function. std::vector FilterIds; @@ -165,13 +162,24 @@ class MachineModuleInfo : public ImmutablePass { /// to _fltused on Windows targets. bool UsesVAFloatArgument; + /// UsesMorestackAddr - True if the module calls the __morestack function + /// indirectly, as is required under the large code model on x86. This is used + /// to emit a definition of a symbol, __morestack_addr, containing the + /// address. See comments in lib/Target/X86/X86FrameLowering.cpp for more + /// details. + bool UsesMorestackAddr; + public: static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - TrackingVH Var; + TrackingMDNodeRef Var; + TrackingMDNodeRef Expr; unsigned Slot; DebugLoc Loc; + + VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) + : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector VariableDbgInfoMapTy; VariableDbgInfoMapTy VariableDbgInfos; @@ -234,6 +242,14 @@ public: UsesVAFloatArgument = b; } + bool usesMorestackAddr() const { + return UsesMorestackAddr; + } + + void setUsesMorestackAddr(bool b) { + UsesMorestackAddr = b; + } + /// \brief Returns a reference to a list of cfi instructions in the current /// function's prologue. Used to construct frame maps for debug and exception /// handling comsumers. @@ -247,15 +263,6 @@ public: return FrameInstructions.size() - 1; } - /// getCompactUnwindEncoding - Returns the compact unwind encoding for a - /// function if the target supports the encoding. This encoding replaces a - /// function's CIE and FDE. - uint32_t getCompactUnwindEncoding() const { return CompactUnwindEncoding; } - - /// setCompactUnwindEncoding - Set the compact unwind encoding for a function - /// if the target supports the encoding. - void setCompactUnwindEncoding(uint32_t Enc) { CompactUnwindEncoding = Enc; } - /// getAddrLabelSymbol - Return the symbol to be used for the specified basic /// block when its address is taken. This cannot be its normal LBB label /// because the block may be accessed outside its containing function. @@ -313,20 +320,25 @@ public: /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. /// void addCatchTypeInfo(MachineBasicBlock *LandingPad, - ArrayRef TyInfo); + ArrayRef TyInfo); /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. /// void addFilterTypeInfo(MachineBasicBlock *LandingPad, - ArrayRef TyInfo); + ArrayRef TyInfo); /// addCleanup - Add a cleanup action for a landing pad. /// void addCleanup(MachineBasicBlock *LandingPad); + /// Add a clause for a landing pad. Returns a new label for the clause. This + /// is used by EH schemes that have more than one landing pad. In this case, + /// each clause gets its own basic block. + MCSymbol *addClauseForLandingPad(MachineBasicBlock *LandingPad); + /// getTypeIDFor - Return the type id for the specified typeinfo. This is /// function wide. - unsigned getTypeIDFor(const GlobalVariable *TI); + unsigned getTypeIDFor(const GlobalValue *TI); /// getFilterIDFor - Return the id of the filter encoded by TyIds. This is /// function wide. @@ -387,7 +399,7 @@ public: /// getTypeInfos - Return a reference to the C++ typeinfo for the current /// function. - const std::vector &getTypeInfos() const { + const std::vector &getTypeInfos() const { return TypeInfos; } @@ -403,9 +415,9 @@ public: /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. - void setVariableDbgInfo(MDNode *N, unsigned Slot, DebugLoc Loc) { - VariableDbgInfo Info = { N, Slot, Loc }; - VariableDbgInfos.push_back(std::move(Info)); + void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, + DebugLoc Loc) { + VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } VariableDbgInfoMapTy &getVariableDbgInfo() { return VariableDbgInfos; } diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 22969bc..eed1e57 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -506,6 +506,11 @@ public: Contents.ImmVal = immVal; } + void setFPImm(const ConstantFP *CFP) { + assert(isFPImm() && "Wrong MachineOperand mutator"); + Contents.CFP = CFP; + } + void setOffset(int64_t Offset) { assert((isGlobal() || isSymbol() || isCPI() || isTargetIndex() || isBlockAddress()) && "Wrong MachineOperand accessor"); @@ -544,6 +549,11 @@ public: /// the setImm method should be used. void ChangeToImmediate(int64_t ImmVal); + /// ChangeToFPImmediate - Replace this operand with a new FP immediate operand + /// of the specified value. If an operand is known to be an FP immediate + /// already, the setFPImm method should be used. + void ChangeToFPImmediate(const ConstantFP *FPImm); + /// ChangeToRegister - Replace this operand with a new register operand of /// the specified value. If an operand is known to be an register already, /// the setReg method should be used. @@ -702,6 +712,8 @@ public: friend class MachineInstr; friend class MachineRegisterInfo; private: + void removeRegFromUses(); + //===--------------------------------------------------------------------===// // Methods for handling register use/def lists. //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index beb2c4f..aab5c40 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -22,7 +22,7 @@ namespace llvm { /// /// PostDominatorTree Class - Concrete subclass of DominatorTree that is used -/// to compute the a post-dominator tree. +/// to compute the post-dominator tree. /// struct MachinePostDominatorTree : public MachineFunctionPass { private: diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 51139f7..caa48a5 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -17,9 +17,10 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBundle.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include namespace llvm { @@ -39,7 +40,7 @@ public: }; private: - const TargetMachine &TM; + const MachineFunction *MF; Delegate *TheDelegate; /// IsSSA - True when the machine function is in SSA form and virtual @@ -51,6 +52,9 @@ private: /// accurate when after this flag is cleared. bool TracksLiveness; + /// True if subregister liveness is tracked. + bool TracksSubRegLiveness; + /// VRegInfo - Information we keep for each virtual register. /// /// Each element in this list contains the register class of the vreg and the @@ -69,7 +73,7 @@ private: /// PhysRegUseDefLists - This is an array of the head of the use/def list for /// physical registers. - MachineOperand **PhysRegUseDefLists; + std::vector PhysRegUseDefLists; /// getRegUseDefListHead - Return the head pointer for the register use/def /// list for the specified virtual or physical register. @@ -122,11 +126,10 @@ private: MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; public: - explicit MachineRegisterInfo(const TargetMachine &TM); - ~MachineRegisterInfo(); + explicit MachineRegisterInfo(const MachineFunction *MF); const TargetRegisterInfo *getTargetRegisterInfo() const { - return TM.getRegisterInfo(); + return MF->getSubtarget().getRegisterInfo(); } void resetDelegate(Delegate *delegate) { @@ -179,6 +182,12 @@ public: /// information. void invalidateLiveness() { TracksLiveness = false; } + bool tracksSubRegLiveness() const { return TracksSubRegLiveness; } + + void enableSubRegLiveness(bool Enable = true) { + TracksSubRegLiveness = Enable; + } + //===--------------------------------------------------------------------===// // Register Info //===--------------------------------------------------------------------===// @@ -515,8 +524,12 @@ public: /// /// That function will return NULL if the virtual registers have incompatible /// constraints. + /// + /// Note that if ToReg is a physical register the function will replace and + /// apply sub registers to ToReg in order to obtain a final/proper physical + /// register. void replaceRegWith(unsigned FromReg, unsigned ToReg); - + /// getVRegDef - Return the machine instr that defines the specified virtual /// register or null if none is found. This assumes that the code is in SSA /// form, so there should only be one definition. @@ -764,6 +777,10 @@ public: const TargetRegisterInfo &TRI, const TargetInstrInfo &TII); + /// Returns a mask covering all bits that can appear in lane masks of + /// subregisters of the virtual register @p Reg. + unsigned getMaxLaneMaskForVReg(unsigned Reg) const; + /// defusechain_iterator - This class provides iterator support for machine /// operands in the function that use or define a specific register. If /// ReturnUses is true it returns uses of registers, if ReturnDefs is true it diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h deleted file mode 100644 index e778457..0000000 --- a/include/llvm/CodeGen/MachineRelocation.h +++ /dev/null @@ -1,342 +0,0 @@ -//===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- C++ -*-===// -// -// 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 MachineRelocation class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_MACHINERELOCATION_H -#define LLVM_CODEGEN_MACHINERELOCATION_H - -#include "llvm/Support/DataTypes.h" -#include - -namespace llvm { -class GlobalValue; -class MachineBasicBlock; - -/// MachineRelocation - This represents a target-specific relocation value, -/// produced by the code emitter. This relocation is resolved after the has -/// been emitted, either to an object file or to memory, when the target of the -/// relocation can be resolved. -/// -/// A relocation is made up of the following logical portions: -/// 1. An offset in the machine code buffer, the location to modify. -/// 2. A target specific relocation type (a number from 0 to 63). -/// 3. A symbol being referenced, either as a GlobalValue* or as a string. -/// 4. An optional constant value to be added to the reference. -/// 5. A bit, CanRewrite, which indicates to the JIT that a function stub is -/// not needed for the relocation. -/// 6. An index into the GOT, if the target uses a GOT -/// -class MachineRelocation { - enum AddressType { - isResult, // Relocation has be transformed into its result pointer. - isGV, // The Target.GV field is valid. - isIndirectSym, // Relocation of an indirect symbol. - isBB, // Relocation of BB address. - isExtSym, // The Target.ExtSym field is valid. - isConstPool, // Relocation of constant pool address. - isJumpTable, // Relocation of jump table address. - isGOTIndex // The Target.GOTIndex field is valid. - }; - - /// Offset - This is the offset from the start of the code buffer of the - /// relocation to perform. - uintptr_t Offset; - - /// ConstantVal - A field that may be used by the target relocation type. - intptr_t ConstantVal; - - union { - void *Result; // If this has been resolved to a resolved pointer - GlobalValue *GV; // If this is a pointer to a GV or an indirect ref. - MachineBasicBlock *MBB; // If this is a pointer to an LLVM BB - const char *ExtSym; // If this is a pointer to a named symbol - unsigned Index; // Constant pool / jump table index - unsigned GOTIndex; // Index in the GOT of this symbol/global - } Target; - - unsigned TargetReloType : 6; // The target relocation ID - AddressType AddrType : 4; // The field of Target to use - bool MayNeedFarStub : 1; // True if this relocation may require a far-stub - bool GOTRelative : 1; // Should this relocation be relative to the GOT? - bool TargetResolve : 1; // True if target should resolve the address - -public: - // Relocation types used in a generic implementation. Currently, relocation - // entries for all things use the generic VANILLA type until they are refined - // into target relocation types. - enum RelocationType { - VANILLA - }; - - /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue. - /// - static MachineRelocation getGV(uintptr_t offset, unsigned RelocationType, - GlobalValue *GV, intptr_t cst = 0, - bool MayNeedFarStub = 0, - bool GOTrelative = 0) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isGV; - Result.MayNeedFarStub = MayNeedFarStub; - Result.GOTRelative = GOTrelative; - Result.TargetResolve = false; - Result.Target.GV = GV; - return Result; - } - - /// MachineRelocation::getIndirectSymbol - Return a relocation entry for an - /// indirect symbol. - static MachineRelocation getIndirectSymbol(uintptr_t offset, - unsigned RelocationType, - GlobalValue *GV, intptr_t cst = 0, - bool MayNeedFarStub = 0, - bool GOTrelative = 0) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isIndirectSym; - Result.MayNeedFarStub = MayNeedFarStub; - Result.GOTRelative = GOTrelative; - Result.TargetResolve = false; - Result.Target.GV = GV; - return Result; - } - - /// MachineRelocation::getBB - Return a relocation entry for a BB. - /// - static MachineRelocation getBB(uintptr_t offset,unsigned RelocationType, - MachineBasicBlock *MBB, intptr_t cst = 0) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isBB; - Result.MayNeedFarStub = false; - Result.GOTRelative = false; - Result.TargetResolve = false; - Result.Target.MBB = MBB; - return Result; - } - - /// MachineRelocation::getExtSym - Return a relocation entry for an external - /// symbol, like "free". - /// - static MachineRelocation getExtSym(uintptr_t offset, unsigned RelocationType, - const char *ES, intptr_t cst = 0, - bool GOTrelative = 0, - bool NeedStub = true) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isExtSym; - Result.MayNeedFarStub = NeedStub; - Result.GOTRelative = GOTrelative; - Result.TargetResolve = false; - Result.Target.ExtSym = ES; - return Result; - } - - /// MachineRelocation::getConstPool - Return a relocation entry for a constant - /// pool entry. - /// - static MachineRelocation getConstPool(uintptr_t offset,unsigned RelocationType, - unsigned CPI, intptr_t cst = 0, - bool letTargetResolve = false) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isConstPool; - Result.MayNeedFarStub = false; - Result.GOTRelative = false; - Result.TargetResolve = letTargetResolve; - Result.Target.Index = CPI; - return Result; - } - - /// MachineRelocation::getJumpTable - Return a relocation entry for a jump - /// table entry. - /// - static MachineRelocation getJumpTable(uintptr_t offset,unsigned RelocationType, - unsigned JTI, intptr_t cst = 0, - bool letTargetResolve = false) { - assert((RelocationType & ~63) == 0 && "Relocation type too large!"); - MachineRelocation Result; - Result.Offset = offset; - Result.ConstantVal = cst; - Result.TargetReloType = RelocationType; - Result.AddrType = isJumpTable; - Result.MayNeedFarStub = false; - Result.GOTRelative = false; - Result.TargetResolve = letTargetResolve; - Result.Target.Index = JTI; - return Result; - } - - /// getMachineCodeOffset - Return the offset into the code buffer that the - /// relocation should be performed. - intptr_t getMachineCodeOffset() const { - return Offset; - } - - /// getRelocationType - Return the target-specific relocation ID for this - /// relocation. - unsigned getRelocationType() const { - return TargetReloType; - } - - /// getConstantVal - Get the constant value associated with this relocation. - /// This is often an offset from the symbol. - /// - intptr_t getConstantVal() const { - return ConstantVal; - } - - /// setConstantVal - Set the constant value associated with this relocation. - /// This is often an offset from the symbol. - /// - void setConstantVal(intptr_t val) { - ConstantVal = val; - } - - /// isGlobalValue - Return true if this relocation is a GlobalValue, as - /// opposed to a constant string. - bool isGlobalValue() const { - return AddrType == isGV; - } - - /// isIndirectSymbol - Return true if this relocation is the address an - /// indirect symbol - bool isIndirectSymbol() const { - return AddrType == isIndirectSym; - } - - /// isBasicBlock - Return true if this relocation is a basic block reference. - /// - bool isBasicBlock() const { - return AddrType == isBB; - } - - /// isExternalSymbol - Return true if this is a constant string. - /// - bool isExternalSymbol() const { - return AddrType == isExtSym; - } - - /// isConstantPoolIndex - Return true if this is a constant pool reference. - /// - bool isConstantPoolIndex() const { - return AddrType == isConstPool; - } - - /// isJumpTableIndex - Return true if this is a jump table reference. - /// - bool isJumpTableIndex() const { - return AddrType == isJumpTable; - } - - /// isGOTRelative - Return true the target wants the index into the GOT of - /// the symbol rather than the address of the symbol. - bool isGOTRelative() const { - return GOTRelative; - } - - /// mayNeedFarStub - This function returns true if the JIT for this target may - /// need either a stub function or an indirect global-variable load to handle - /// the relocated GlobalValue reference. For example, the x86-64 call - /// instruction can only call functions within +/-2GB of the call site. - /// Anything farther away needs a longer mov+call sequence, which can't just - /// be written on top of the existing call. - bool mayNeedFarStub() const { - return MayNeedFarStub; - } - - /// letTargetResolve - Return true if the target JITInfo is usually - /// responsible for resolving the address of this relocation. - bool letTargetResolve() const { - return TargetResolve; - } - - /// getGlobalValue - If this is a global value reference, return the - /// referenced global. - GlobalValue *getGlobalValue() const { - assert((isGlobalValue() || isIndirectSymbol()) && - "This is not a global value reference!"); - return Target.GV; - } - - MachineBasicBlock *getBasicBlock() const { - assert(isBasicBlock() && "This is not a basic block reference!"); - return Target.MBB; - } - - /// getString - If this is a string value, return the string reference. - /// - const char *getExternalSymbol() const { - assert(isExternalSymbol() && "This is not an external symbol reference!"); - return Target.ExtSym; - } - - /// getConstantPoolIndex - If this is a const pool reference, return - /// the index into the constant pool. - unsigned getConstantPoolIndex() const { - assert(isConstantPoolIndex() && "This is not a constant pool reference!"); - return Target.Index; - } - - /// getJumpTableIndex - If this is a jump table reference, return - /// the index into the jump table. - unsigned getJumpTableIndex() const { - assert(isJumpTableIndex() && "This is not a jump table reference!"); - return Target.Index; - } - - /// getResultPointer - Once this has been resolved to point to an actual - /// address, this returns the pointer. - void *getResultPointer() const { - assert(AddrType == isResult && "Result pointer isn't set yet!"); - return Target.Result; - } - - /// setResultPointer - Set the result to the specified pointer value. - /// - void setResultPointer(void *Ptr) { - Target.Result = Ptr; - AddrType = isResult; - } - - /// setGOTIndex - Set the GOT index to a specific value. - void setGOTIndex(unsigned idx) { - AddrType = isGOTIndex; - Target.GOTIndex = idx; - } - - /// getGOTIndex - Once this has been resolved to an entry in the GOT, - /// this returns that index. The index is from the lowest address entry - /// in the GOT. - unsigned getGOTIndex() const { - assert(AddrType == isGOTIndex); - return Target.GOTIndex; - } -}; -} - -#endif diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 7d85432..a319401 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -80,7 +80,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" - #include namespace llvm { @@ -250,7 +249,7 @@ protected: public: ScheduleDAGMI(MachineSchedContext *C, std::unique_ptr S, bool IsPostRA) - : ScheduleDAGInstrs(*C->MF, *C->MLI, *C->MDT, IsPostRA, + : ScheduleDAGInstrs(*C->MF, C->MLI, IsPostRA, /*RemoveKillFlags=*/IsPostRA, C->LIS), AA(C->AA), SchedImpl(std::move(S)), Topo(SUnits, &ExitSU), CurrentTop(), CurrentBottom(), NextClusterPred(nullptr), NextClusterSucc(nullptr) { diff --git a/include/llvm/CodeGen/MachineTraceMetrics.h b/include/llvm/CodeGen/MachineTraceMetrics.h index 323b694..bfe6e94 100644 --- a/include/llvm/CodeGen/MachineTraceMetrics.h +++ b/include/llvm/CodeGen/MachineTraceMetrics.h @@ -44,8 +44,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_MACHINE_TRACE_METRICS_H -#define LLVM_CODEGEN_MACHINE_TRACE_METRICS_H +#ifndef LLVM_CODEGEN_MACHINETRACEMETRICS_H +#define LLVM_CODEGEN_MACHINETRACEMETRICS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -264,8 +264,9 @@ public: /// classes are included. For the caller to account for extra machine /// instructions, it must first resolve each instruction's scheduling class. unsigned getResourceLength( - ArrayRef Extrablocks = None, - ArrayRef ExtraInstrs = None) const; + ArrayRef Extrablocks = None, + ArrayRef ExtraInstrs = None, + ArrayRef RemoveInstrs = None) const; /// Return the length of the (data dependency) critical path through the /// trace. @@ -286,6 +287,12 @@ public: /// Return the Depth of a PHI instruction in a trace center block successor. /// The PHI does not have to be part of the trace. unsigned getPHIDepth(const MachineInstr *PHI) const; + + /// A dependence is useful if the basic block of the defining instruction + /// is part of the trace of the user instruction. It is assumed that DefMI + /// dominates UseMI (see also isUsefulDominator). + bool isDepInTrace(const MachineInstr *DefMI, + const MachineInstr *UseMI) const; }; /// A trace ensemble is a collection of traces selected using the same diff --git a/include/llvm/CodeGen/MachineValueType.h b/include/llvm/CodeGen/MachineValueType.h index ad215ec..e3fbfe8 100644 --- a/include/llvm/CodeGen/MachineValueType.h +++ b/include/llvm/CodeGen/MachineValueType.h @@ -15,6 +15,7 @@ #ifndef LLVM_CODEGEN_MACHINEVALUETYPE_H #define LLVM_CODEGEN_MACHINEVALUETYPE_H +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" @@ -118,6 +119,7 @@ namespace llvm { // unspecified type. The register class // will be determined by the opcode. + FIRST_VALUETYPE = 0, // This is always the beginning of the list. LAST_VALUETYPE = 58, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. @@ -165,6 +167,12 @@ namespace llvm { bool operator>=(const MVT& S) const { return SimpleTy >= S.SimpleTy; } bool operator<=(const MVT& S) const { return SimpleTy <= S.SimpleTy; } + /// isValid - Return true if this is a valid simple valuetype. + bool isValid() const { + return (SimpleTy >= MVT::FIRST_VALUETYPE && + SimpleTy < MVT::LAST_VALUETYPE); + } + /// isFloatingPoint - Return true if this is a FP, or a vector FP type. bool isFloatingPoint() const { return ((SimpleTy >= MVT::FIRST_FP_VALUETYPE && @@ -196,21 +204,24 @@ namespace llvm { /// is32BitVector - Return true if this is a 32-bit vector type. bool is32BitVector() const { return (SimpleTy == MVT::v4i8 || SimpleTy == MVT::v2i16 || - SimpleTy == MVT::v1i32); + SimpleTy == MVT::v1i32 || SimpleTy == MVT::v2f16 || + SimpleTy == MVT::v1f32); } /// is64BitVector - Return true if this is a 64-bit vector type. bool is64BitVector() const { return (SimpleTy == MVT::v8i8 || SimpleTy == MVT::v4i16 || SimpleTy == MVT::v2i32 || SimpleTy == MVT::v1i64 || - SimpleTy == MVT::v1f64 || SimpleTy == MVT::v2f32); + SimpleTy == MVT::v4f16 || SimpleTy == MVT::v2f32 || + SimpleTy == MVT::v1f64); } /// is128BitVector - Return true if this is a 128-bit vector type. bool is128BitVector() const { return (SimpleTy == MVT::v16i8 || SimpleTy == MVT::v8i16 || SimpleTy == MVT::v4i32 || SimpleTy == MVT::v2i64 || - SimpleTy == MVT::v4f32 || SimpleTy == MVT::v2f64); + SimpleTy == MVT::v8f16 || SimpleTy == MVT::v4f32 || + SimpleTy == MVT::v2f64); } /// is256BitVector - Return true if this is a 256-bit vector type. @@ -572,6 +583,52 @@ namespace llvm { /// returned as Other, otherwise they are invalid. static MVT getVT(Type *Ty, bool HandleUnknown = false); + private: + /// A simple iterator over the MVT::SimpleValueType enum. + struct mvt_iterator { + SimpleValueType VT; + mvt_iterator(SimpleValueType VT) : VT(VT) {} + MVT operator*() const { return VT; } + bool operator!=(const mvt_iterator &LHS) const { return VT != LHS.VT; } + mvt_iterator& operator++() { + VT = (MVT::SimpleValueType)((int)VT + 1); + assert((int)VT <= MVT::MAX_ALLOWED_VALUETYPE && + "MVT iterator overflowed."); + return *this; + } + }; + /// A range of the MVT::SimpleValueType enum. + typedef iterator_range mvt_range; + + public: + /// SimpleValueType Iteration + /// @{ + static mvt_range all_valuetypes() { + return mvt_range(MVT::FIRST_VALUETYPE, MVT::LAST_VALUETYPE); + } + static mvt_range integer_valuetypes() { + return mvt_range(MVT::FIRST_INTEGER_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VALUETYPE + 1)); + } + static mvt_range fp_valuetypes() { + return mvt_range(MVT::FIRST_FP_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VALUETYPE + 1)); + } + static mvt_range vector_valuetypes() { + return mvt_range(MVT::FIRST_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_VECTOR_VALUETYPE + 1)); + } + static mvt_range integer_vector_valuetypes() { + return mvt_range( + MVT::FIRST_INTEGER_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_INTEGER_VECTOR_VALUETYPE + 1)); + } + static mvt_range fp_vector_valuetypes() { + return mvt_range( + MVT::FIRST_FP_VECTOR_VALUETYPE, + (MVT::SimpleValueType)(MVT::LAST_FP_VECTOR_VALUETYPE + 1)); + } + /// @} }; } // End llvm namespace diff --git a/include/llvm/CodeGen/PBQP/CostAllocator.h b/include/llvm/CodeGen/PBQP/CostAllocator.h index ff62c09..02d39fe 100644 --- a/include/llvm/CodeGen/PBQP/CostAllocator.h +++ b/include/llvm/CodeGen/PBQP/CostAllocator.h @@ -15,117 +15,101 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_COSTALLOCATOR_H -#define LLVM_COSTALLOCATOR_H +#ifndef LLVM_CODEGEN_PBQP_COSTALLOCATOR_H +#define LLVM_CODEGEN_PBQP_COSTALLOCATOR_H -#include +#include "llvm/ADT/DenseSet.h" +#include #include +namespace llvm { namespace PBQP { -template -class CostPool { +template +class ValuePool { public: + typedef std::shared_ptr PoolRef; - class PoolEntry { +private: + + class PoolEntry : public std::enable_shared_from_this { public: - template - PoolEntry(CostPool &pool, CostKeyT cost) - : pool(pool), cost(std::move(cost)), refCount(0) {} - ~PoolEntry() { pool.removeEntry(this); } - void incRef() { ++refCount; } - bool decRef() { --refCount; return (refCount == 0); } - CostT& getCost() { return cost; } - const CostT& getCost() const { return cost; } + template + PoolEntry(ValuePool &Pool, ValueKeyT Value) + : Pool(Pool), Value(std::move(Value)) {} + ~PoolEntry() { Pool.removeEntry(this); } + const ValueT& getValue() const { return Value; } private: - CostPool &pool; - CostT cost; - std::size_t refCount; + ValuePool &Pool; + ValueT Value; }; - class PoolRef { + class PoolEntryDSInfo { public: - PoolRef(PoolEntry *entry) : entry(entry) { - this->entry->incRef(); + static inline PoolEntry* getEmptyKey() { return nullptr; } + + static inline PoolEntry* getTombstoneKey() { + return reinterpret_cast(static_cast(1)); } - PoolRef(const PoolRef &r) { - entry = r.entry; - entry->incRef(); + + template + static unsigned getHashValue(const ValueKeyT &C) { + return hash_value(C); } - PoolRef& operator=(const PoolRef &r) { - assert(entry != nullptr && "entry should not be null."); - PoolEntry *temp = r.entry; - temp->incRef(); - entry->decRef(); - entry = temp; - return *this; + + static unsigned getHashValue(PoolEntry *P) { + return getHashValue(P->getValue()); } - ~PoolRef() { - if (entry->decRef()) - delete entry; + static unsigned getHashValue(const PoolEntry *P) { + return getHashValue(P->getValue()); } - void reset(PoolEntry *entry) { - entry->incRef(); - this->entry->decRef(); - this->entry = entry; + + template + static + bool isEqual(const ValueKeyT1 &C1, const ValueKeyT2 &C2) { + return C1 == C2; } - CostT& operator*() { return entry->getCost(); } - const CostT& operator*() const { return entry->getCost(); } - CostT* operator->() { return &entry->getCost(); } - const CostT* operator->() const { return &entry->getCost(); } - private: - PoolEntry *entry; - }; -private: - class EntryComparator { - public: - template - typename std::enable_if< - !std::is_same::type>::value, - bool>::type - operator()(const PoolEntry* a, const CostKeyT &b) { - return compare(a->getCost(), b); + template + static bool isEqual(const ValueKeyT &C, PoolEntry *P) { + if (P == getEmptyKey() || P == getTombstoneKey()) + return false; + return isEqual(C, P->getValue()); } - bool operator()(const PoolEntry* a, const PoolEntry* b) { - return compare(a->getCost(), b->getCost()); + + static bool isEqual(PoolEntry *P1, PoolEntry *P2) { + if (P1 == getEmptyKey() || P1 == getTombstoneKey()) + return P1 == P2; + return isEqual(P1->getValue(), P2); } - private: - CostKeyTComparator compare; + }; - typedef std::set EntrySet; + typedef DenseSet EntrySetT; - EntrySet entrySet; + EntrySetT EntrySet; - void removeEntry(PoolEntry *p) { entrySet.erase(p); } + void removeEntry(PoolEntry *P) { EntrySet.erase(P); } public: + template PoolRef getValue(ValueKeyT ValueKey) { + typename EntrySetT::iterator I = EntrySet.find_as(ValueKey); - template - PoolRef getCost(CostKeyT costKey) { - typename EntrySet::iterator itr = - std::lower_bound(entrySet.begin(), entrySet.end(), costKey, - EntryComparator()); - - if (itr != entrySet.end() && costKey == (*itr)->getCost()) - return PoolRef(*itr); + if (I != EntrySet.end()) + return PoolRef((*I)->shared_from_this(), &(*I)->getValue()); - PoolEntry *p = new PoolEntry(*this, std::move(costKey)); - entrySet.insert(itr, p); - return PoolRef(p); + auto P = std::make_shared(*this, std::move(ValueKey)); + EntrySet.insert(P.get()); + return PoolRef(std::move(P), &P->getValue()); } }; -template +template class PoolCostAllocator { private: - typedef CostPool VectorCostPool; - typedef CostPool MatrixCostPool; + typedef ValuePool VectorCostPool; + typedef ValuePool MatrixCostPool; public: typedef VectorT Vector; typedef MatrixT Matrix; @@ -133,15 +117,16 @@ public: typedef typename MatrixCostPool::PoolRef MatrixPtr; template - VectorPtr getVector(VectorKeyT v) { return vectorPool.getCost(std::move(v)); } + VectorPtr getVector(VectorKeyT v) { return VectorPool.getValue(std::move(v)); } template - MatrixPtr getMatrix(MatrixKeyT m) { return matrixPool.getCost(std::move(m)); } + MatrixPtr getMatrix(MatrixKeyT m) { return MatrixPool.getValue(std::move(m)); } private: - VectorCostPool vectorPool; - MatrixCostPool matrixPool; + VectorCostPool VectorPool; + MatrixCostPool MatrixPool; }; -} +} // namespace PBQP +} // namespace llvm -#endif // LLVM_COSTALLOCATOR_H +#endif diff --git a/include/llvm/CodeGen/PBQP/Graph.h b/include/llvm/CodeGen/PBQP/Graph.h index a55f0ea..4dc5674 100644 --- a/include/llvm/CodeGen/PBQP/Graph.h +++ b/include/llvm/CodeGen/PBQP/Graph.h @@ -17,11 +17,12 @@ #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" -#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" #include #include #include +namespace llvm { namespace PBQP { class GraphBase { @@ -29,12 +30,12 @@ namespace PBQP { typedef unsigned NodeId; typedef unsigned EdgeId; - /// \brief Returns a value representing an invalid (non-existent) node. + /// @brief Returns a value representing an invalid (non-existent) node. static NodeId invalidNodeId() { return std::numeric_limits::max(); } - /// \brief Returns a value representing an invalid (non-existent) edge. + /// @brief Returns a value representing an invalid (non-existent) edge. static EdgeId invalidEdgeId() { return std::numeric_limits::max(); } @@ -56,6 +57,7 @@ namespace PBQP { typedef typename CostAllocator::MatrixPtr MatrixPtr; typedef typename SolverT::NodeMetadata NodeMetadata; typedef typename SolverT::EdgeMetadata EdgeMetadata; + typedef typename SolverT::GraphMetadata GraphMetadata; private: @@ -172,6 +174,7 @@ namespace PBQP { // ----- MEMBERS ----- + GraphMetadata Metadata; CostAllocator CostAlloc; SolverT *Solver; @@ -187,13 +190,19 @@ namespace PBQP { // ----- INTERNAL METHODS ----- - NodeEntry& getNode(NodeId NId) { return Nodes[NId]; } - const NodeEntry& getNode(NodeId NId) const { return Nodes[NId]; } + NodeEntry &getNode(NodeId NId) { + assert(NId < Nodes.size() && "Out of bound NodeId"); + return Nodes[NId]; + } + const NodeEntry &getNode(NodeId NId) const { + assert(NId < Nodes.size() && "Out of bound NodeId"); + return Nodes[NId]; + } EdgeEntry& getEdge(EdgeId EId) { return Edges[EId]; } const EdgeEntry& getEdge(EdgeId EId) const { return Edges[EId]; } - NodeId addConstructedNode(const NodeEntry &N) { + NodeId addConstructedNode(NodeEntry N) { NodeId NId = 0; if (!FreeNodeIds.empty()) { NId = FreeNodeIds.back(); @@ -206,7 +215,7 @@ namespace PBQP { return NId; } - EdgeId addConstructedEdge(const EdgeEntry &E) { + EdgeId addConstructedEdge(EdgeEntry E) { assert(findEdge(E.getN1Id(), E.getN2Id()) == invalidEdgeId() && "Attempt to add duplicate edge."); EdgeId EId = 0; @@ -235,6 +244,12 @@ namespace PBQP { class NodeItr { public: + typedef std::forward_iterator_tag iterator_category; + typedef NodeId value_type; + typedef int difference_type; + typedef NodeId* pointer; + typedef NodeId& reference; + NodeItr(NodeId CurNId, const Graph &G) : CurNId(CurNId), EndNId(G.Nodes.size()), FreeNodeIds(G.FreeNodeIds) { this->CurNId = findNextInUse(CurNId); // Move to first in-use node id @@ -249,7 +264,7 @@ namespace PBQP { NodeId findNextInUse(NodeId NId) const { while (NId < EndNId && std::find(FreeNodeIds.begin(), FreeNodeIds.end(), NId) != - FreeNodeIds.end()) { + FreeNodeIds.end()) { ++NId; } return NId; @@ -328,10 +343,19 @@ namespace PBQP { const NodeEntry &NE; }; - /// \brief Construct an empty PBQP graph. - Graph() : Solver(nullptr) { } + /// @brief Construct an empty PBQP graph. + Graph() : Solver(nullptr) {} + + /// @brief Construct an empty PBQP graph with the given graph metadata. + Graph(GraphMetadata Metadata) : Metadata(Metadata), Solver(nullptr) {} + + /// @brief Get a reference to the graph metadata. + GraphMetadata& getMetadata() { return Metadata; } - /// \brief Lock this graph to the given solver instance in preparation + /// @brief Get a const-reference to the graph metadata. + const GraphMetadata& getMetadata() const { return Metadata; } + + /// @brief Lock this graph to the given solver instance in preparation /// for running the solver. This method will call solver.handleAddNode for /// each node in the graph, and handleAddEdge for each edge, to give the /// solver an opportunity to set up any requried metadata. @@ -344,13 +368,13 @@ namespace PBQP { Solver->handleAddEdge(EId); } - /// \brief Release from solver instance. + /// @brief Release from solver instance. void unsetSolver() { assert(Solver && "Solver not set."); Solver = nullptr; } - /// \brief Add a node with the given costs. + /// @brief Add a node with the given costs. /// @param Costs Cost vector for the new node. /// @return Node iterator for the added node. template @@ -363,9 +387,29 @@ namespace PBQP { return NId; } - /// \brief Add an edge between the given nodes with the given costs. + /// @brief Add a node bypassing the cost allocator. + /// @param Costs Cost vector ptr for the new node (must be convertible to + /// VectorPtr). + /// @return Node iterator for the added node. + /// + /// This method allows for fast addition of a node whose costs don't need + /// to be passed through the cost allocator. The most common use case for + /// this is when duplicating costs from an existing node (when using a + /// pooling allocator). These have already been uniqued, so we can avoid + /// re-constructing and re-uniquing them by attaching them directly to the + /// new node. + template + NodeId addNodeBypassingCostAllocator(OtherVectorPtrT Costs) { + NodeId NId = addConstructedNode(NodeEntry(Costs)); + if (Solver) + Solver->handleAddNode(NId); + return NId; + } + + /// @brief Add an edge between the given nodes with the given costs. /// @param N1Id First node. /// @param N2Id Second node. + /// @param Costs Cost matrix for new edge. /// @return Edge iterator for the added edge. template EdgeId addEdge(NodeId N1Id, NodeId N2Id, OtherVectorT Costs) { @@ -380,7 +424,32 @@ namespace PBQP { return EId; } - /// \brief Returns true if the graph is empty. + /// @brief Add an edge bypassing the cost allocator. + /// @param N1Id First node. + /// @param N2Id Second node. + /// @param Costs Cost matrix for new edge. + /// @return Edge iterator for the added edge. + /// + /// This method allows for fast addition of an edge whose costs don't need + /// to be passed through the cost allocator. The most common use case for + /// this is when duplicating costs from an existing edge (when using a + /// pooling allocator). These have already been uniqued, so we can avoid + /// re-constructing and re-uniquing them by attaching them directly to the + /// new edge. + template + NodeId addEdgeBypassingCostAllocator(NodeId N1Id, NodeId N2Id, + OtherMatrixPtrT Costs) { + assert(getNodeCosts(N1Id).getLength() == Costs->getRows() && + getNodeCosts(N2Id).getLength() == Costs->getCols() && + "Matrix dimensions mismatch."); + // Get cost matrix from the problem domain. + EdgeId EId = addConstructedEdge(EdgeEntry(N1Id, N2Id, Costs)); + if (Solver) + Solver->handleAddEdge(EId); + return EId; + } + + /// @brief Returns true if the graph is empty. bool empty() const { return NodeIdSet(*this).empty(); } NodeIdSet nodeIds() const { return NodeIdSet(*this); } @@ -388,15 +457,15 @@ namespace PBQP { AdjEdgeIdSet adjEdgeIds(NodeId NId) { return AdjEdgeIdSet(getNode(NId)); } - /// \brief Get the number of nodes in the graph. + /// @brief Get the number of nodes in the graph. /// @return Number of nodes in the graph. unsigned getNumNodes() const { return NodeIdSet(*this).size(); } - /// \brief Get the number of edges in the graph. + /// @brief Get the number of edges in the graph. /// @return Number of edges in the graph. unsigned getNumEdges() const { return EdgeIdSet(*this).size(); } - /// \brief Set a node's cost vector. + /// @brief Set a node's cost vector. /// @param NId Node to update. /// @param Costs New costs to set. template @@ -407,11 +476,23 @@ namespace PBQP { getNode(NId).Costs = AllocatedCosts; } - /// \brief Get a node's cost vector (const version). + /// @brief Get a VectorPtr to a node's cost vector. Rarely useful - use + /// getNodeCosts where possible. + /// @param NId Node id. + /// @return VectorPtr to node cost vector. + /// + /// This method is primarily useful for duplicating costs quickly by + /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer + /// getNodeCosts when dealing with node cost values. + const VectorPtr& getNodeCostsPtr(NodeId NId) const { + return getNode(NId).Costs; + } + + /// @brief Get a node's cost vector. /// @param NId Node id. /// @return Node cost vector. const Vector& getNodeCosts(NodeId NId) const { - return *getNode(NId).Costs; + return *getNodeCostsPtr(NId); } NodeMetadata& getNodeMetadata(NodeId NId) { @@ -426,7 +507,7 @@ namespace PBQP { return getNode(NId).getAdjEdgeIds().size(); } - /// \brief Set an edge's cost matrix. + /// @brief Set an edge's cost matrix. /// @param EId Edge id. /// @param Costs New cost matrix. template @@ -437,34 +518,48 @@ namespace PBQP { getEdge(EId).Costs = AllocatedCosts; } - /// \brief Get an edge's cost matrix (const version). + /// @brief Get a MatrixPtr to a node's cost matrix. Rarely useful - use + /// getEdgeCosts where possible. + /// @param EId Edge id. + /// @return MatrixPtr to edge cost matrix. + /// + /// This method is primarily useful for duplicating costs quickly by + /// bypassing the cost allocator. See addNodeBypassingCostAllocator. Prefer + /// getEdgeCosts when dealing with edge cost values. + const MatrixPtr& getEdgeCostsPtr(EdgeId EId) const { + return getEdge(EId).Costs; + } + + /// @brief Get an edge's cost matrix. /// @param EId Edge id. /// @return Edge cost matrix. - const Matrix& getEdgeCosts(EdgeId EId) const { return *getEdge(EId).Costs; } + const Matrix& getEdgeCosts(EdgeId EId) const { + return *getEdge(EId).Costs; + } - EdgeMetadata& getEdgeMetadata(EdgeId NId) { - return getEdge(NId).Metadata; + EdgeMetadata& getEdgeMetadata(EdgeId EId) { + return getEdge(EId).Metadata; } - const EdgeMetadata& getEdgeMetadata(EdgeId NId) const { - return getEdge(NId).Metadata; + const EdgeMetadata& getEdgeMetadata(EdgeId EId) const { + return getEdge(EId).Metadata; } - /// \brief Get the first node connected to this edge. + /// @brief Get the first node connected to this edge. /// @param EId Edge id. /// @return The first node connected to the given edge. NodeId getEdgeNode1Id(EdgeId EId) { return getEdge(EId).getN1Id(); } - /// \brief Get the second node connected to this edge. + /// @brief Get the second node connected to this edge. /// @param EId Edge id. /// @return The second node connected to the given edge. NodeId getEdgeNode2Id(EdgeId EId) { return getEdge(EId).getN2Id(); } - /// \brief Get the "other" node connected to this edge. + /// @brief Get the "other" node connected to this edge. /// @param EId Edge id. /// @param NId Node id for the "given" node. /// @return The iterator for the "other" node connected to this edge. @@ -476,7 +571,7 @@ namespace PBQP { return E.getN1Id(); } - /// \brief Get the edge connecting two nodes. + /// @brief Get the edge connecting two nodes. /// @param N1Id First node id. /// @param N2Id Second node id. /// @return An id for edge (N1Id, N2Id) if such an edge exists, @@ -491,7 +586,7 @@ namespace PBQP { return invalidEdgeId(); } - /// \brief Remove a node from the graph. + /// @brief Remove a node from the graph. /// @param NId Node id. void removeNode(NodeId NId) { if (Solver) @@ -499,7 +594,7 @@ namespace PBQP { NodeEntry &N = getNode(NId); // TODO: Can this be for-each'd? for (AdjEdgeItr AEItr = N.adjEdgesBegin(), - AEEnd = N.adjEdgesEnd(); + AEEnd = N.adjEdgesEnd(); AEItr != AEEnd;) { EdgeId EId = *AEItr; ++AEItr; @@ -508,7 +603,7 @@ namespace PBQP { FreeNodeIds.push_back(NId); } - /// \brief Disconnect an edge from the given node. + /// @brief Disconnect an edge from the given node. /// /// Removes the given edge from the adjacency list of the given node. /// This operation leaves the edge in an 'asymmetric' state: It will no @@ -541,14 +636,14 @@ namespace PBQP { E.disconnectFrom(*this, NId); } - /// \brief Convenience method to disconnect all neighbours from the given + /// @brief Convenience method to disconnect all neighbours from the given /// node. void disconnectAllNeighborsFromNode(NodeId NId) { for (auto AEId : adjEdgeIds(NId)) disconnectEdge(AEId, getEdgeOtherNodeId(AEId, NId)); } - /// \brief Re-attach an edge to its nodes. + /// @brief Re-attach an edge to its nodes. /// /// Adds an edge that had been previously disconnected back into the /// adjacency set of the nodes that the edge connects. @@ -559,7 +654,7 @@ namespace PBQP { Solver->handleReconnectEdge(EId, NId); } - /// \brief Remove an edge from the graph. + /// @brief Remove an edge from the graph. /// @param EId Edge id. void removeEdge(EdgeId EId) { if (Solver) @@ -570,7 +665,7 @@ namespace PBQP { Edges[EId].invalidate(); } - /// \brief Remove all nodes and edges from the graph. + /// @brief Remove all nodes and edges from the graph. void clear() { Nodes.clear(); FreeNodeIds.clear(); @@ -578,9 +673,9 @@ namespace PBQP { FreeEdgeIds.clear(); } - /// \brief Dump a graph to an output stream. + /// @brief Dump a graph to an output stream. template - void dump(OStream &OS) { + void dumpToStream(OStream &OS) { OS << nodeIds().size() << " " << edgeIds().size() << "\n"; for (auto NId : nodeIds()) { @@ -613,7 +708,12 @@ namespace PBQP { } } - /// \brief Print a representation of this graph in DOT format. + /// @brief Dump this graph to dbgs(). + void dump() { + dumpToStream(dbgs()); + } + + /// @brief Print a representation of this graph in DOT format. /// @param OS Output stream to print on. template void printDot(OStream &OS) { @@ -637,6 +737,7 @@ namespace PBQP { } }; -} +} // namespace PBQP +} // namespace llvm #endif // LLVM_CODEGEN_PBQP_GRAPH_HPP diff --git a/include/llvm/CodeGen/PBQP/Math.h b/include/llvm/CodeGen/PBQP/Math.h index 69a9d83..2792608 100644 --- a/include/llvm/CodeGen/PBQP/Math.h +++ b/include/llvm/CodeGen/PBQP/Math.h @@ -10,17 +10,19 @@ #ifndef LLVM_CODEGEN_PBQP_MATH_H #define LLVM_CODEGEN_PBQP_MATH_H +#include "llvm/ADT/Hashing.h" #include #include #include +namespace llvm { namespace PBQP { typedef float PBQPNum; /// \brief PBQP Vector class. class Vector { - friend class VectorComparator; + friend hash_code hash_value(const Vector &); public: /// \brief Construct a PBQP vector of the given size. @@ -136,21 +138,12 @@ private: PBQPNum *Data; }; -class VectorComparator { -public: - bool operator()(const Vector &A, const Vector &B) { - if (A.Length < B.Length) - return true; - if (B.Length < A.Length) - return false; - char *AData = reinterpret_cast(A.Data); - char *BData = reinterpret_cast(B.Data); - return std::lexicographical_compare(AData, - AData + A.Length * sizeof(PBQPNum), - BData, - BData + A.Length * sizeof(PBQPNum)); - } -}; +/// \brief Return a hash_value for the given vector. +inline hash_code hash_value(const Vector &V) { + unsigned *VBegin = reinterpret_cast(V.Data); + unsigned *VEnd = reinterpret_cast(V.Data + V.Length); + return hash_combine(V.Length, hash_combine_range(VBegin, VEnd)); +} /// \brief Output a textual representation of the given vector on the given /// output stream. @@ -166,11 +159,10 @@ OStream& operator<<(OStream &OS, const Vector &V) { return OS; } - /// \brief PBQP Matrix class class Matrix { private: - friend class MatrixComparator; + friend hash_code hash_value(const Matrix &); public: /// \brief Construct a PBQP Matrix with the given dimensions. @@ -384,24 +376,12 @@ private: PBQPNum *Data; }; -class MatrixComparator { -public: - bool operator()(const Matrix &A, const Matrix &B) { - if (A.Rows < B.Rows) - return true; - if (B.Rows < A.Rows) - return false; - if (A.Cols < B.Cols) - return true; - if (B.Cols < A.Cols) - return false; - char *AData = reinterpret_cast(A.Data); - char *BData = reinterpret_cast(B.Data); - return std::lexicographical_compare( - AData, AData + (A.Rows * A.Cols * sizeof(PBQPNum)), - BData, BData + (A.Rows * A.Cols * sizeof(PBQPNum))); - } -}; +/// \brief Return a hash_code for the given matrix. +inline hash_code hash_value(const Matrix &M) { + unsigned *MBegin = reinterpret_cast(M.Data); + unsigned *MEnd = reinterpret_cast(M.Data + (M.Rows * M.Cols)); + return hash_combine(M.Rows, M.Cols, hash_combine_range(MBegin, MEnd)); +} /// \brief Output a textual representation of the given matrix on the given /// output stream. @@ -409,7 +389,7 @@ template OStream& operator<<(OStream &OS, const Matrix &M) { assert((M.getRows() != 0) && "Zero-row matrix badness."); for (unsigned i = 0; i < M.getRows(); ++i) - OS << M.getRowAsVector(i); + OS << M.getRowAsVector(i) << "\n"; return OS; } @@ -424,6 +404,11 @@ private: }; template +inline hash_code hash_value(const MDVector &V) { + return hash_value(static_cast(V)); +} + +template class MDMatrix : public Matrix { public: MDMatrix(const Matrix &m) : Matrix(m), md(*this) { } @@ -433,6 +418,12 @@ private: Metadata md; }; +template +inline hash_code hash_value(const MDMatrix &M) { + return hash_value(static_cast(M)); } +} // namespace PBQP +} // namespace llvm + #endif // LLVM_CODEGEN_PBQP_MATH_H diff --git a/include/llvm/CodeGen/PBQP/ReductionRules.h b/include/llvm/CodeGen/PBQP/ReductionRules.h index a55a060..21fde4d 100644 --- a/include/llvm/CodeGen/PBQP/ReductionRules.h +++ b/include/llvm/CodeGen/PBQP/ReductionRules.h @@ -11,13 +11,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_REDUCTIONRULES_H -#define LLVM_REDUCTIONRULES_H +#ifndef LLVM_CODEGEN_PBQP_REDUCTIONRULES_H +#define LLVM_CODEGEN_PBQP_REDUCTIONRULES_H #include "Graph.h" #include "Math.h" #include "Solution.h" +namespace llvm { namespace PBQP { /// \brief Reduce a node of degree one. @@ -186,6 +187,7 @@ namespace PBQP { return s; } -} +} // namespace PBQP +} // namespace llvm -#endif // LLVM_REDUCTIONRULES_H +#endif diff --git a/include/llvm/CodeGen/PBQP/RegAllocSolver.h b/include/llvm/CodeGen/PBQP/RegAllocSolver.h deleted file mode 100644 index 977c348..0000000 --- a/include/llvm/CodeGen/PBQP/RegAllocSolver.h +++ /dev/null @@ -1,359 +0,0 @@ -//===-- RegAllocSolver.h - Heuristic PBQP Solver for reg alloc --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Heuristic PBQP solver for register allocation problems. This solver uses a -// graph reduction approach. Nodes of degree 0, 1 and 2 are eliminated with -// optimality-preserving rules (see ReductionRules.h). When no low-degree (<3) -// nodes are present, a heuristic derived from Brigg's graph coloring approach -// is used. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H -#define LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H - -#include "CostAllocator.h" -#include "Graph.h" -#include "ReductionRules.h" -#include "Solution.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include - -namespace PBQP { - - namespace RegAlloc { - - /// \brief Metadata to speed allocatability test. - /// - /// Keeps track of the number of infinities in each row and column. - class MatrixMetadata { - private: - MatrixMetadata(const MatrixMetadata&); - void operator=(const MatrixMetadata&); - public: - MatrixMetadata(const PBQP::Matrix& M) - : WorstRow(0), WorstCol(0), - UnsafeRows(new bool[M.getRows() - 1]()), - UnsafeCols(new bool[M.getCols() - 1]()) { - - unsigned* ColCounts = new unsigned[M.getCols() - 1](); - - for (unsigned i = 1; i < M.getRows(); ++i) { - unsigned RowCount = 0; - for (unsigned j = 1; j < M.getCols(); ++j) { - if (M[i][j] == std::numeric_limits::infinity()) { - ++RowCount; - ++ColCounts[j - 1]; - UnsafeRows[i - 1] = true; - UnsafeCols[j - 1] = true; - } - } - WorstRow = std::max(WorstRow, RowCount); - } - unsigned WorstColCountForCurRow = - *std::max_element(ColCounts, ColCounts + M.getCols() - 1); - WorstCol = std::max(WorstCol, WorstColCountForCurRow); - delete[] ColCounts; - } - - ~MatrixMetadata() { - delete[] UnsafeRows; - delete[] UnsafeCols; - } - - unsigned getWorstRow() const { return WorstRow; } - unsigned getWorstCol() const { return WorstCol; } - const bool* getUnsafeRows() const { return UnsafeRows; } - const bool* getUnsafeCols() const { return UnsafeCols; } - - private: - unsigned WorstRow, WorstCol; - bool* UnsafeRows; - bool* UnsafeCols; - }; - - class NodeMetadata { - public: - typedef enum { Unprocessed, - OptimallyReducible, - ConservativelyAllocatable, - NotProvablyAllocatable } ReductionState; - - NodeMetadata() : RS(Unprocessed), DeniedOpts(0), OptUnsafeEdges(nullptr){} - ~NodeMetadata() { delete[] OptUnsafeEdges; } - - void setup(const Vector& Costs) { - NumOpts = Costs.getLength() - 1; - OptUnsafeEdges = new unsigned[NumOpts](); - } - - ReductionState getReductionState() const { return RS; } - void setReductionState(ReductionState RS) { this->RS = RS; } - - void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); - const bool* UnsafeOpts = - Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); - for (unsigned i = 0; i < NumOpts; ++i) - OptUnsafeEdges[i] += UnsafeOpts[i]; - } - - void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { - DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); - const bool* UnsafeOpts = - Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); - for (unsigned i = 0; i < NumOpts; ++i) - OptUnsafeEdges[i] -= UnsafeOpts[i]; - } - - bool isConservativelyAllocatable() const { - return (DeniedOpts < NumOpts) || - (std::find(OptUnsafeEdges, OptUnsafeEdges + NumOpts, 0) != - OptUnsafeEdges + NumOpts); - } - - private: - ReductionState RS; - unsigned NumOpts; - unsigned DeniedOpts; - unsigned* OptUnsafeEdges; - }; - - class RegAllocSolverImpl { - private: - typedef PBQP::MDMatrix RAMatrix; - public: - typedef PBQP::Vector RawVector; - typedef PBQP::Matrix RawMatrix; - typedef PBQP::Vector Vector; - typedef RAMatrix Matrix; - typedef PBQP::PoolCostAllocator< - Vector, PBQP::VectorComparator, - Matrix, PBQP::MatrixComparator> CostAllocator; - - typedef PBQP::GraphBase::NodeId NodeId; - typedef PBQP::GraphBase::EdgeId EdgeId; - - typedef RegAlloc::NodeMetadata NodeMetadata; - - struct EdgeMetadata { }; - - typedef PBQP::Graph Graph; - - RegAllocSolverImpl(Graph &G) : G(G) {} - - Solution solve() { - G.setSolver(*this); - Solution S; - setup(); - S = backpropagate(G, reduce()); - G.unsetSolver(); - return S; - } - - void handleAddNode(NodeId NId) { - G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); - } - void handleRemoveNode(NodeId NId) {} - void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {} - - void handleAddEdge(EdgeId EId) { - handleReconnectEdge(EId, G.getEdgeNode1Id(EId)); - handleReconnectEdge(EId, G.getEdgeNode2Id(EId)); - } - - void handleRemoveEdge(EdgeId EId) { - handleDisconnectEdge(EId, G.getEdgeNode1Id(EId)); - handleDisconnectEdge(EId, G.getEdgeNode2Id(EId)); - } - - void handleDisconnectEdge(EdgeId EId, NodeId NId) { - NodeMetadata& NMd = G.getNodeMetadata(NId); - const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); - NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); - if (G.getNodeDegree(NId) == 3) { - // This node is becoming optimally reducible. - moveToOptimallyReducibleNodes(NId); - } else if (NMd.getReductionState() == - NodeMetadata::NotProvablyAllocatable && - NMd.isConservativelyAllocatable()) { - // This node just became conservatively allocatable. - moveToConservativelyAllocatableNodes(NId); - } - } - - void handleReconnectEdge(EdgeId EId, NodeId NId) { - NodeMetadata& NMd = G.getNodeMetadata(NId); - const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); - NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); - } - - void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { - handleRemoveEdge(EId); - - NodeId N1Id = G.getEdgeNode1Id(EId); - NodeId N2Id = G.getEdgeNode2Id(EId); - NodeMetadata& N1Md = G.getNodeMetadata(N1Id); - NodeMetadata& N2Md = G.getNodeMetadata(N2Id); - const MatrixMetadata& MMd = NewCosts.getMetadata(); - N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); - N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); - } - - private: - - void removeFromCurrentSet(NodeId NId) { - switch (G.getNodeMetadata(NId).getReductionState()) { - case NodeMetadata::Unprocessed: break; - case NodeMetadata::OptimallyReducible: - assert(OptimallyReducibleNodes.find(NId) != - OptimallyReducibleNodes.end() && - "Node not in optimally reducible set."); - OptimallyReducibleNodes.erase(NId); - break; - case NodeMetadata::ConservativelyAllocatable: - assert(ConservativelyAllocatableNodes.find(NId) != - ConservativelyAllocatableNodes.end() && - "Node not in conservatively allocatable set."); - ConservativelyAllocatableNodes.erase(NId); - break; - case NodeMetadata::NotProvablyAllocatable: - assert(NotProvablyAllocatableNodes.find(NId) != - NotProvablyAllocatableNodes.end() && - "Node not in not-provably-allocatable set."); - NotProvablyAllocatableNodes.erase(NId); - break; - } - } - - void moveToOptimallyReducibleNodes(NodeId NId) { - removeFromCurrentSet(NId); - OptimallyReducibleNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::OptimallyReducible); - } - - void moveToConservativelyAllocatableNodes(NodeId NId) { - removeFromCurrentSet(NId); - ConservativelyAllocatableNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::ConservativelyAllocatable); - } - - void moveToNotProvablyAllocatableNodes(NodeId NId) { - removeFromCurrentSet(NId); - NotProvablyAllocatableNodes.insert(NId); - G.getNodeMetadata(NId).setReductionState( - NodeMetadata::NotProvablyAllocatable); - } - - void setup() { - // Set up worklists. - for (auto NId : G.nodeIds()) { - if (G.getNodeDegree(NId) < 3) - moveToOptimallyReducibleNodes(NId); - else if (G.getNodeMetadata(NId).isConservativelyAllocatable()) - moveToConservativelyAllocatableNodes(NId); - else - moveToNotProvablyAllocatableNodes(NId); - } - } - - // Compute a reduction order for the graph by iteratively applying PBQP - // reduction rules. Locally optimal rules are applied whenever possible (R0, - // R1, R2). If no locally-optimal rules apply then any conservatively - // allocatable node is reduced. Finally, if no conservatively allocatable - // node exists then the node with the lowest spill-cost:degree ratio is - // selected. - std::vector reduce() { - assert(!G.empty() && "Cannot reduce empty graph."); - - typedef GraphBase::NodeId NodeId; - std::vector NodeStack; - - // Consume worklists. - while (true) { - if (!OptimallyReducibleNodes.empty()) { - NodeSet::iterator NItr = OptimallyReducibleNodes.begin(); - NodeId NId = *NItr; - OptimallyReducibleNodes.erase(NItr); - NodeStack.push_back(NId); - switch (G.getNodeDegree(NId)) { - case 0: - break; - case 1: - applyR1(G, NId); - break; - case 2: - applyR2(G, NId); - break; - default: llvm_unreachable("Not an optimally reducible node."); - } - } else if (!ConservativelyAllocatableNodes.empty()) { - // Conservatively allocatable nodes will never spill. For now just - // take the first node in the set and push it on the stack. When we - // start optimizing more heavily for register preferencing, it may - // would be better to push nodes with lower 'expected' or worst-case - // register costs first (since early nodes are the most - // constrained). - NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin(); - NodeId NId = *NItr; - ConservativelyAllocatableNodes.erase(NItr); - NodeStack.push_back(NId); - G.disconnectAllNeighborsFromNode(NId); - - } else if (!NotProvablyAllocatableNodes.empty()) { - NodeSet::iterator NItr = - std::min_element(NotProvablyAllocatableNodes.begin(), - NotProvablyAllocatableNodes.end(), - SpillCostComparator(G)); - NodeId NId = *NItr; - NotProvablyAllocatableNodes.erase(NItr); - NodeStack.push_back(NId); - G.disconnectAllNeighborsFromNode(NId); - } else - break; - } - - return NodeStack; - } - - class SpillCostComparator { - public: - SpillCostComparator(const Graph& G) : G(G) {} - bool operator()(NodeId N1Id, NodeId N2Id) { - PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id); - PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id); - return N1SC < N2SC; - } - private: - const Graph& G; - }; - - Graph& G; - typedef std::set NodeSet; - NodeSet OptimallyReducibleNodes; - NodeSet ConservativelyAllocatableNodes; - NodeSet NotProvablyAllocatableNodes; - }; - - typedef Graph Graph; - - inline Solution solve(Graph& G) { - if (G.empty()) - return Solution(); - RegAllocSolverImpl RegAllocSolver(G); - return RegAllocSolver.solve(); - } - - } -} - -#endif // LLVM_CODEGEN_PBQP_REGALLOCSOLVER_H diff --git a/include/llvm/CodeGen/PBQP/Solution.h b/include/llvm/CodeGen/PBQP/Solution.h index 3556e60..a3bfaeb 100644 --- a/include/llvm/CodeGen/PBQP/Solution.h +++ b/include/llvm/CodeGen/PBQP/Solution.h @@ -18,6 +18,7 @@ #include "Math.h" #include +namespace llvm { namespace PBQP { /// \brief Represents a solution to a PBQP problem. @@ -87,6 +88,7 @@ namespace PBQP { }; -} +} // namespace PBQP +} // namespace llvm #endif // LLVM_CODEGEN_PBQP_SOLUTION_H diff --git a/include/llvm/CodeGen/PBQPRAConstraint.h b/include/llvm/CodeGen/PBQPRAConstraint.h new file mode 100644 index 0000000..833b9ba --- /dev/null +++ b/include/llvm/CodeGen/PBQPRAConstraint.h @@ -0,0 +1,69 @@ +//===-- RegAllocPBQP.h ------------------------------------------*- C++ -*-===// +// +// 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 PBQPBuilder interface, for classes which build PBQP +// instances to represent register allocation problems, and the RegAllocPBQP +// interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PBQPRACONSTRAINT_H +#define LLVM_CODEGEN_PBQPRACONSTRAINT_H + +#include +#include + +namespace llvm { +namespace PBQP { +namespace RegAlloc { +// Forward declare PBQP graph class. +class PBQPRAGraph; +} +} + +class LiveIntervals; +class MachineBlockFrequencyInfo; +class MachineFunction; +class TargetRegisterInfo; + +typedef PBQP::RegAlloc::PBQPRAGraph PBQPRAGraph; + +/// @brief Abstract base for classes implementing PBQP register allocation +/// constraints (e.g. Spill-costs, interference, coalescing). +class PBQPRAConstraint { +public: + virtual ~PBQPRAConstraint() = 0; + virtual void apply(PBQPRAGraph &G) = 0; +private: + virtual void anchor(); +}; + +/// @brief PBQP register allocation constraint composer. +/// +/// Constraints added to this list will be applied, in the order that they are +/// added, to the PBQP graph. +class PBQPRAConstraintList : public PBQPRAConstraint { +public: + void apply(PBQPRAGraph &G) override { + for (auto &C : Constraints) + C->apply(G); + } + + void addConstraint(std::unique_ptr C) { + if (C) + Constraints.push_back(std::move(C)); + } +private: + std::vector> Constraints; + void anchor() override; +}; + +} + +#endif /* LLVM_CODEGEN_PBQPRACONSTRAINT_H */ diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 87f55e8..8ed32b8 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -105,6 +105,7 @@ private: AnalysisID StopAfter; bool Started; bool Stopped; + bool AddingMachinePasses; protected: TargetMachine *TM; @@ -178,6 +179,10 @@ public: /// Return true if the optimized regalloc pipeline is enabled. bool getOptimizeRegAlloc() const; + /// Return true if the default global register allocator is in use and + /// has not be overriden on the command line with '-regalloc=...' + bool usingDefaultRegAlloc() const; + /// Add common target configurable passes that perform LLVM IR to IR /// transforms following machine independent optimization. virtual void addIRPasses(); @@ -255,12 +260,9 @@ protected: return false; } - /// addPreRegAlloc - This method may be implemented by targets that want to - /// run passes immediately before register allocation. This should return - /// true if -print-machineinstrs should print after these passes. - virtual bool addPreRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes + /// immediately before register allocation. + virtual void addPreRegAlloc() { } /// createTargetRegisterAllocator - Create the register allocator pass for /// this target at the current optimization level. @@ -286,24 +288,16 @@ protected: return false; } - /// addPostRegAlloc - This method may be implemented by targets that want to - /// run passes after register allocation pass pipeline but before - /// prolog-epilog insertion. This should return true if -print-machineinstrs - /// should print after these passes. - virtual bool addPostRegAlloc() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// register allocation pass pipeline but before prolog-epilog insertion. + virtual void addPostRegAlloc() { } /// Add passes that optimize machine instructions after register allocation. virtual void addMachineLateOptimization(); - /// addPreSched2 - This method may be implemented by targets that want to - /// run passes after prolog-epilog insertion and before the second instruction - /// scheduling pass. This should return true if -print-machineinstrs should - /// print after these passes. - virtual bool addPreSched2() { - return false; - } + /// This method may be implemented by targets that want to run passes after + /// prolog-epilog insertion and before the second instruction scheduling pass. + virtual void addPreSched2() { } /// addGCPasses - Add late codegen passes that analyze code for garbage /// collection. This should return true if GC info should be printed after @@ -313,24 +307,30 @@ protected: /// Add standard basic block placement passes. virtual void addBlockPlacement(); - /// addPreEmitPass - This pass may be implemented by targets that want to run - /// passes immediately before machine code is emitted. This should return - /// true if -print-machineinstrs should print out the code after the passes. - virtual bool addPreEmitPass() { - return false; - } + /// This pass may be implemented by targets that want to run passes + /// immediately before machine code is emitted. + virtual void addPreEmitPass() { } /// Utilities for targets to add passes to the pass manager. /// /// Add a CodeGen pass at this point in the pipeline after checking overrides. /// Return the pass that was added, or zero if no pass was added. - AnalysisID addPass(AnalysisID PassID); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, + bool printAfter = true); /// Add a pass to the PassManager if that pass is supposed to be run, as /// determined by the StartAfter and StopAfter options. Takes ownership of the /// pass. - void addPass(Pass *P); + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); /// addMachinePasses helper to create the target-selected or overriden /// regalloc pass. @@ -339,13 +339,20 @@ protected: /// printAndVerify - Add a pass to dump then verify the machine function, if /// those steps are enabled. /// - void printAndVerify(const char *Banner); + void printAndVerify(const std::string &Banner); + + /// Add a pass to print the machine function if printing is enabled. + void addPrintPass(const std::string &Banner); + + /// Add a pass to perform basic verification of the machine function if + /// verification is enabled. + void addVerifyPass(const std::string &Banner); }; } // namespace llvm /// List of target independent CodeGen pass IDs. namespace llvm { - FunctionPass *createAtomicExpandLoadLinkedPass(const TargetMachine *TM); + FunctionPass *createAtomicExpandPass(const TargetMachine *TM); /// \brief Create a basic TargetTransformInfo analysis pass. /// @@ -372,8 +379,9 @@ namespace llvm { /// matching during instruction selection. FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr); - /// AtomicExpandLoadLinkedID -- FIXME - extern char &AtomicExpandLoadLinkedID; + /// AtomicExpandID -- Lowers atomic operations in terms of either cmpxchg + /// load-linked/store-conditional loops. + extern char &AtomicExpandID; /// MachineLoopInfo - This pass is a loop analysis pass. extern char &MachineLoopInfoID; @@ -489,6 +497,10 @@ namespace llvm { /// inserting cmov instructions. extern char &EarlyIfConverterID; + /// This pass performs instruction combining using trace metrics to estimate + /// critical-path and resource depth. + extern char &MachineCombinerID; + /// StackSlotColoring - This pass performs stack coloring and merging. /// It merges disjoint allocas to reduce the stack size. extern char &StackColoringID; @@ -551,7 +563,7 @@ namespace llvm { /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. /// - FunctionPass *createMachineVerifierPass(const char *Banner = nullptr); + FunctionPass *createMachineVerifierPass(const std::string& Banner); /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. @@ -593,6 +605,10 @@ namespace llvm { /// createJumpInstrTables - This pass creates jump-instruction tables. ModulePass *createJumpInstrTablesPass(); + + /// createForwardControlFlowIntegrityPass - This pass adds control-flow + /// integrity. + ModulePass *createForwardControlFlowIntegrityPass(); } // End llvm namespace /// This initializer registers TargetMachine constructor, so the pass being diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 441b0f0..eceb790 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -16,150 +16,505 @@ #ifndef LLVM_CODEGEN_REGALLOCPBQP_H #define LLVM_CODEGEN_REGALLOCPBQP_H -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/PBQP/RegAllocSolver.h" -#include -#include +#include "llvm/CodeGen/PBQP/CostAllocator.h" +#include "llvm/CodeGen/PBQP/ReductionRules.h" +#include "llvm/CodeGen/PBQPRAConstraint.h" +#include "llvm/Support/ErrorHandling.h" namespace llvm { - - class LiveIntervals; - class MachineBlockFrequencyInfo; - class MachineFunction; - class TargetRegisterInfo; - - typedef PBQP::RegAlloc::Graph PBQPRAGraph; - - /// This class wraps up a PBQP instance representing a register allocation - /// problem, plus the structures necessary to map back from the PBQP solution - /// to a register allocation solution. (i.e. The PBQP-node <--> vreg map, - /// and the PBQP option <--> storage location map). - class PBQPRAProblem { - public: - - typedef SmallVector AllowedSet; - - PBQPRAGraph& getGraph() { return graph; } - - const PBQPRAGraph& getGraph() const { return graph; } - - /// Record the mapping between the given virtual register and PBQP node, - /// and the set of allowed pregs for the vreg. - /// - /// If you are extending - /// PBQPBuilder you are unlikely to need this: Nodes and options for all - /// vregs will already have been set up for you by the base class. - template - void recordVReg(unsigned vreg, PBQPRAGraph::NodeId nodeId, - AllowedRegsItr arBegin, AllowedRegsItr arEnd) { - assert(node2VReg.find(nodeId) == node2VReg.end() && "Re-mapping node."); - assert(vreg2Node.find(vreg) == vreg2Node.end() && "Re-mapping vreg."); - assert(allowedSets[vreg].empty() && "vreg already has pregs."); - - node2VReg[nodeId] = vreg; - vreg2Node[vreg] = nodeId; - std::copy(arBegin, arEnd, std::back_inserter(allowedSets[vreg])); +namespace PBQP { +namespace RegAlloc { + +/// @brief Spill option index. +inline unsigned getSpillOptionIdx() { return 0; } + +/// \brief Metadata to speed allocatability test. +/// +/// Keeps track of the number of infinities in each row and column. +class MatrixMetadata { +private: + MatrixMetadata(const MatrixMetadata&); + void operator=(const MatrixMetadata&); +public: + MatrixMetadata(const Matrix& M) + : WorstRow(0), WorstCol(0), + UnsafeRows(new bool[M.getRows() - 1]()), + UnsafeCols(new bool[M.getCols() - 1]()) { + + unsigned* ColCounts = new unsigned[M.getCols() - 1](); + + for (unsigned i = 1; i < M.getRows(); ++i) { + unsigned RowCount = 0; + for (unsigned j = 1; j < M.getCols(); ++j) { + if (M[i][j] == std::numeric_limits::infinity()) { + ++RowCount; + ++ColCounts[j - 1]; + UnsafeRows[i - 1] = true; + UnsafeCols[j - 1] = true; + } + } + WorstRow = std::max(WorstRow, RowCount); } + unsigned WorstColCountForCurRow = + *std::max_element(ColCounts, ColCounts + M.getCols() - 1); + WorstCol = std::max(WorstCol, WorstColCountForCurRow); + delete[] ColCounts; + } + + unsigned getWorstRow() const { return WorstRow; } + unsigned getWorstCol() const { return WorstCol; } + const bool* getUnsafeRows() const { return UnsafeRows.get(); } + const bool* getUnsafeCols() const { return UnsafeCols.get(); } + +private: + unsigned WorstRow, WorstCol; + std::unique_ptr UnsafeRows; + std::unique_ptr UnsafeCols; +}; + +/// \brief Holds a vector of the allowed physical regs for a vreg. +class AllowedRegVector { + friend hash_code hash_value(const AllowedRegVector &); +public: + + AllowedRegVector() : NumOpts(0), Opts(nullptr) {} + + AllowedRegVector(const std::vector &OptVec) + : NumOpts(OptVec.size()), Opts(new unsigned[NumOpts]) { + std::copy(OptVec.begin(), OptVec.end(), Opts.get()); + } + + AllowedRegVector(const AllowedRegVector &Other) + : NumOpts(Other.NumOpts), Opts(new unsigned[NumOpts]) { + std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get()); + } + + AllowedRegVector(AllowedRegVector &&Other) + : NumOpts(std::move(Other.NumOpts)), Opts(std::move(Other.Opts)) {} + + AllowedRegVector& operator=(const AllowedRegVector &Other) { + NumOpts = Other.NumOpts; + Opts.reset(new unsigned[NumOpts]); + std::copy(Other.Opts.get(), Other.Opts.get() + NumOpts, Opts.get()); + return *this; + } + + AllowedRegVector& operator=(AllowedRegVector &&Other) { + NumOpts = std::move(Other.NumOpts); + Opts = std::move(Other.Opts); + return *this; + } + + unsigned size() const { return NumOpts; } + unsigned operator[](size_t I) const { return Opts[I]; } + + bool operator==(const AllowedRegVector &Other) const { + if (NumOpts != Other.NumOpts) + return false; + return std::equal(Opts.get(), Opts.get() + NumOpts, Other.Opts.get()); + } + + bool operator!=(const AllowedRegVector &Other) const { + return !(*this == Other); + } + +private: + unsigned NumOpts; + std::unique_ptr Opts; +}; + +inline hash_code hash_value(const AllowedRegVector &OptRegs) { + unsigned *OStart = OptRegs.Opts.get(); + unsigned *OEnd = OptRegs.Opts.get() + OptRegs.NumOpts; + return hash_combine(OptRegs.NumOpts, + hash_combine_range(OStart, OEnd)); +} - /// Get the virtual register corresponding to the given PBQP node. - unsigned getVRegForNode(PBQPRAGraph::NodeId nodeId) const; - - /// Get the PBQP node corresponding to the given virtual register. - PBQPRAGraph::NodeId getNodeForVReg(unsigned vreg) const; - - /// Returns true if the given PBQP option represents a physical register, - /// false otherwise. - bool isPRegOption(unsigned vreg, unsigned option) const { - // At present we only have spills or pregs, so anything that's not a - // spill is a preg. (This might be extended one day to support remat). - return !isSpillOption(vreg, option); +/// \brief Holds graph-level metadata relevent to PBQP RA problems. +class GraphMetadata { +private: + typedef ValuePool AllowedRegVecPool; +public: + + typedef AllowedRegVecPool::PoolRef AllowedRegVecRef; + + GraphMetadata(MachineFunction &MF, + LiveIntervals &LIS, + MachineBlockFrequencyInfo &MBFI) + : MF(MF), LIS(LIS), MBFI(MBFI) {} + + MachineFunction &MF; + LiveIntervals &LIS; + MachineBlockFrequencyInfo &MBFI; + + void setNodeIdForVReg(unsigned VReg, GraphBase::NodeId NId) { + VRegToNodeId[VReg] = NId; + } + + GraphBase::NodeId getNodeIdForVReg(unsigned VReg) const { + auto VRegItr = VRegToNodeId.find(VReg); + if (VRegItr == VRegToNodeId.end()) + return GraphBase::invalidNodeId(); + return VRegItr->second; + } + + void eraseNodeIdForVReg(unsigned VReg) { + VRegToNodeId.erase(VReg); + } + + AllowedRegVecRef getAllowedRegs(AllowedRegVector Allowed) { + return AllowedRegVecs.getValue(std::move(Allowed)); + } + +private: + DenseMap VRegToNodeId; + AllowedRegVecPool AllowedRegVecs; +}; + +/// \brief Holds solver state and other metadata relevant to each PBQP RA node. +class NodeMetadata { +public: + typedef RegAlloc::AllowedRegVector AllowedRegVector; + + typedef enum { Unprocessed, + OptimallyReducible, + ConservativelyAllocatable, + NotProvablyAllocatable } ReductionState; + + NodeMetadata() + : RS(Unprocessed), NumOpts(0), DeniedOpts(0), OptUnsafeEdges(nullptr), + VReg(0) {} + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata(const NodeMetadata &Other) + : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), + OptUnsafeEdges(new unsigned[NumOpts]), VReg(Other.VReg), + AllowedRegs(Other.AllowedRegs) { + if (NumOpts > 0) { + std::copy(&Other.OptUnsafeEdges[0], &Other.OptUnsafeEdges[NumOpts], + &OptUnsafeEdges[0]); } - - /// Returns true if the given PBQP option represents spilling, false - /// otherwise. - bool isSpillOption(unsigned vreg, unsigned option) const { - // We hardcode option zero as the spill option. - return option == 0; + } + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata(NodeMetadata &&Other) + : RS(Other.RS), NumOpts(Other.NumOpts), DeniedOpts(Other.DeniedOpts), + OptUnsafeEdges(std::move(Other.OptUnsafeEdges)), VReg(Other.VReg), + AllowedRegs(std::move(Other.AllowedRegs)) {} + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata& operator=(const NodeMetadata &Other) { + RS = Other.RS; + NumOpts = Other.NumOpts; + DeniedOpts = Other.DeniedOpts; + OptUnsafeEdges.reset(new unsigned[NumOpts]); + std::copy(Other.OptUnsafeEdges.get(), Other.OptUnsafeEdges.get() + NumOpts, + OptUnsafeEdges.get()); + VReg = Other.VReg; + AllowedRegs = Other.AllowedRegs; + return *this; + } + + // FIXME: Re-implementing default behavior to work around MSVC. Remove once + // MSVC synthesizes move constructors properly. + NodeMetadata& operator=(NodeMetadata &&Other) { + RS = Other.RS; + NumOpts = Other.NumOpts; + DeniedOpts = Other.DeniedOpts; + OptUnsafeEdges = std::move(Other.OptUnsafeEdges); + VReg = Other.VReg; + AllowedRegs = std::move(Other.AllowedRegs); + return *this; + } + + void setVReg(unsigned VReg) { this->VReg = VReg; } + unsigned getVReg() const { return VReg; } + + void setAllowedRegs(GraphMetadata::AllowedRegVecRef AllowedRegs) { + this->AllowedRegs = std::move(AllowedRegs); + } + const AllowedRegVector& getAllowedRegs() const { return *AllowedRegs; } + + void setup(const Vector& Costs) { + NumOpts = Costs.getLength() - 1; + OptUnsafeEdges = std::unique_ptr(new unsigned[NumOpts]()); + } + + ReductionState getReductionState() const { return RS; } + void setReductionState(ReductionState RS) { this->RS = RS; } + + void handleAddEdge(const MatrixMetadata& MD, bool Transpose) { + DeniedOpts += Transpose ? MD.getWorstCol() : MD.getWorstRow(); + const bool* UnsafeOpts = + Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); + for (unsigned i = 0; i < NumOpts; ++i) + OptUnsafeEdges[i] += UnsafeOpts[i]; + } + + void handleRemoveEdge(const MatrixMetadata& MD, bool Transpose) { + DeniedOpts -= Transpose ? MD.getWorstCol() : MD.getWorstRow(); + const bool* UnsafeOpts = + Transpose ? MD.getUnsafeCols() : MD.getUnsafeRows(); + for (unsigned i = 0; i < NumOpts; ++i) + OptUnsafeEdges[i] -= UnsafeOpts[i]; + } + + bool isConservativelyAllocatable() const { + return (DeniedOpts < NumOpts) || + (std::find(&OptUnsafeEdges[0], &OptUnsafeEdges[NumOpts], 0) != + &OptUnsafeEdges[NumOpts]); + } + +private: + ReductionState RS; + unsigned NumOpts; + unsigned DeniedOpts; + std::unique_ptr OptUnsafeEdges; + unsigned VReg; + GraphMetadata::AllowedRegVecRef AllowedRegs; +}; + +class RegAllocSolverImpl { +private: + typedef MDMatrix RAMatrix; +public: + typedef PBQP::Vector RawVector; + typedef PBQP::Matrix RawMatrix; + typedef PBQP::Vector Vector; + typedef RAMatrix Matrix; + typedef PBQP::PoolCostAllocator CostAllocator; + + typedef GraphBase::NodeId NodeId; + typedef GraphBase::EdgeId EdgeId; + + typedef RegAlloc::NodeMetadata NodeMetadata; + struct EdgeMetadata { }; + typedef RegAlloc::GraphMetadata GraphMetadata; + + typedef PBQP::Graph Graph; + + RegAllocSolverImpl(Graph &G) : G(G) {} + + Solution solve() { + G.setSolver(*this); + Solution S; + setup(); + S = backpropagate(G, reduce()); + G.unsetSolver(); + return S; + } + + void handleAddNode(NodeId NId) { + G.getNodeMetadata(NId).setup(G.getNodeCosts(NId)); + } + void handleRemoveNode(NodeId NId) {} + void handleSetNodeCosts(NodeId NId, const Vector& newCosts) {} + + void handleAddEdge(EdgeId EId) { + handleReconnectEdge(EId, G.getEdgeNode1Id(EId)); + handleReconnectEdge(EId, G.getEdgeNode2Id(EId)); + } + + void handleRemoveEdge(EdgeId EId) { + handleDisconnectEdge(EId, G.getEdgeNode1Id(EId)); + handleDisconnectEdge(EId, G.getEdgeNode2Id(EId)); + } + + void handleDisconnectEdge(EdgeId EId, NodeId NId) { + NodeMetadata& NMd = G.getNodeMetadata(NId); + const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); + NMd.handleRemoveEdge(MMd, NId == G.getEdgeNode2Id(EId)); + if (G.getNodeDegree(NId) == 3) { + // This node is becoming optimally reducible. + moveToOptimallyReducibleNodes(NId); + } else if (NMd.getReductionState() == + NodeMetadata::NotProvablyAllocatable && + NMd.isConservativelyAllocatable()) { + // This node just became conservatively allocatable. + moveToConservativelyAllocatableNodes(NId); + } + } + + void handleReconnectEdge(EdgeId EId, NodeId NId) { + NodeMetadata& NMd = G.getNodeMetadata(NId); + const MatrixMetadata& MMd = G.getEdgeCosts(EId).getMetadata(); + NMd.handleAddEdge(MMd, NId == G.getEdgeNode2Id(EId)); + } + + void handleSetEdgeCosts(EdgeId EId, const Matrix& NewCosts) { + handleRemoveEdge(EId); + + NodeId N1Id = G.getEdgeNode1Id(EId); + NodeId N2Id = G.getEdgeNode2Id(EId); + NodeMetadata& N1Md = G.getNodeMetadata(N1Id); + NodeMetadata& N2Md = G.getNodeMetadata(N2Id); + const MatrixMetadata& MMd = NewCosts.getMetadata(); + N1Md.handleAddEdge(MMd, N1Id != G.getEdgeNode1Id(EId)); + N2Md.handleAddEdge(MMd, N2Id != G.getEdgeNode1Id(EId)); + } + +private: + + void removeFromCurrentSet(NodeId NId) { + switch (G.getNodeMetadata(NId).getReductionState()) { + case NodeMetadata::Unprocessed: break; + case NodeMetadata::OptimallyReducible: + assert(OptimallyReducibleNodes.find(NId) != + OptimallyReducibleNodes.end() && + "Node not in optimally reducible set."); + OptimallyReducibleNodes.erase(NId); + break; + case NodeMetadata::ConservativelyAllocatable: + assert(ConservativelyAllocatableNodes.find(NId) != + ConservativelyAllocatableNodes.end() && + "Node not in conservatively allocatable set."); + ConservativelyAllocatableNodes.erase(NId); + break; + case NodeMetadata::NotProvablyAllocatable: + assert(NotProvablyAllocatableNodes.find(NId) != + NotProvablyAllocatableNodes.end() && + "Node not in not-provably-allocatable set."); + NotProvablyAllocatableNodes.erase(NId); + break; + } + } + + void moveToOptimallyReducibleNodes(NodeId NId) { + removeFromCurrentSet(NId); + OptimallyReducibleNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::OptimallyReducible); + } + + void moveToConservativelyAllocatableNodes(NodeId NId) { + removeFromCurrentSet(NId); + ConservativelyAllocatableNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::ConservativelyAllocatable); + } + + void moveToNotProvablyAllocatableNodes(NodeId NId) { + removeFromCurrentSet(NId); + NotProvablyAllocatableNodes.insert(NId); + G.getNodeMetadata(NId).setReductionState( + NodeMetadata::NotProvablyAllocatable); + } + + void setup() { + // Set up worklists. + for (auto NId : G.nodeIds()) { + if (G.getNodeDegree(NId) < 3) + moveToOptimallyReducibleNodes(NId); + else if (G.getNodeMetadata(NId).isConservativelyAllocatable()) + moveToConservativelyAllocatableNodes(NId); + else + moveToNotProvablyAllocatableNodes(NId); + } + } + + // Compute a reduction order for the graph by iteratively applying PBQP + // reduction rules. Locally optimal rules are applied whenever possible (R0, + // R1, R2). If no locally-optimal rules apply then any conservatively + // allocatable node is reduced. Finally, if no conservatively allocatable + // node exists then the node with the lowest spill-cost:degree ratio is + // selected. + std::vector reduce() { + assert(!G.empty() && "Cannot reduce empty graph."); + + typedef GraphBase::NodeId NodeId; + std::vector NodeStack; + + // Consume worklists. + while (true) { + if (!OptimallyReducibleNodes.empty()) { + NodeSet::iterator NItr = OptimallyReducibleNodes.begin(); + NodeId NId = *NItr; + OptimallyReducibleNodes.erase(NItr); + NodeStack.push_back(NId); + switch (G.getNodeDegree(NId)) { + case 0: + break; + case 1: + applyR1(G, NId); + break; + case 2: + applyR2(G, NId); + break; + default: llvm_unreachable("Not an optimally reducible node."); + } + } else if (!ConservativelyAllocatableNodes.empty()) { + // Conservatively allocatable nodes will never spill. For now just + // take the first node in the set and push it on the stack. When we + // start optimizing more heavily for register preferencing, it may + // would be better to push nodes with lower 'expected' or worst-case + // register costs first (since early nodes are the most + // constrained). + NodeSet::iterator NItr = ConservativelyAllocatableNodes.begin(); + NodeId NId = *NItr; + ConservativelyAllocatableNodes.erase(NItr); + NodeStack.push_back(NId); + G.disconnectAllNeighborsFromNode(NId); + + } else if (!NotProvablyAllocatableNodes.empty()) { + NodeSet::iterator NItr = + std::min_element(NotProvablyAllocatableNodes.begin(), + NotProvablyAllocatableNodes.end(), + SpillCostComparator(G)); + NodeId NId = *NItr; + NotProvablyAllocatableNodes.erase(NItr); + NodeStack.push_back(NId); + G.disconnectAllNeighborsFromNode(NId); + } else + break; } - /// Returns the allowed set for the given virtual register. - const AllowedSet& getAllowedSet(unsigned vreg) const; - - /// Get PReg for option. - unsigned getPRegForOption(unsigned vreg, unsigned option) const; - - private: - - typedef std::map Node2VReg; - typedef DenseMap VReg2Node; - typedef DenseMap AllowedSetMap; - - PBQPRAGraph graph; - Node2VReg node2VReg; - VReg2Node vreg2Node; - - AllowedSetMap allowedSets; - - }; + return NodeStack; + } - /// Builds PBQP instances to represent register allocation problems. Includes - /// spill, interference and coalescing costs by default. You can extend this - /// class to support additional constraints for your architecture. - class PBQPBuilder { - private: - PBQPBuilder(const PBQPBuilder&) LLVM_DELETED_FUNCTION; - void operator=(const PBQPBuilder&) LLVM_DELETED_FUNCTION; + class SpillCostComparator { public: - - typedef std::set RegSet; - - /// Default constructor. - PBQPBuilder() {} - - /// Clean up a PBQPBuilder. - virtual ~PBQPBuilder() {} - - /// Build a PBQP instance to represent the register allocation problem for - /// the given MachineFunction. - virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineBlockFrequencyInfo *mbfi, - const RegSet &vregs); + SpillCostComparator(const Graph& G) : G(G) {} + bool operator()(NodeId N1Id, NodeId N2Id) { + PBQPNum N1SC = G.getNodeCosts(N1Id)[0] / G.getNodeDegree(N1Id); + PBQPNum N2SC = G.getNodeCosts(N2Id)[0] / G.getNodeDegree(N2Id); + return N1SC < N2SC; + } private: - - void addSpillCosts(PBQP::Vector &costVec, PBQP::PBQPNum spillCost); - - void addInterferenceCosts(PBQP::Matrix &costMat, - const PBQPRAProblem::AllowedSet &vr1Allowed, - const PBQPRAProblem::AllowedSet &vr2Allowed, - const TargetRegisterInfo *tri); + const Graph& G; }; - /// Extended builder which adds coalescing constraints to a problem. - class PBQPBuilderWithCoalescing : public PBQPBuilder { - public: - - /// Build a PBQP instance to represent the register allocation problem for - /// the given MachineFunction. - PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineBlockFrequencyInfo *mbfi, - const RegSet &vregs) override; - - private: + Graph& G; + typedef std::set NodeSet; + NodeSet OptimallyReducibleNodes; + NodeSet ConservativelyAllocatableNodes; + NodeSet NotProvablyAllocatableNodes; +}; + +class PBQPRAGraph : public PBQP::Graph { +private: + typedef PBQP::Graph BaseT; +public: + PBQPRAGraph(GraphMetadata Metadata) : BaseT(Metadata) {} +}; + +inline Solution solve(PBQPRAGraph& G) { + if (G.empty()) + return Solution(); + RegAllocSolverImpl RegAllocSolver(G); + return RegAllocSolver.solve(); +} - void addPhysRegCoalesce(PBQP::Vector &costVec, unsigned pregOption, - PBQP::PBQPNum benefit); +} // namespace RegAlloc +} // namespace PBQP - void addVirtRegCoalesce(PBQP::Matrix &costMat, - const PBQPRAProblem::AllowedSet &vr1Allowed, - const PBQPRAProblem::AllowedSet &vr2Allowed, - PBQP::PBQPNum benefit); - }; +/// @brief Create a PBQP register allocator instance. +FunctionPass * +createPBQPRegisterAllocator(char *customPassID = nullptr); - FunctionPass * - createPBQPRegisterAllocator(std::unique_ptr builder, - char *customPassID = nullptr); -} +} // namespace llvm #endif /* LLVM_CODEGEN_REGALLOCPBQP_H */ diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 335dd7f..474861e 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -34,7 +34,7 @@ class RegScavenger { MachineRegisterInfo* MRI; MachineBasicBlock *MBB; MachineBasicBlock::iterator MBBI; - unsigned NumPhysRegs; + unsigned NumRegUnits; /// Tracking - True if RegScavenger is currently tracking the liveness of /// registers. @@ -58,22 +58,19 @@ class RegScavenger { /// A vector of information on scavenged registers. SmallVector Scavenged; - /// CalleeSavedrRegs - A bitvector of callee saved registers for the target. - /// - BitVector CalleeSavedRegs; - - /// RegsAvailable - The current state of all the physical registers immediately - /// before MBBI. One bit per physical register. If bit is set that means it's - /// available, unset means the register is currently being used. - BitVector RegsAvailable; + /// RegUnitsAvailable - The current state of each reg unit immediatelly + /// before MBBI. One bit per register unit. If bit is not set it means any + /// register containing that register unit is currently being used. + BitVector RegUnitsAvailable; // These BitVectors are only used internally to forward(). They are members // to avoid frequent reallocations. - BitVector KillRegs, DefRegs; + BitVector KillRegUnits, DefRegUnits; + BitVector TmpRegUnits; public: RegScavenger() - : MBB(nullptr), NumPhysRegs(0), Tracking(false) {} + : MBB(nullptr), NumRegUnits(0), Tracking(false) {} /// enterBasicBlock - Start tracking liveness from the begin of the specific /// basic block. @@ -112,9 +109,9 @@ public: MachineBasicBlock::iterator getCurrentPosition() const { return MBBI; } - - /// getRegsUsed - return all registers currently in use in used. - void getRegsUsed(BitVector &used, bool includeReserved); + + /// isRegUsed - return if a specific register is currently used. + bool isRegUsed(unsigned Reg, bool includeReserved = true) const; /// getRegsAvailable - Return all available registers in the register class /// in Mask. @@ -157,40 +154,29 @@ public: return scavengeRegister(RegClass, MBBI, SPAdj); } - /// setUsed - Tell the scavenger a register is used. + /// setRegUsed - Tell the scavenger a register is used. /// - void setUsed(unsigned Reg); + void setRegUsed(unsigned Reg); private: /// isReserved - Returns true if a register is reserved. It is never "unused". bool isReserved(unsigned Reg) const { return MRI->isReserved(Reg); } - /// isUsed - Test if a register is currently being used. When called by the - /// isAliasUsed function, we only check isReserved if this is the original - /// register, not an alias register. + /// setUsed / setUnused - Mark the state of one or a number of register units. /// - bool isUsed(unsigned Reg, bool CheckReserved = true) const { - return !RegsAvailable.test(Reg) || (CheckReserved && isReserved(Reg)); + void setUsed(BitVector &RegUnits) { + RegUnitsAvailable.reset(RegUnits); } - - /// isAliasUsed - Is Reg or an alias currently in use? - bool isAliasUsed(unsigned Reg) const; - - /// setUsed / setUnused - Mark the state of one or a number of registers. - /// - void setUsed(BitVector &Regs) { - RegsAvailable.reset(Regs); - } - void setUnused(BitVector &Regs) { - RegsAvailable |= Regs; + void setUnused(BitVector &RegUnits) { + RegUnitsAvailable |= RegUnits; } - /// Processes the current instruction and fill the KillRegs and DefRegs bit - /// vectors. + /// Processes the current instruction and fill the KillRegUnits and + /// DefRegUnits bit vectors. void determineKillsAndDefs(); - - /// Add Reg and all its sub-registers to BV. - void addRegWithSubRegs(BitVector &BV, unsigned Reg); - + + /// Add all Reg Units that Reg contains to BV. + void addRegUnits(BitVector &BV, unsigned Reg); + /// findSurvivorReg - Return the candidate register that is unused for the /// longest after StartMI. UseMI is set to the instruction where the search /// stopped. diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 81db8a2..64c9c47 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -203,6 +203,16 @@ namespace RTLIB { COPYSIGN_F80, COPYSIGN_F128, COPYSIGN_PPCF128, + FMIN_F32, + FMIN_F64, + FMIN_F80, + FMIN_F128, + FMIN_PPCF128, + FMAX_F32, + FMAX_F64, + FMAX_F80, + FMAX_F128, + FMAX_PPCF128, // CONVERSION FPEXT_F64_F128, diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 5a65d59..80aee8c 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -190,6 +190,12 @@ namespace llvm { return getKind() == Order && Contents.OrdKind == Barrier; } + /// isNormalMemoryOrBarrier - Test if this is could be any kind of memory + /// dependence. + bool isNormalMemoryOrBarrier() const { + return (isNormalMemory() || isBarrier()); + } + /// isMustAlias - Test if this is an Order dependence that is marked /// as "must alias", meaning that the SUnits at either end of the edge /// have a memory dependence on a known memory location. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index e6754a2..00dd8f9 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -75,8 +75,7 @@ namespace llvm { /// MachineInstrs. class ScheduleDAGInstrs : public ScheduleDAG { protected: - const MachineLoopInfo &MLI; - const MachineDominatorTree &MDT; + const MachineLoopInfo *MLI; const MachineFrameInfo *MFI; /// Live Intervals provides reaching defs in preRA scheduling. @@ -154,8 +153,7 @@ namespace llvm { public: explicit ScheduleDAGInstrs(MachineFunction &mf, - const MachineLoopInfo &mli, - const MachineDominatorTree &mdt, + const MachineLoopInfo *mli, bool IsPostRAFlag, bool RemoveKillFlags = false, LiveIntervals *LIS = nullptr); diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index bb87f82..4950797 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -16,9 +16,11 @@ #define LLVM_CODEGEN_SELECTIONDAG_H #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/ilist.h" #include "llvm/CodeGen/DAGCombine.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/Support/RecyclingAllocator.h" #include "llvm/Target/TargetMachine.h" @@ -126,6 +128,10 @@ public: DbgValMap[Node].push_back(V); } + /// \brief Invalidate all DbgValues attached to the node and remove + /// it from the Node-to-DbgValues map. + void erase(const SDNode *Node); + void clear() { DbgValMap.clear(); DbgValues.clear(); @@ -166,7 +172,7 @@ void checkForCycles(const SelectionDAG *DAG, bool force = false); /// class SelectionDAG { const TargetMachine &TM; - const TargetSelectionDAGInfo &TSI; + const TargetSelectionDAGInfo *TSI; const TargetLowering *TLI; MachineFunction *MF; LLVMContext *Context; @@ -266,7 +272,7 @@ public: /// init - Prepare this SelectionDAG to process code in the given /// MachineFunction. /// - void init(MachineFunction &mf, const TargetLowering *TLI); + void init(MachineFunction &mf); /// clear - Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -275,8 +281,9 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const TargetMachine &getTarget() const { return TM; } + const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } const TargetLowering &getTargetLoweringInfo() const { return *TLI; } - const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } + const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; } LLVMContext *getContext() const {return Context; } /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. @@ -364,6 +371,27 @@ public: /// the graph. void Legalize(); + /// \brief Transforms a SelectionDAG node and any operands to it into a node + /// that is compatible with the target instruction selector, as indicated by + /// the TargetLowering object. + /// + /// \returns true if \c N is a valid, legal node after calling this. + /// + /// This essentially runs a single recursive walk of the \c Legalize process + /// over the given node (and its operands). This can be used to incrementally + /// legalize the DAG. All of the nodes which are directly replaced, + /// potentially including N, are added to the output parameter \c + /// UpdatedNodes so that the delta to the DAG can be understood by the + /// caller. + /// + /// When this returns false, N has been legalized in a way that make the + /// pointer passed in no longer valid. It may have even been deleted from the + /// DAG, and so it shouldn't be used further. When this returns true, the + /// N passed in is a legal node, and can be immediately processed as such. + /// This may still have done some work on the DAG, and will still populate + /// UpdatedNodes with any new nodes replacing those originally in the DAG. + bool LegalizeOp(SDNode *N, SmallSetVector &UpdatedNodes); + /// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG /// that only uses vector math operations supported by the target. This is /// necessary as a separate step from Legalize because unrolling a vector @@ -725,7 +753,7 @@ public: SDValue SV, unsigned Align); /// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two - /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces a the value loaded and a + /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a /// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded, /// a success flag (initially i1), and a chain. SDValue getAtomicCmpSwap(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTs, @@ -778,7 +806,8 @@ public: ArrayRef Ops, EVT MemVT, MachinePointerInfo PtrInfo, unsigned Align = 0, bool Vol = false, - bool ReadMem = true, bool WriteMem = true); + bool ReadMem = true, bool WriteMem = true, + unsigned Size = 0); SDValue getMemIntrinsicNode(unsigned Opcode, SDLoc dl, SDVTList VTList, ArrayRef Ops, @@ -793,15 +822,15 @@ public: SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, bool isInvariant, unsigned Alignment, - const MDNode *TBAAInfo = nullptr, + const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, - bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + bool isNonTemporal, bool isInvariant, unsigned Alignment, + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getExtLoad(ISD::LoadExtType ExtType, SDLoc dl, EVT VT, SDValue Chain, SDValue Ptr, EVT MemVT, MachineMemOperand *MMO); @@ -812,7 +841,7 @@ public: SDValue Chain, SDValue Ptr, SDValue Offset, MachinePointerInfo PtrInfo, EVT MemVT, bool isVolatile, bool isNonTemporal, bool isInvariant, - unsigned Alignment, const MDNode *TBAAInfo = nullptr, + unsigned Alignment, const AAMDNodes &AAInfo = AAMDNodes(), const MDNode *Ranges = nullptr); SDValue getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType, EVT VT, SDLoc dl, @@ -824,19 +853,23 @@ public: SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachineMemOperand *MMO); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, EVT TVT, bool isNonTemporal, bool isVolatile, unsigned Alignment, - const MDNode *TBAAInfo = nullptr); + const AAMDNodes &AAInfo = AAMDNodes()); SDValue getTruncStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, EVT TVT, MachineMemOperand *MMO); SDValue getIndexedStore(SDValue OrigStoe, SDLoc dl, SDValue Base, SDValue Offset, ISD::MemIndexedMode AM); + SDValue getMaskedLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, + SDValue Mask, SDValue Src0, MachineMemOperand *MMO); + SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, + SDValue Ptr, SDValue Mask, MachineMemOperand *MMO); /// getSrcValue - Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); @@ -959,15 +992,18 @@ public: /// getDbgValue - Creates a SDDbgValue node. /// - SDDbgValue *getDbgValue(MDNode *MDPtr, SDNode *N, unsigned R, - bool IsIndirect, uint64_t Off, - DebugLoc DL, unsigned O); - /// Constant. - SDDbgValue *getConstantDbgValue(MDNode *MDPtr, const Value *C, uint64_t Off, - DebugLoc DL, unsigned O); - /// Frame index. - SDDbgValue *getFrameIndexDbgValue(MDNode *MDPtr, unsigned FI, uint64_t Off, - DebugLoc DL, unsigned O); + /// SDNode + SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R, + bool IsIndirect, uint64_t Off, DebugLoc DL, + unsigned O); + + /// Constant + SDDbgValue *getConstantDbgValue(MDNode *Var, MDNode *Expr, const Value *C, + uint64_t Off, DebugLoc DL, unsigned O); + + /// FrameIndex + SDDbgValue *getFrameIndexDbgValue(MDNode *Var, MDNode *Expr, unsigned FI, + uint64_t Off, DebugLoc DL, unsigned O); /// RemoveDeadNode - Remove the specified node from the system. If any of its /// operands then becomes dead, remove them as well. Inform UpdateListener @@ -1039,7 +1075,10 @@ public: case ISD::SADDO: case ISD::UADDO: case ISD::ADDC: - case ISD::ADDE: return true; + case ISD::ADDE: + case ISD::FMINNUM: + case ISD::FMAXNUM: + return true; default: return false; } } @@ -1198,6 +1237,7 @@ public: unsigned getEVTAlignment(EVT MemoryVT) const; private: + void InsertNode(SDNode *N); bool RemoveNodeFromCSEMaps(SDNode *N); void AddModifiedNodeToCSEMaps(SDNode *N); SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos); diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 520be40..d53e66d 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -19,6 +19,7 @@ #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/IR/BasicBlock.h" #include "llvm/Pass.h" +#include "llvm/Target/TargetSubtargetInfo.h" namespace llvm { class FastISel; @@ -50,15 +51,16 @@ public: AliasAnalysis *AA; GCFunctionInfo *GFI; CodeGenOpt::Level OptLevel; + const TargetInstrInfo *TII; + const TargetLowering *TLI; + static char ID; explicit SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); virtual ~SelectionDAGISel(); - const TargetLowering *getTargetLowering() const { - return TM.getTargetLowering(); - } + const TargetLowering *getTargetLowering() const { return TLI; } void getAnalysisUsage(AnalysisUsage &AU) const override; @@ -238,6 +240,12 @@ public: const unsigned char *MatcherTable, unsigned TableSize); + /// \brief Return true if complex patterns for this target can mutate the + /// DAG. + virtual bool ComplexPatternFuncMutatesDAG() const { + return false; + } + private: // Calls to these functions are generated by tblgen. diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 2231511..8e7fd54 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -19,7 +19,6 @@ #ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H #define LLVM_CODEGEN_SELECTIONDAGNODES_H -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" @@ -27,6 +26,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/ValueTypes.h" @@ -117,11 +117,13 @@ namespace ISD { /// of information is represented with the SDValue value type. /// class SDValue { + friend struct DenseMapInfo; + SDNode *Node; // The node defining the value we are using. unsigned ResNo; // Which return value of the node we are using. public: SDValue() : Node(nullptr), ResNo(0) {} - SDValue(SDNode *node, unsigned resno) : Node(node), ResNo(resno) {} + SDValue(SDNode *node, unsigned resno); /// get the index which selects a specific result in the SDNode unsigned getResNo() const { return ResNo; } @@ -208,10 +210,14 @@ public: template<> struct DenseMapInfo { static inline SDValue getEmptyKey() { - return SDValue((SDNode*)-1, -1U); + SDValue V; + V.ResNo = -1U; + return V; } static inline SDValue getTombstoneKey() { - return SDValue((SDNode*)-1, 0); + SDValue V; + V.ResNo = -2U; + return V; } static unsigned getHashValue(const SDValue &Val) { return ((unsigned)((uintptr_t)Val.getNode() >> 4) ^ @@ -411,6 +417,16 @@ public: return NodeType >= ISD::FIRST_TARGET_MEMORY_OPCODE; } + /// Test if this node is a memory intrinsic (with valid pointer information). + /// INTRINSIC_W_CHAIN and INTRINSIC_VOID nodes are sometimes created for + /// non-memory intrinsics (with chains) that are not really instances of + /// MemSDNode. For such nodes, we need some extra state to determine the + /// proper classof relationship. + bool isMemIntrinsic() const { + return (NodeType == ISD::INTRINSIC_W_CHAIN || + NodeType == ISD::INTRINSIC_VOID) && ((SubclassData >> 13) & 1); + } + /// isMachineOpcode - Test if this node has a post-isel opcode, directly /// corresponding to a MachineInstr opcode. bool isMachineOpcode() const { return NodeType < 0; } @@ -578,7 +594,7 @@ public: /// changes. /// NOTE: This is still very expensive. Use carefully. bool hasPredecessorHelper(const SDNode *N, - SmallPtrSet &Visited, + SmallPtrSetImpl &Visited, SmallVectorImpl &Worklist) const; /// getNumOperands - Return the number of values used by this operation. @@ -746,7 +762,13 @@ protected: ValueList(VTs.VTs), UseList(nullptr), NumOperands(Ops.size()), NumValues(VTs.NumVTs), debugLoc(dl), IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + assert(NumOperands == Ops.size() && + "NumOperands wasn't wide enough for its operands!"); + assert(NumValues == VTs.NumVTs && + "NumValues wasn't wide enough for its operands!"); for (unsigned i = 0; i != Ops.size(); ++i) { + assert(OperandList && "no operands available"); OperandList[i].setUser(this); OperandList[i].setInitial(Ops[i]); } @@ -759,7 +781,11 @@ protected: : NodeType(Opc), OperandsNeedDelete(false), HasDebugValue(false), SubclassData(0), NodeId(-1), OperandList(nullptr), ValueList(VTs.VTs), UseList(nullptr), NumOperands(0), NumValues(VTs.NumVTs), debugLoc(dl), - IROrder(Order) {} + IROrder(Order) { + assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); + assert(NumValues == VTs.NumVTs && + "NumValues wasn't wide enough for its operands!"); + } /// InitOperands - Initialize the operands list of this with 1 operand. void InitOperands(SDUse *Ops, const SDValue &Op0) { @@ -818,6 +844,8 @@ protected: Ops[i].setInitial(Vals[i]); } NumOperands = N; + assert(NumOperands == N && + "NumOperands wasn't wide enough for its operands!"); OperandList = Ops; checkForCycles(this); } @@ -877,6 +905,13 @@ public: // Define inline functions from the SDValue class. +inline SDValue::SDValue(SDNode *node, unsigned resno) + : Node(node), ResNo(resno) { + assert((!Node || ResNo < Node->getNumValues()) && + "Invalid result number for the given node!"); + assert(ResNo < -2U && "Cannot use result numbers reserved for DenseMaps."); +} + inline unsigned SDValue::getOpcode() const { return Node->getOpcode(); } @@ -1088,8 +1123,8 @@ public: // Returns the offset from the location of the access. int64_t getSrcValueOffset() const { return MMO->getOffset(); } - /// Returns the TBAAInfo that describes the dereference. - const MDNode *getTBAAInfo() const { return MMO->getTBAAInfo(); } + /// Returns the AA info that describes the dereference. + AAMDNodes getAAInfo() const { return MMO->getAAInfo(); } /// Returns the Ranges that describes the dereference. const MDNode *getRanges() const { return MMO->getRanges(); } @@ -1145,6 +1180,9 @@ public: N->getOpcode() == ISD::ATOMIC_LOAD_UMAX || N->getOpcode() == ISD::ATOMIC_LOAD || N->getOpcode() == ISD::ATOMIC_STORE || + N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE || + N->isMemIntrinsic() || N->isTargetMemoryOpcode(); } }; @@ -1273,14 +1311,14 @@ public: ArrayRef Ops, EVT MemoryVT, MachineMemOperand *MMO) : MemSDNode(Opc, Order, dl, VTs, Ops, MemoryVT, MMO) { + SubclassData |= 1u << 13; } // Methods to support isa and dyn_cast static bool classof(const SDNode *N) { // We lower some target intrinsics to their target opcode // early a node with a target opcode can be of this class - return N->getOpcode() == ISD::INTRINSIC_W_CHAIN || - N->getOpcode() == ISD::INTRINSIC_VOID || + return N->isMemIntrinsic() || N->getOpcode() == ISD::PREFETCH || N->isTargetMemoryOpcode(); } @@ -1380,6 +1418,12 @@ public: /// isNaN - Return true if the value is a NaN. bool isNaN() const { return Value->isNaN(); } + /// isInfinity - Return true if the value is an infinity + bool isInfinity() const { return Value->isInfinity(); } + + /// isNegative - Return true if the value is negative. + bool isNegative() const { return Value->isNegative(); } + /// isExactlyValue - We don't rely on operator== working on double values, as /// it returns true for things that are clearly not equal, like -0.0 and 0.0. /// As such, this method can be used to do an exact bit-for-bit comparison of @@ -1893,6 +1937,72 @@ public: } }; +/// MaskedLoadStoreSDNode - This is a base class is used to represent MLOAD and +/// MSTORE nodes +/// +class MaskedLoadStoreSDNode : public MemSDNode { + // Operands + SDUse Ops[4]; +public: + friend class SelectionDAG; + MaskedLoadStoreSDNode(ISD::NodeType NodeTy, unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MemSDNode(NodeTy, Order, dl, VTs, MemVT, MMO) { + InitOperands(Ops, Operands, numOperands); + } + + // In the both nodes address is Op1, mask is Op2: + // MaskedLoadSDNode (Chain, ptr, mask, src0), src0 is a passthru value + // MaskedStoreSDNode (Chain, ptr, mask, data) + // Mask is a vector of i1 elements + const SDValue &getBasePtr() const { return getOperand(1); } + const SDValue &getMask() const { return getOperand(2); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD || + N->getOpcode() == ISD::MSTORE; + } +}; + +/// MaskedLoadSDNode - This class is used to represent an MLOAD node +/// +class MaskedLoadSDNode : public MaskedLoadStoreSDNode { +public: + friend class SelectionDAG; + MaskedLoadSDNode(unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MLOAD, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) + {} + + const SDValue &getSrc0() const { return getOperand(3); } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MLOAD; + } +}; + +/// MaskedStoreSDNode - This class is used to represent an MSTORE node +/// +class MaskedStoreSDNode : public MaskedLoadStoreSDNode { + +public: + friend class SelectionDAG; + MaskedStoreSDNode(unsigned Order, DebugLoc dl, + SDValue *Operands, unsigned numOperands, + SDVTList VTs, EVT MemVT, MachineMemOperand *MMO) + : MaskedLoadStoreSDNode(ISD::MSTORE, Order, dl, Operands, numOperands, + VTs, MemVT, MMO) + {} + + const SDValue &getData() const { return getOperand(3); } + + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::MSTORE; + } +}; + /// MachineSDNode - An SDNode that represents everything that will be needed /// to construct a MachineInstr. These nodes are created during the /// instruction selection proper phase. diff --git a/include/llvm/CodeGen/StackMapLivenessAnalysis.h b/include/llvm/CodeGen/StackMapLivenessAnalysis.h index 6f07546..f67a6e9 100644 --- a/include/llvm/CodeGen/StackMapLivenessAnalysis.h +++ b/include/llvm/CodeGen/StackMapLivenessAnalysis.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H -#define LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H +#ifndef LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H +#define LLVM_CODEGEN_STACKMAPLIVENESSANALYSIS_H #include "llvm/CodeGen/LivePhysRegs.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -61,4 +61,4 @@ private: } // llvm namespace -#endif // LLVM_CODEGEN_STACKMAP_LIVENESS_ANALYSIS_H +#endif diff --git a/include/llvm/CodeGen/StackMaps.h b/include/llvm/CodeGen/StackMaps.h index 5eddbb6..4e48afe 100644 --- a/include/llvm/CodeGen/StackMaps.h +++ b/include/llvm/CodeGen/StackMaps.h @@ -8,8 +8,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_STACKMAPS -#define LLVM_STACKMAPS +#ifndef LLVM_CODEGEN_STACKMAPS_H +#define LLVM_CODEGEN_STACKMAPS_H #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" @@ -81,6 +81,52 @@ public: unsigned getNextScratchIdx(unsigned StartIdx = 0) const; }; +/// MI-level Statepoint operands +/// +/// Statepoint operands take the form: +/// , , [call arguments], +/// , , +/// , , [other args], +/// [gc values] +class StatepointOpers { +private: + enum { + NCallArgsPos = 0, + CallTargetPos = 1 + }; + +public: + explicit StatepointOpers(const MachineInstr *MI): + MI(MI) { } + + /// Get starting index of non call related arguments + /// (statepoint flags, vm state and gc state). + unsigned getVarIdx() const { + return MI->getOperand(NCallArgsPos).getImm() + 2; + } + + /// Returns the index of the operand containing the number of non-gc non-call + /// arguments. + unsigned getNumVMSArgsIdx() const { + return getVarIdx() + 3; + } + + /// Returns the number of non-gc non-call arguments attached to the + /// statepoint. Note that this is the number of arguments, not the number of + /// operands required to represent those arguments. + unsigned getNumVMSArgs() const { + return MI->getOperand(getNumVMSArgsIdx()).getImm(); + } + + /// Returns the target of the underlying call. + const MachineOperand &getCallTarget() const { + return MI->getOperand(CallTargetPos); + } + +private: + const MachineInstr *MI; +}; + class StackMaps { public: struct Location { @@ -118,6 +164,12 @@ public: StackMaps(AsmPrinter &AP); + void reset() { + CSInfos.clear(); + ConstPool.clear(); + FnStackSize.clear(); + } + /// \brief Generate a stackmap record for a stackmap instruction. /// /// MI must be a raw STACKMAP, not a PATCHPOINT. @@ -126,6 +178,9 @@ public: /// \brief Generate a stackmap record for a patchpoint instruction. void recordPatchPoint(const MachineInstr &MI); + /// \brief Generate a stackmap record for a statepoint instruction. + void recordStatepoint(const MachineInstr &MI); + /// If there is any stack map data, create a stack map section and serialize /// the map info into it. This clears the stack map data structures /// afterwards. @@ -133,10 +188,9 @@ public: private: static const char *WSMP; - typedef SmallVector LocationVec; typedef SmallVector LiveOutVec; - typedef MapVector ConstantPool; + typedef MapVector ConstantPool; typedef MapVector FnStackSizeMap; struct CallsiteInfo { @@ -146,9 +200,9 @@ private: LiveOutVec LiveOuts; CallsiteInfo() : CSOffsetExpr(nullptr), ID(0) {} CallsiteInfo(const MCExpr *CSOffsetExpr, uint64_t ID, - LocationVec &Locations, LiveOutVec &LiveOuts) - : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(Locations), - LiveOuts(LiveOuts) {} + LocationVec &&Locations, LiveOutVec &&LiveOuts) + : CSOffsetExpr(CSOffsetExpr), ID(ID), Locations(std::move(Locations)), + LiveOuts(std::move(LiveOuts)) {} }; typedef std::vector CallsiteInfoList; @@ -196,4 +250,4 @@ private: } -#endif // LLVM_STACKMAPS +#endif diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 87f1401..9209e1c 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -89,8 +89,6 @@ public: ArrayRef ModuleFlags, Mangler &Mang, const TargetMachine &TM) const override; - bool isSectionAtomizableBySymbols(const MCSection &Section) const override; - const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 690b70f..b613666 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -41,7 +41,7 @@ class TargetSchedModel { unsigned MicroOpFactor; // Multiply to normalize microops to resource units. unsigned ResourceLCM; // Resource units per cycle. Latency normalization factor. public: - TargetSchedModel(): STI(nullptr), TII(nullptr) {} + TargetSchedModel(): SchedModel(MCSchedModel::GetDefaultSchedModel()), STI(nullptr), TII(nullptr) {} /// \brief Initialize the machine model for instruction scheduling. /// @@ -167,6 +167,7 @@ public: /// if converter after moving it to TargetSchedModel). unsigned computeInstrLatency(const MachineInstr *MI, bool UseDefaultDefLatency = true) const; + unsigned computeInstrLatency(unsigned Opcode) const; /// \brief Output dependency latency of a pair of defs of the same register. /// diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 996f9ba..d154135 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -18,6 +18,9 @@ /* Define to enable crash overrides */ #cmakedefine ENABLE_CRASH_OVERRIDES +/* Define to disable C++ atexit */ +#cmakedefine DISABLE_LLVM_DYLIB_ATEXIT + /* Define if position independent code is enabled */ #cmakedefine ENABLE_PIC @@ -188,6 +191,9 @@ /* Define to 1 if you have the header file. */ #cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_LINK_H ${HAVE_LINK_H} + /* Define if you can use -rdynamic. */ #define HAVE_LINK_EXPORT_DYNAMIC 1 @@ -456,9 +462,6 @@ /* Have host's ___chkstk */ #cmakedefine HAVE____CHKSTK ${HAVE____CHKSTK} -/* Linker version detected at compile time. */ -#undef HOST_LINK_VERSION - /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS @@ -518,9 +521,6 @@ /* Type of 1st arg on ELM Callback */ #cmakedefine WIN32_ELMCB_PCSTR ${WIN32_ELMCB_PCSTR} -/* Define to empty if `const' does not conform to ANSI C. */ -#undef const - /* Define to `int' if does not define. */ #undef pid_t @@ -542,7 +542,4 @@ /* Define to 1 if you have the `_chsize_s' function. */ #cmakedefine HAVE__CHSIZE_S ${HAVE__CHSIZE_S} -/* Maximum path length */ -#cmakedefine MAXPATHLEN ${MAXPATHLEN} - #endif diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index beed118..ec09c84 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -9,6 +9,9 @@ /* Define if we have libxml2 */ #undef CLANG_HAVE_LIBXML +/* Multilib suffix for libdir. */ +#undef CLANG_LIBDIR_SUFFIX + /* Relative directory for resource files */ #undef CLANG_RESOURCE_DIR @@ -543,6 +546,9 @@ /* Patch version of the LLVM API */ #undef LLVM_VERSION_PATCH +/* LLVM version string */ +#undef LLVM_VERSION_STRING + /* The shared library extension */ #undef LTDL_SHLIB_EXT diff --git a/include/llvm/Config/llvm-config.h.cmake b/include/llvm/Config/llvm-config.h.cmake index 5811164..77201e6 100644 --- a/include/llvm/Config/llvm-config.h.cmake +++ b/include/llvm/Config/llvm-config.h.cmake @@ -92,6 +92,9 @@ /* Minor version of the LLVM API */ #cmakedefine LLVM_VERSION_MINOR ${LLVM_VERSION_MINOR} +/* LLVM version string */ +#define LLVM_VERSION_STRING "${PACKAGE_VERSION}" + /* Define if we link Polly to the tools */ #cmakedefine LINK_POLLY_INTO_TOOLS diff --git a/include/llvm/Config/llvm-config.h.in b/include/llvm/Config/llvm-config.h.in index 5656240..2d6add7 100644 --- a/include/llvm/Config/llvm-config.h.in +++ b/include/llvm/Config/llvm-config.h.in @@ -92,4 +92,7 @@ /* Minor version of the LLVM API */ #undef LLVM_VERSION_MINOR +/* LLVM version string */ +#undef LLVM_VERSION_STRING + #endif diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index c1aba01..622aa69 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -21,7 +21,6 @@ #include "llvm/Object/RelocVisitor.h" #include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" - #include namespace llvm { @@ -66,11 +65,15 @@ class DIInliningInfo { } }; +/// A DINameKind is passed to name search methods to specify a +/// preference regarding the type of name resolution the caller wants. +enum class DINameKind { None, ShortName, LinkageName }; + /// DILineInfoSpecifier - controls which fields of DILineInfo container /// should be filled with data. struct DILineInfoSpecifier { enum class FileLineInfoKind { None, Default, AbsoluteFilePath }; - enum class FunctionNameKind { None, ShortName, LinkageName }; + typedef DINameKind FunctionNameKind; FileLineInfoKind FLIKind; FunctionNameKind FNKind; @@ -103,7 +106,11 @@ enum DIDumpType { DIDT_GnuPubtypes, DIDT_Str, DIDT_StrDwo, - DIDT_StrOffsetsDwo + DIDT_StrOffsetsDwo, + DIDT_AppleNames, + DIDT_AppleTypes, + DIDT_AppleNamespaces, + DIDT_AppleObjC }; // In place of applying the relocations to the data we've read from disk we use @@ -124,7 +131,7 @@ public: virtual ~DIContext(); /// getDWARFContext - get a context for binary DWARF data. - static DIContext *getDWARFContext(object::ObjectFile *); + static DIContext *getDWARFContext(const object::ObjectFile &Obj); virtual void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) = 0; diff --git a/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h new file mode 100644 index 0000000..bb05c30 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFAbbreviationDeclaration.h @@ -0,0 +1,60 @@ +//===-- DWARFAbbreviationDeclaration.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H +#define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFAbbreviationDeclaration { + uint32_t Code; + uint32_t Tag; + bool HasChildren; + + struct AttributeSpec { + AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {} + uint16_t Attr; + uint16_t Form; + }; + typedef SmallVector AttributeSpecVector; + AttributeSpecVector AttributeSpecs; +public: + DWARFAbbreviationDeclaration(); + + uint32_t getCode() const { return Code; } + uint32_t getTag() const { return Tag; } + bool hasChildren() const { return HasChildren; } + + typedef iterator_range + attr_iterator_range; + + attr_iterator_range attributes() const { + return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); + } + + uint16_t getFormByIndex(uint32_t idx) const { + return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0; + } + + uint32_t findAttributeIndex(uint16_t attr) const; + bool extract(DataExtractor Data, uint32_t* OffsetPtr); + void dump(raw_ostream &OS) const; + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARFAcceleratorTable.h new file mode 100644 index 0000000..3fbc1c3 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFAcceleratorTable.h @@ -0,0 +1,49 @@ +//===--- DWARFAcceleratorTable.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include + +namespace llvm { + +class DWARFAcceleratorTable { + + struct Header { + uint32_t Magic; + uint16_t Version; + uint16_t HashFunction; + uint32_t NumBuckets; + uint32_t NumHashes; + uint32_t HeaderDataLength; + }; + + struct HeaderData { + typedef uint16_t AtomType; + typedef uint16_t Form; + uint32_t DIEOffsetBase; + SmallVector, 3> Atoms; + }; + + struct Header Hdr; + struct HeaderData HdrData; + DataExtractor AccelSection; + DataExtractor StringSection; + const RelocAddrMap& Relocs; +public: + DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection, + const RelocAddrMap &Relocs) + : AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {} + + bool extract(); + void dump(raw_ostream &OS) const; +}; + +} diff --git a/include/llvm/DebugInfo/DWARFCompileUnit.h b/include/llvm/DebugInfo/DWARFCompileUnit.h new file mode 100644 index 0000000..dbf777c --- /dev/null +++ b/include/llvm/DebugInfo/DWARFCompileUnit.h @@ -0,0 +1,31 @@ +//===-- DWARFCompileUnit.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H + +#include "llvm/DebugInfo/DWARFUnit.h" + +namespace llvm { + +class DWARFCompileUnit : public DWARFUnit { +public: + DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + void dump(raw_ostream &OS); + // VTable anchor. + ~DWARFCompileUnit() override; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFContext.h b/include/llvm/DebugInfo/DWARFContext.h new file mode 100644 index 0000000..82b5bb0 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFContext.h @@ -0,0 +1,292 @@ +//===-- DWARFContext.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===/ + +#ifndef LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H +#define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H + +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARFCompileUnit.h" +#include "llvm/DebugInfo/DWARFDebugAranges.h" +#include "llvm/DebugInfo/DWARFDebugFrame.h" +#include "llvm/DebugInfo/DWARFDebugLine.h" +#include "llvm/DebugInfo/DWARFDebugLoc.h" +#include "llvm/DebugInfo/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARFSection.h" +#include "llvm/DebugInfo/DWARFTypeUnit.h" +#include + +namespace llvm { + +/// DWARFContext +/// This data structure is the top level entity that deals with dwarf debug +/// information parsing. The actual data is supplied through pure virtual +/// methods that a concrete implementation provides. +class DWARFContext : public DIContext { + + DWARFUnitSection CUs; + std::vector> TUs; + std::unique_ptr Abbrev; + std::unique_ptr Loc; + std::unique_ptr Aranges; + std::unique_ptr Line; + std::unique_ptr DebugFrame; + + DWARFUnitSection DWOCUs; + std::vector> DWOTUs; + std::unique_ptr AbbrevDWO; + std::unique_ptr LocDWO; + + DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION; + DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION; + + /// Read compile units from the debug_info section (if necessary) + /// and store them in CUs. + void parseCompileUnits(); + + /// Read type units from the debug_types sections (if necessary) + /// and store them in TUs. + void parseTypeUnits(); + + /// Read compile units from the debug_info.dwo section (if necessary) + /// and store them in DWOCUs. + void parseDWOCompileUnits(); + + /// Read type units from the debug_types.dwo section (if necessary) + /// and store them in DWOTUs. + void parseDWOTypeUnits(); + +public: + DWARFContext() : DIContext(CK_DWARF) {} + + static bool classof(const DIContext *DICtx) { + return DICtx->getKind() == CK_DWARF; + } + + void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; + + typedef DWARFUnitSection::iterator_range cu_iterator_range; + typedef DWARFUnitSection::iterator_range tu_iterator_range; + typedef iterator_range>::iterator> tu_section_iterator_range; + + /// Get compile units in this context. + cu_iterator_range compile_units() { + parseCompileUnits(); + return cu_iterator_range(CUs.begin(), CUs.end()); + } + + /// Get type units in this context. + tu_section_iterator_range type_unit_sections() { + parseTypeUnits(); + return tu_section_iterator_range(TUs.begin(), TUs.end()); + } + + /// Get compile units in the DWO context. + cu_iterator_range dwo_compile_units() { + parseDWOCompileUnits(); + return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); + } + + /// Get type units in the DWO context. + tu_section_iterator_range dwo_type_unit_sections() { + parseDWOTypeUnits(); + return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); + } + + /// Get the number of compile units in this context. + unsigned getNumCompileUnits() { + parseCompileUnits(); + return CUs.size(); + } + + /// Get the number of compile units in this context. + unsigned getNumTypeUnits() { + parseTypeUnits(); + return TUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOCompileUnits() { + parseDWOCompileUnits(); + return DWOCUs.size(); + } + + /// Get the number of compile units in the DWO context. + unsigned getNumDWOTypeUnits() { + parseDWOTypeUnits(); + return DWOTUs.size(); + } + + /// Get the compile unit at the specified index for this compile unit. + DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { + parseCompileUnits(); + return CUs[index].get(); + } + + /// Get the compile unit at the specified index for the DWO compile units. + DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { + parseDWOCompileUnits(); + return DWOCUs[index].get(); + } + + /// Get a pointer to the parsed DebugAbbrev object. + const DWARFDebugAbbrev *getDebugAbbrev(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLoc *getDebugLoc(); + + /// Get a pointer to the parsed dwo abbreviations object. + const DWARFDebugAbbrev *getDebugAbbrevDWO(); + + /// Get a pointer to the parsed DebugLoc object. + const DWARFDebugLocDWO *getDebugLocDWO(); + + /// Get a pointer to the parsed DebugAranges object. + const DWARFDebugAranges *getDebugAranges(); + + /// Get a pointer to the parsed frame information object. + const DWARFDebugFrame *getDebugFrame(); + + /// Get a pointer to a parsed line table corresponding to a compile unit. + const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); + + DILineInfo getLineInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + DIInliningInfo getInliningInfoForAddress(uint64_t Address, + DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; + + virtual bool isLittleEndian() const = 0; + virtual uint8_t getAddressSize() const = 0; + virtual const DWARFSection &getInfoSection() = 0; + typedef MapVector> TypeSectionMap; + virtual const TypeSectionMap &getTypesSections() = 0; + virtual StringRef getAbbrevSection() = 0; + virtual const DWARFSection &getLocSection() = 0; + virtual StringRef getARangeSection() = 0; + virtual StringRef getDebugFrameSection() = 0; + virtual const DWARFSection &getLineSection() = 0; + virtual StringRef getStringSection() = 0; + virtual StringRef getRangeSection() = 0; + virtual StringRef getPubNamesSection() = 0; + virtual StringRef getPubTypesSection() = 0; + virtual StringRef getGnuPubNamesSection() = 0; + virtual StringRef getGnuPubTypesSection() = 0; + + // Sections for DWARF5 split dwarf proposal. + virtual const DWARFSection &getInfoDWOSection() = 0; + virtual const TypeSectionMap &getTypesDWOSections() = 0; + virtual StringRef getAbbrevDWOSection() = 0; + virtual const DWARFSection &getLineDWOSection() = 0; + virtual const DWARFSection &getLocDWOSection() = 0; + virtual StringRef getStringDWOSection() = 0; + virtual StringRef getStringOffsetDWOSection() = 0; + virtual StringRef getRangeDWOSection() = 0; + virtual StringRef getAddrSection() = 0; + virtual const DWARFSection& getAppleNamesSection() = 0; + virtual const DWARFSection& getAppleTypesSection() = 0; + virtual const DWARFSection& getAppleNamespacesSection() = 0; + virtual const DWARFSection& getAppleObjCSection() = 0; + + static bool isSupportedVersion(unsigned version) { + return version == 2 || version == 3 || version == 4; + } +private: + /// Return the compile unit that includes an offset (relative to .debug_info). + DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); + + /// Return the compile unit which contains instruction with provided + /// address. + DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); +}; + +/// DWARFContextInMemory is the simplest possible implementation of a +/// DWARFContext. It assumes all content is available in memory and stores +/// pointers to it. +class DWARFContextInMemory : public DWARFContext { + virtual void anchor(); + bool IsLittleEndian; + uint8_t AddressSize; + DWARFSection InfoSection; + TypeSectionMap TypesSections; + StringRef AbbrevSection; + DWARFSection LocSection; + StringRef ARangeSection; + StringRef DebugFrameSection; + DWARFSection LineSection; + StringRef StringSection; + StringRef RangeSection; + StringRef PubNamesSection; + StringRef PubTypesSection; + StringRef GnuPubNamesSection; + StringRef GnuPubTypesSection; + + // Sections for DWARF5 split dwarf proposal. + DWARFSection InfoDWOSection; + TypeSectionMap TypesDWOSections; + StringRef AbbrevDWOSection; + DWARFSection LineDWOSection; + DWARFSection LocDWOSection; + StringRef StringDWOSection; + StringRef StringOffsetDWOSection; + StringRef RangeDWOSection; + StringRef AddrSection; + DWARFSection AppleNamesSection; + DWARFSection AppleTypesSection; + DWARFSection AppleNamespacesSection; + DWARFSection AppleObjCSection; + + SmallVector, 4> UncompressedSections; + +public: + DWARFContextInMemory(const object::ObjectFile &Obj); + bool isLittleEndian() const override { return IsLittleEndian; } + uint8_t getAddressSize() const override { return AddressSize; } + const DWARFSection &getInfoSection() override { return InfoSection; } + const TypeSectionMap &getTypesSections() override { return TypesSections; } + StringRef getAbbrevSection() override { return AbbrevSection; } + const DWARFSection &getLocSection() override { return LocSection; } + StringRef getARangeSection() override { return ARangeSection; } + StringRef getDebugFrameSection() override { return DebugFrameSection; } + const DWARFSection &getLineSection() override { return LineSection; } + StringRef getStringSection() override { return StringSection; } + StringRef getRangeSection() override { return RangeSection; } + StringRef getPubNamesSection() override { return PubNamesSection; } + StringRef getPubTypesSection() override { return PubTypesSection; } + StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } + StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } + const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; } + const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; } + const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; } + const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; } + + // Sections for DWARF5 split dwarf proposal. + const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; } + const TypeSectionMap &getTypesDWOSections() override { + return TypesDWOSections; + } + StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } + const DWARFSection &getLineDWOSection() override { return LineDWOSection; } + const DWARFSection &getLocDWOSection() override { return LocDWOSection; } + StringRef getStringDWOSection() override { return StringDWOSection; } + StringRef getStringOffsetDWOSection() override { + return StringOffsetDWOSection; + } + StringRef getRangeDWOSection() override { return RangeDWOSection; } + StringRef getAddrSection() override { + return AddrSection; + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARFDebugAbbrev.h new file mode 100644 index 0000000..6752df9 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugAbbrev.h @@ -0,0 +1,63 @@ +//===-- DWARFDebugAbbrev.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H + +#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h" +#include +#include +#include + +namespace llvm { + +class DWARFAbbreviationDeclarationSet { + uint32_t Offset; + /// Code of the first abbreviation, if all abbreviations in the set have + /// consecutive codes. UINT32_MAX otherwise. + uint32_t FirstAbbrCode; + std::vector Decls; + +public: + DWARFAbbreviationDeclarationSet(); + + uint32_t getOffset() const { return Offset; } + void dump(raw_ostream &OS) const; + bool extract(DataExtractor Data, uint32_t *OffsetPtr); + + const DWARFAbbreviationDeclaration * + getAbbreviationDeclaration(uint32_t AbbrCode) const; + +private: + void clear(); +}; + +class DWARFDebugAbbrev { + typedef std::map + DWARFAbbreviationDeclarationSetMap; + + DWARFAbbreviationDeclarationSetMap AbbrDeclSets; + mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; + +public: + DWARFDebugAbbrev(); + + const DWARFAbbreviationDeclarationSet * + getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; + + void dump(raw_ostream &OS) const; + void extract(DataExtractor Data); + +private: + void clear(); +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugArangeSet.h b/include/llvm/DebugInfo/DWARFDebugArangeSet.h new file mode 100644 index 0000000..837a8e6 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugArangeSet.h @@ -0,0 +1,70 @@ +//===-- DWARFDebugArangeSet.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugArangeSet { +public: + struct Header { + // The total length of the entries for that set, not including the length + // field itself. + uint32_t Length; + // The offset from the beginning of the .debug_info section of the + // compilation unit entry referenced by the table. + uint32_t CuOffset; + // The DWARF version number. + uint16_t Version; + // The size in bytes of an address on the target architecture. For segmented + // addressing, this is the size of the offset portion of the address. + uint8_t AddrSize; + // The size in bytes of a segment descriptor on the target architecture. + // If the target system uses a flat address space, this value is 0. + uint8_t SegSize; + }; + + struct Descriptor { + uint64_t Address; + uint64_t Length; + uint64_t getEndAddress() const { return Address + Length; } + }; + +private: + typedef std::vector DescriptorColl; + typedef iterator_range desc_iterator_range; + + uint32_t Offset; + Header HeaderData; + DescriptorColl ArangeDescriptors; + +public: + DWARFDebugArangeSet() { clear(); } + void clear(); + bool extract(DataExtractor data, uint32_t *offset_ptr); + void dump(raw_ostream &OS) const; + + uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } + + desc_iterator_range descriptors() const { + return desc_iterator_range(ArangeDescriptors.begin(), + ArangeDescriptors.end()); + } +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugAranges.h b/include/llvm/DebugInfo/DWARFDebugAranges.h new file mode 100644 index 0000000..791f010 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugAranges.h @@ -0,0 +1,87 @@ +//===-- DWARFDebugAranges.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H + +#include "llvm/ADT/DenseSet.h" +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class DWARFContext; + +class DWARFDebugAranges { +public: + void generate(DWARFContext *CTX); + uint32_t findAddress(uint64_t Address) const; + +private: + void clear(); + void extract(DataExtractor DebugArangesData); + + // Call appendRange multiple times and then call construct. + void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); + void construct(); + + struct Range { + explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL, + uint32_t CUOffset = -1U) + : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {} + + void setHighPC(uint64_t HighPC) { + if (HighPC == -1ULL || HighPC <= LowPC) + Length = 0; + else + Length = HighPC - LowPC; + } + uint64_t HighPC() const { + if (Length) + return LowPC + Length; + return -1ULL; + } + + bool containsAddress(uint64_t Address) const { + return LowPC <= Address && Address < HighPC(); + } + bool operator<(const Range &other) const { + return LowPC < other.LowPC; + } + + uint64_t LowPC; // Start of address range. + uint32_t Length; // End of address range (not including this address). + uint32_t CUOffset; // Offset of the compile unit or die. + }; + + struct RangeEndpoint { + uint64_t Address; + uint32_t CUOffset; + bool IsRangeStart; + + RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) + : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} + + bool operator<(const RangeEndpoint &Other) const { + return Address < Other.Address; + } + }; + + + typedef std::vector RangeColl; + typedef RangeColl::const_iterator RangeCollIterator; + + std::vector Endpoints; + RangeColl Aranges; + DenseSet ParsedCUOffsets; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARFDebugFrame.h new file mode 100644 index 0000000..be925cb --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugFrame.h @@ -0,0 +1,43 @@ +//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H + +#include "llvm/Support/DataExtractor.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +namespace llvm { + +class FrameEntry; + +/// \brief A parsed .debug_frame section +/// +class DWARFDebugFrame { +public: + DWARFDebugFrame(); + ~DWARFDebugFrame(); + + /// \brief Dump the section data into the given stream. + void dump(raw_ostream &OS) const; + + /// \brief Parse the section from raw data. + /// data is assumed to be pointing to the beginning of the section. + void parse(DataExtractor Data); + +private: + std::vector> Entries; +}; + + +} // namespace llvm + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugInfoEntry.h b/include/llvm/DebugInfo/DWARFDebugInfoEntry.h new file mode 100644 index 0000000..f05d64b --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugInfoEntry.h @@ -0,0 +1,160 @@ +//===-- DWARFDebugInfoEntry.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARFAbbreviationDeclaration.h" +#include "llvm/DebugInfo/DWARFDebugRangeList.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class DWARFDebugAranges; +class DWARFCompileUnit; +class DWARFUnit; +class DWARFContext; +class DWARFFormValue; +struct DWARFDebugInfoEntryInlinedChain; + +/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. +class DWARFDebugInfoEntryMinimal { + /// Offset within the .debug_info of the start of this entry. + uint32_t Offset; + + /// How many to add to "this" to get the sibling. + uint32_t SiblingIdx; + + const DWARFAbbreviationDeclaration *AbbrevDecl; +public: + DWARFDebugInfoEntryMinimal() + : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} + + void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, + unsigned indent = 0) const; + void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, + uint16_t attr, uint16_t form, unsigned indent = 0) const; + + /// Extracts a debug info entry, which is a child of a given unit, + /// starting at a given offset. If DIE can't be extracted, returns false and + /// doesn't change OffsetPtr. + bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); + + uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } + bool isNULL() const { return AbbrevDecl == nullptr; } + + /// Returns true if DIE represents a subprogram (not inlined). + bool isSubprogramDIE() const; + /// Returns true if DIE represents a subprogram or an inlined + /// subroutine. + bool isSubroutineDIE() const; + + uint32_t getOffset() const { return Offset; } + bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } + + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + const DWARFDebugInfoEntryMinimal *getSibling() const { + return SiblingIdx > 0 ? this + SiblingIdx : nullptr; + } + + // We know we are kept in a vector of contiguous entries, so we know + // we don't need to store our child pointer, if we have a child it will + // be the next entry in the list... + const DWARFDebugInfoEntryMinimal *getFirstChild() const { + return hasChildren() ? this + 1 : nullptr; + } + + void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { + if (Sibling) { + // We know we are kept in a vector of contiguous entries, so we know + // our sibling will be some index after "this". + SiblingIdx = Sibling - this; + } else + SiblingIdx = 0; + } + + const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { + return AbbrevDecl; + } + + bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr, + DWARFFormValue &FormValue) const; + + const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr, + const char *FailValue) const; + + uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, + const uint16_t Attr, + uint64_t FailValue) const; + + uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; + + /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. + /// Returns true if both attributes are present. + bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, + uint64_t &HighPC) const; + + DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; + + void collectChildrenAddressRanges(const DWARFUnit *U, + DWARFAddressRangesVector &Ranges) const; + + bool addressRangeContainsAddress(const DWARFUnit *U, + const uint64_t Address) const; + + /// If a DIE represents a subprogram (or inlined subroutine), + /// returns its mangled name (or short name, if mangled is missing). + /// This name may be fetched from specification or abstract origin + /// for this subprogram. Returns null if no name is found. + const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const; + + /// Return the DIE name resolving DW_AT_sepcification or + /// DW_AT_abstract_origin references if necessary. + /// Returns null if no name is found. + const char *getName(const DWARFUnit *U, DINameKind Kind) const; + + /// Retrieves values of DW_AT_call_file, DW_AT_call_line and + /// DW_AT_call_column from DIE (or zeroes if they are missing). + void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, + uint32_t &CallLine, uint32_t &CallColumn) const; + + /// Get inlined chain for a given address, rooted at the current DIE. + /// Returns empty chain if address is not contained in address range + /// of current DIE. + DWARFDebugInfoEntryInlinedChain + getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const; +}; + +/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine +/// DIEs, (possibly ending with subprogram DIE), all of which are contained +/// in some concrete inlined instance tree. Address range for each DIE +/// (except the last DIE) in this chain is contained in address +/// range for next DIE in the chain. +struct DWARFDebugInfoEntryInlinedChain { + DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} + SmallVector DIEs; + const DWARFUnit *U; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARFDebugLine.h new file mode 100644 index 0000000..c5ee76e --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugLine.h @@ -0,0 +1,238 @@ +//===-- DWARFDebugLine.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H + +#include "llvm/DebugInfo/DIContext.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" +#include +#include +#include + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLine { +public: + DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} + struct FileNameEntry { + FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {} + + const char *Name; + uint64_t DirIdx; + uint64_t ModTime; + uint64_t Length; + }; + + struct Prologue { + Prologue(); + + // The size in bytes of the statement information for this compilation unit + // (not including the total_length field itself). + uint32_t TotalLength; + // Version identifier for the statement information format. + uint16_t Version; + // The number of bytes following the prologue_length field to the beginning + // of the first byte of the statement program itself. + uint32_t PrologueLength; + // The size in bytes of the smallest target machine instruction. Statement + // program opcodes that alter the address register first multiply their + // operands by this value. + uint8_t MinInstLength; + // The maximum number of individual operations that may be encoded in an + // instruction. + uint8_t MaxOpsPerInst; + // The initial value of theis_stmtregister. + uint8_t DefaultIsStmt; + // This parameter affects the meaning of the special opcodes. See below. + int8_t LineBase; + // This parameter affects the meaning of the special opcodes. See below. + uint8_t LineRange; + // The number assigned to the first special opcode. + uint8_t OpcodeBase; + std::vector StandardOpcodeLengths; + std::vector IncludeDirectories; + std::vector FileNames; + + // Length of the prologue in bytes. + uint32_t getLength() const { + return PrologueLength + sizeof(TotalLength) + sizeof(Version) + + sizeof(PrologueLength); + } + // Length of the line table data in bytes (not including the prologue). + uint32_t getStatementTableLength() const { + return TotalLength + sizeof(TotalLength) - getLength(); + } + int32_t getMaxLineIncrementForSpecialOpcode() const { + return LineBase + (int8_t)LineRange - 1; + } + + void clear(); + void dump(raw_ostream &OS) const; + bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr); + }; + + // Standard .debug_line state machine structure. + struct Row { + explicit Row(bool default_is_stmt = false); + + /// Called after a row is appended to the matrix. + void postAppend(); + void reset(bool default_is_stmt); + void dump(raw_ostream &OS) const; + + static bool orderByAddress(const Row& LHS, const Row& RHS) { + return LHS.Address < RHS.Address; + } + + // The program-counter value corresponding to a machine instruction + // generated by the compiler. + uint64_t Address; + // An unsigned integer indicating a source line number. Lines are numbered + // beginning at 1. The compiler may emit the value 0 in cases where an + // instruction cannot be attributed to any source line. + uint32_t Line; + // An unsigned integer indicating a column number within a source line. + // Columns are numbered beginning at 1. The value 0 is reserved to indicate + // that a statement begins at the 'left edge' of the line. + uint16_t Column; + // An unsigned integer indicating the identity of the source file + // corresponding to a machine instruction. + uint16_t File; + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + uint8_t Isa; + // An unsigned integer representing the DWARF path discriminator value + // for this location. + uint32_t Discriminator; + // A boolean indicating that the current instruction is the beginning of a + // statement. + uint8_t IsStmt:1, + // A boolean indicating that the current instruction is the + // beginning of a basic block. + BasicBlock:1, + // A boolean indicating that the current address is that of the + // first byte after the end of a sequence of target machine + // instructions. + EndSequence:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an entry breakpoint + // of a function. + PrologueEnd:1, + // A boolean indicating that the current address is one (of possibly + // many) where execution should be suspended for an exit breakpoint + // of a function. + EpilogueBegin:1; + }; + + // Represents a series of contiguous machine instructions. Line table for each + // compilation unit may consist of multiple sequences, which are not + // guaranteed to be in the order of ascending instruction address. + struct Sequence { + // Sequence describes instructions at address range [LowPC, HighPC) + // and is described by line table rows [FirstRowIndex, LastRowIndex). + uint64_t LowPC; + uint64_t HighPC; + unsigned FirstRowIndex; + unsigned LastRowIndex; + bool Empty; + + Sequence(); + void reset(); + + static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { + return LHS.LowPC < RHS.LowPC; + } + bool isValid() const { + return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); + } + bool containsPC(uint64_t pc) const { + return (LowPC <= pc && pc < HighPC); + } + }; + + struct LineTable { + LineTable(); + + void appendRow(const DWARFDebugLine::Row &R) { + Rows.push_back(R); + } + void appendSequence(const DWARFDebugLine::Sequence &S) { + Sequences.push_back(S); + } + + // Returns the index of the row with file/line info for a given address, + // or -1 if there is no such row. + uint32_t lookupAddress(uint64_t address) const; + + bool lookupAddressRange(uint64_t address, uint64_t size, + std::vector &result) const; + + // Extracts filename by its index in filename table in prologue. + // Returns true on success. + bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + std::string &Result) const; + + // Fills the Result argument with the file and line information + // corresponding to Address. Returns true on success. + bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, + DILineInfoSpecifier::FileLineInfoKind Kind, + DILineInfo &Result) const; + + void dump(raw_ostream &OS) const; + void clear(); + + /// Parse prologue and all rows. + bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, + uint32_t *offset_ptr); + + struct Prologue Prologue; + typedef std::vector RowVector; + typedef RowVector::const_iterator RowIter; + typedef std::vector SequenceVector; + typedef SequenceVector::const_iterator SequenceIter; + RowVector Rows; + SequenceVector Sequences; + }; + + const LineTable *getLineTable(uint32_t offset) const; + const LineTable *getOrParseLineTable(DataExtractor debug_line_data, + uint32_t offset); + +private: + struct ParsingState { + ParsingState(struct LineTable *LT); + + void resetRowAndSequence(); + void appendRowToMatrix(uint32_t offset); + + // Line table we're currently parsing. + struct LineTable *LineTable; + // The row number that starts at zero for the prologue, and increases for + // each row added to the matrix. + unsigned RowNumber; + struct Row Row; + struct Sequence Sequence; + }; + + typedef std::map LineTableMapTy; + typedef LineTableMapTy::iterator LineTableIter; + typedef LineTableMapTy::const_iterator LineTableConstIter; + + const RelocAddrMap *RelocMap; + LineTableMapTy LineTableMap; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARFDebugLoc.h new file mode 100644 index 0000000..a6135a0 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugLoc.h @@ -0,0 +1,81 @@ +//===-- DWARFDebugLoc.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/Support/DataExtractor.h" + +namespace llvm { + +class raw_ostream; + +class DWARFDebugLoc { + /// A single location within a location list. + struct Entry { + /// The beginning address of the instruction range. + uint64_t Begin; + /// The ending address of the instruction range. + uint64_t End; + /// The location of the variable within the specified range. + SmallVector Loc; + }; + + /// A list of locations that contain one variable. + struct LocationList { + /// The beginning offset where this location list is stored in the debug_loc + /// section. + unsigned Offset; + /// All the locations in which the variable is stored. + SmallVector Entries; + }; + + typedef SmallVector LocationLists; + + /// A list of all the variables in the debug_loc section, each one describing + /// the locations in which the variable is stored. + LocationLists Locations; + + /// A map used to resolve binary relocations. + const RelocAddrMap &RelocMap; + +public: + DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {} + /// Print the location lists found within the debug_loc section. + void dump(raw_ostream &OS) const; + /// Parse the debug_loc section accessible via the 'data' parameter using the + /// specified address size to interpret the address ranges. + void parse(DataExtractor data, unsigned AddressSize); +}; + +class DWARFDebugLocDWO { + struct Entry { + uint64_t Start; + uint32_t Length; + SmallVector Loc; + }; + + struct LocationList { + unsigned Offset; + SmallVector Entries; + }; + + typedef SmallVector LocationLists; + + LocationLists Locations; + +public: + void parse(DataExtractor data); + void dump(raw_ostream &OS) const; +}; +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARFDebugRangeList.h new file mode 100644 index 0000000..4ee3bda --- /dev/null +++ b/include/llvm/DebugInfo/DWARFDebugRangeList.h @@ -0,0 +1,77 @@ +//===-- DWARFDebugRangeList.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H +#define LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H + +#include "llvm/Support/DataExtractor.h" +#include + +namespace llvm { + +class raw_ostream; + +/// DWARFAddressRangesVector - represents a set of absolute address ranges. +typedef std::vector> DWARFAddressRangesVector; + +class DWARFDebugRangeList { +public: + struct RangeListEntry { + // A beginning address offset. This address offset has the size of an + // address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the beginning + // of an address range. + uint64_t StartAddress; + // An ending address offset. This address offset again has the size of + // an address and is relative to the applicable base address of the + // compilation unit referencing this range list. It marks the first + // address past the end of the address range. The ending address must + // be greater than or equal to the beginning address. + uint64_t EndAddress; + // The end of any given range list is marked by an end of list entry, + // which consists of a 0 for the beginning address offset + // and a 0 for the ending address offset. + bool isEndOfListEntry() const { + return (StartAddress == 0) && (EndAddress == 0); + } + // A base address selection entry consists of: + // 1. The value of the largest representable address offset + // (for example, 0xffffffff when the size of an address is 32 bits). + // 2. An address, which defines the appropriate base address for + // use in interpreting the beginning and ending address offsets of + // subsequent entries of the location list. + bool isBaseAddressSelectionEntry(uint8_t AddressSize) const { + assert(AddressSize == 4 || AddressSize == 8); + if (AddressSize == 4) + return StartAddress == -1U; + else + return StartAddress == -1ULL; + } + }; + +private: + // Offset in .debug_ranges section. + uint32_t Offset; + uint8_t AddressSize; + std::vector Entries; + +public: + DWARFDebugRangeList() { clear(); } + void clear(); + void dump(raw_ostream &OS) const; + bool extract(DataExtractor data, uint32_t *offset_ptr); + /// getAbsoluteRanges - Returns absolute address ranges defined by this range + /// list. Has to be passed base address of the compile unit referencing this + /// range list. + DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const; +}; + +} // namespace llvm + +#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H diff --git a/include/llvm/DebugInfo/DWARFFormValue.h b/include/llvm/DebugInfo/DWARFFormValue.h index d517a72..5bb6d1b 100644 --- a/include/llvm/DebugInfo/DWARFFormValue.h +++ b/include/llvm/DebugInfo/DWARFFormValue.h @@ -57,6 +57,13 @@ public: bool isFormClass(FormClass FC) const; void dump(raw_ostream &OS, const DWARFUnit *U) const; + + /// \brief extracts a value in data at offset *offset_ptr. + /// + /// The passed DWARFUnit is allowed to be nullptr, in which + /// case no relocation processing will be performed and some + /// kind of forms that depend on Unit information are disallowed. + /// \returns wether the extraction succeeded. bool extractValue(DataExtractor data, uint32_t *offset_ptr, const DWARFUnit *u); bool isInlinedCStr() const { @@ -70,6 +77,7 @@ public: Optional getAsCString(const DWARFUnit *U) const; Optional getAsAddress(const DWARFUnit *U) const; Optional getAsSectionOffset() const; + Optional> getAsBlock() const; bool skipValue(DataExtractor debug_info_data, uint32_t *offset_ptr, const DWARFUnit *u) const; diff --git a/include/llvm/DebugInfo/DWARFRelocMap.h b/include/llvm/DebugInfo/DWARFRelocMap.h new file mode 100644 index 0000000..d7fe303 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFRelocMap.h @@ -0,0 +1,22 @@ +//===-- DWARFRelocMap.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H +#define LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +typedef DenseMap > RelocAddrMap; + +} // namespace llvm + +#endif + diff --git a/include/llvm/DebugInfo/DWARFSection.h b/include/llvm/DebugInfo/DWARFSection.h new file mode 100644 index 0000000..5f09d9e --- /dev/null +++ b/include/llvm/DebugInfo/DWARFSection.h @@ -0,0 +1,24 @@ +//===-- DWARFSection.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFSECTION_H +#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H + +#include "llvm/DebugInfo/DWARFRelocMap.h" + +namespace llvm { + +struct DWARFSection { + StringRef Data; + RelocAddrMap Relocs; +}; + +} + +#endif diff --git a/include/llvm/DebugInfo/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARFTypeUnit.h new file mode 100644 index 0000000..213b541 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFTypeUnit.h @@ -0,0 +1,38 @@ +//===-- DWARFTypeUnit.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H + +#include "llvm/DebugInfo/DWARFUnit.h" + +namespace llvm { + +class DWARFTypeUnit : public DWARFUnit { +private: + uint64_t TypeHash; + uint32_t TypeOffset; +public: + DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} + uint32_t getHeaderSize() const override { + return DWARFUnit::getHeaderSize() + 12; + } + void dump(raw_ostream &OS); +protected: + bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; +}; + +} + +#endif + diff --git a/include/llvm/DebugInfo/DWARFUnit.h b/include/llvm/DebugInfo/DWARFUnit.h new file mode 100644 index 0000000..d71a1b6 --- /dev/null +++ b/include/llvm/DebugInfo/DWARFUnit.h @@ -0,0 +1,245 @@ +//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_DEBUGINFO_DWARFUNIT_H +#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H + +#include "llvm/DebugInfo/DWARFDebugAbbrev.h" +#include "llvm/DebugInfo/DWARFDebugInfoEntry.h" +#include "llvm/DebugInfo/DWARFDebugRangeList.h" +#include "llvm/DebugInfo/DWARFRelocMap.h" +#include "llvm/DebugInfo/DWARFSection.h" +#include + +namespace llvm { + +namespace object { +class ObjectFile; +} + +class DWARFContext; +class DWARFDebugAbbrev; +class DWARFUnit; +class StringRef; +class raw_ostream; + +/// Base class for all DWARFUnitSection classes. This provides the +/// functionality common to all unit types. +class DWARFUnitSectionBase { +public: + /// Returns the Unit that contains the given section offset in the + /// same section this Unit originated from. + virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; + + void parse(DWARFContext &C, const DWARFSection &Section); + void parseDWO(DWARFContext &C, const DWARFSection &DWOSection); + +protected: + virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool isLittleEndian) = 0; + + ~DWARFUnitSectionBase() {} +}; + +/// Concrete instance of DWARFUnitSection, specialized for one Unit type. +template +class DWARFUnitSection final : public SmallVector, 1>, + public DWARFUnitSectionBase { + + struct UnitOffsetComparator { + bool operator()(uint32_t LHS, + const std::unique_ptr &RHS) const { + return LHS < RHS->getNextUnitOffset(); + } + }; + + bool Parsed; + +public: + DWARFUnitSection() : Parsed(false) {} + DWARFUnitSection(DWARFUnitSection &&DUS) : + SmallVector, 1>(std::move(DUS)), Parsed(DUS.Parsed) {} + + typedef llvm::SmallVectorImpl> UnitVector; + typedef typename UnitVector::iterator iterator; + typedef llvm::iterator_range iterator_range; + + UnitType *getUnitForOffset(uint32_t Offset) const override { + auto *CU = std::upper_bound(this->begin(), this->end(), Offset, + UnitOffsetComparator()); + if (CU != this->end()) + return CU->get(); + return nullptr; + } + +private: + void parseImpl(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE) override { + if (Parsed) + return; + DataExtractor Data(Section.Data, LE, 0); + uint32_t Offset = 0; + while (Data.isValidOffset(Offset)) { + auto U = llvm::make_unique(Context, Section, DA, RS, SS, SOS, + AOS, LE, *this); + if (!U->extract(Data, &Offset)) + break; + this->push_back(std::move(U)); + Offset = this->back()->getNextUnitOffset(); + } + Parsed = true; + } +}; + +class DWARFUnit { + DWARFContext &Context; + // Section containing this DWARFUnit. + const DWARFSection &InfoSection; + + const DWARFDebugAbbrev *Abbrev; + StringRef RangeSection; + uint32_t RangeSectionBase; + StringRef StringSection; + StringRef StringOffsetSection; + StringRef AddrOffsetSection; + uint32_t AddrOffsetSectionBase; + bool isLittleEndian; + const DWARFUnitSectionBase &UnitSection; + + uint32_t Offset; + uint32_t Length; + uint16_t Version; + const DWARFAbbreviationDeclarationSet *Abbrevs; + uint8_t AddrSize; + uint64_t BaseAddr; + // The compile unit debug information entry items. + std::vector DieArray; + + class DWOHolder { + object::OwningBinary DWOFile; + std::unique_ptr DWOContext; + DWARFUnit *DWOU; + public: + DWOHolder(StringRef DWOPath); + DWARFUnit *getUnit() const { return DWOU; } + }; + std::unique_ptr DWO; + +protected: + virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); + /// Size in bytes of the unit header. + virtual uint32_t getHeaderSize() const { return 11; } + +public: + DWARFUnit(DWARFContext &Context, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection); + + virtual ~DWARFUnit(); + + DWARFContext& getContext() const { return Context; } + + StringRef getStringSection() const { return StringSection; } + StringRef getStringOffsetSection() const { return StringOffsetSection; } + void setAddrOffsetSection(StringRef AOS, uint32_t Base) { + AddrOffsetSection = AOS; + AddrOffsetSectionBase = Base; + } + void setRangesSection(StringRef RS, uint32_t Base) { + RangeSection = RS; + RangeSectionBase = Base; + } + + bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; + // FIXME: Result should be uint64_t in DWARF64. + bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const; + + DataExtractor getDebugInfoExtractor() const { + return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize); + } + DataExtractor getStringExtractor() const { + return DataExtractor(StringSection, false, 0); + } + + const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; } + + bool extract(DataExtractor debug_info, uint32_t* offset_ptr); + + /// extractRangeList - extracts the range list referenced by this compile + /// unit from .debug_ranges section. Returns true on success. + /// Requires that compile unit is already extracted. + bool extractRangeList(uint32_t RangeListOffset, + DWARFDebugRangeList &RangeList) const; + void clear(); + uint32_t getOffset() const { return Offset; } + uint32_t getNextUnitOffset() const { return Offset + Length + 4; } + uint32_t getLength() const { return Length; } + uint16_t getVersion() const { return Version; } + const DWARFAbbreviationDeclarationSet *getAbbreviations() const { + return Abbrevs; + } + uint8_t getAddressByteSize() const { return AddrSize; } + uint64_t getBaseAddress() const { return BaseAddr; } + + void setBaseAddress(uint64_t base_addr) { + BaseAddr = base_addr; + } + + const DWARFDebugInfoEntryMinimal * + getCompileUnitDIE(bool extract_cu_die_only = true) { + extractDIEsIfNeeded(extract_cu_die_only); + return DieArray.empty() ? nullptr : &DieArray[0]; + } + + const char *getCompilationDir(); + uint64_t getDWOId(); + + void collectAddressRanges(DWARFAddressRangesVector &CURanges); + + /// getInlinedChainForAddress - fetches inlined chain for a given address. + /// Returns empty chain if there is no subprogram containing address. The + /// chain is valid as long as parsed compile unit DIEs are not cleared. + DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); + + /// getUnitSection - Return the DWARFUnitSection containing this unit. + const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } + +private: + /// Size in bytes of the .debug_info data associated with this compile unit. + size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } + + /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it + /// hasn't already been done. Returns the number of DIEs parsed at this call. + size_t extractDIEsIfNeeded(bool CUDieOnly); + /// extractDIEsToVector - Appends all parsed DIEs to a vector. + void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, + std::vector &DIEs) const; + /// setDIERelations - We read in all of the DIE entries into our flat list + /// of DIE entries and now we need to go back through all of them and set the + /// parent, sibling and child pointers for quick DIE navigation. + void setDIERelations(); + /// clearDIEs - Clear parsed DIEs to keep memory usage low. + void clearDIEs(bool KeepCUDie); + + /// parseDWO - Parses .dwo file for current compile unit. Returns true if + /// it was actually constructed. + bool parseDWO(); + + /// getSubprogramForAddress - Returns subprogram DIE with address range + /// encompassing the provided address. The pointer is alive as long as parsed + /// compile unit DIEs are not cleared. + const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); +}; + +} + +#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index e5dab61..d79bd3c 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -18,9 +18,11 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" #include "llvm/IR/ValueMap.h" #include "llvm/MC/MCCodeGenInfo.h" +#include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Mutex.h" #include "llvm/Target/TargetMachine.h" @@ -39,9 +41,7 @@ class Function; class GlobalVariable; class GlobalValue; class JITEventListener; -class JITMemoryManager; class MachineCodeInfo; -class Module; class MutexGuard; class ObjectCache; class RTDyldMemoryManager; @@ -131,29 +131,20 @@ class ExecutionEngine { protected: /// The list of Modules that we are JIT'ing from. We use a SmallVector to /// optimize for the case where there is only one module. - SmallVector Modules; + SmallVector, 1> Modules; void setDataLayout(const DataLayout *Val) { DL = Val; } /// getMemoryforGV - Allocate memory for a global variable. virtual char *getMemoryForGV(const GlobalVariable *GV); - // To avoid having libexecutionengine depend on the JIT and interpreter - // libraries, the execution engine implementations set these functions to ctor - // pointers at startup time if they are linked in. - static ExecutionEngine *(*JITCtor)( - Module *M, - std::string *ErrorStr, - JITMemoryManager *JMM, - bool GVsWithCode, - TargetMachine *TM); static ExecutionEngine *(*MCJITCtor)( - Module *M, - std::string *ErrorStr, - RTDyldMemoryManager *MCJMM, - bool GVsWithCode, - TargetMachine *TM); - static ExecutionEngine *(*InterpCtor)(Module *M, std::string *ErrorStr); + std::unique_ptr M, + std::string *ErrorStr, + std::unique_ptr MCJMM, + std::unique_ptr TM); + static ExecutionEngine *(*InterpCtor)(std::unique_ptr M, + std::string *ErrorStr); /// LazyFunctionCreator - If an unknown function is needed, this function /// pointer is invoked to create it. If this returns null, the JIT will @@ -161,9 +152,8 @@ protected: void *(*LazyFunctionCreator)(const std::string &); public: - /// lock - This lock protects the ExecutionEngine, MCJIT, JIT, JITResolver and - /// JITEmitter classes. It must be held while changing the internal state of - /// any of those classes. + /// lock - This lock protects the ExecutionEngine and MCJIT classes. It must + /// be held while changing the internal state of any of those classes. sys::Mutex lock; //===--------------------------------------------------------------------===// @@ -172,44 +162,9 @@ public: virtual ~ExecutionEngine(); - /// create - This is the factory method for creating an execution engine which - /// is appropriate for the current machine. This takes ownership of the - /// module. - /// - /// \param GVsWithCode - Allocating globals with code breaks - /// freeMachineCodeForFunction and is probably unsafe and bad for performance. - /// However, we have clients who depend on this behavior, so we must support - /// it. Eventually, when we're willing to break some backwards compatibility, - /// this flag should be flipped to false, so that by default - /// freeMachineCodeForFunction works. - static ExecutionEngine *create(Module *M, - bool ForceInterpreter = false, - std::string *ErrorStr = nullptr, - CodeGenOpt::Level OptLevel = - CodeGenOpt::Default, - bool GVsWithCode = true); - - /// createJIT - This is the factory method for creating a JIT for the current - /// machine, it does not fall back to the interpreter. This takes ownership - /// of the Module and JITMemoryManager if successful. - /// - /// Clients should make sure to initialize targets prior to calling this - /// function. - static ExecutionEngine *createJIT(Module *M, - std::string *ErrorStr = nullptr, - JITMemoryManager *JMM = nullptr, - CodeGenOpt::Level OptLevel = - CodeGenOpt::Default, - bool GVsWithCode = true, - Reloc::Model RM = Reloc::Default, - CodeModel::Model CMM = - CodeModel::JITDefault); - - /// addModule - Add a Module to the list of modules that we can JIT from. - /// Note that this takes ownership of the Module: when the ExecutionEngine is - /// destroyed, it destroys the Module as well. - virtual void addModule(Module *M) { - Modules.push_back(M); + /// Add a Module to the list of modules that we can JIT from. + virtual void addModule(std::unique_ptr M) { + Modules.push_back(std::move(M)); } /// addObjectFile - Add an ObjectFile to the execution engine. @@ -223,6 +178,7 @@ public: /// /// MCJIT will take ownership of the ObjectFile. virtual void addObjectFile(std::unique_ptr O); + virtual void addObjectFile(object::OwningBinary O); /// addArchive - Add an Archive to the execution engine. /// @@ -230,11 +186,7 @@ public: /// resolve external symbols in objects it is loading. If a symbol is found /// in the Archive the contained object file will be extracted (in memory) /// and loaded for possible execution. - /// - /// MCJIT will take ownership of the Archive. - virtual void addArchive(object::Archive *A) { - llvm_unreachable("ExecutionEngine subclass doesn't implement addArchive."); - } + virtual void addArchive(object::OwningBinary A); //===--------------------------------------------------------------------===// @@ -263,11 +215,7 @@ public: /// it prints a message to stderr and aborts. /// /// This function is deprecated for the MCJIT execution engine. - /// - /// FIXME: the JIT and MCJIT interfaces should be disentangled or united - /// again, if possible. - /// - virtual void *getPointerToNamedFunction(const std::string &Name, + virtual void *getPointerToNamedFunction(StringRef Name, bool AbortOnFailure = true) = 0; /// mapSectionAddress - map a section to its target address space value. @@ -279,7 +227,7 @@ public: "EE!"); } - /// generateCodeForModule - Run code generationen for the specified module and + /// generateCodeForModule - Run code generation for the specified module and /// load it into memory. /// /// When this function has completed, all code and data for the specified @@ -293,7 +241,7 @@ public: /// locally can use the getFunctionAddress call, which will generate code /// and apply final preparations all in one step. /// - /// This method has no effect for the legacy JIT engine or the interpeter. + /// This method has no effect for the interpeter. virtual void generateCodeForModule(Module *M) {} /// finalizeObject - ensure the module is fully processed and is usable. @@ -302,8 +250,7 @@ public: /// object usable for execution. It should be called after sections within an /// object have been relocated using mapSectionAddress. When this method is /// called the MCJIT execution engine will reapply relocations for a loaded - /// object. This method has no effect for the legacy JIT engine or the - /// interpeter. + /// object. This method has no effect for the interpeter. virtual void finalizeObject() {} /// runStaticConstructorsDestructors - This method is used to execute all of @@ -312,11 +259,11 @@ public: /// \param isDtors - Run the destructors instead of constructors. virtual void runStaticConstructorsDestructors(bool isDtors); - /// runStaticConstructorsDestructors - This method is used to execute all of - /// the static constructors or destructors for a particular module. + /// This method is used to execute all of the static constructors or + /// destructors for a particular module. /// /// \param isDtors - Run the destructors instead of constructors. - void runStaticConstructorsDestructors(Module *module, bool isDtors); + void runStaticConstructorsDestructors(Module &module, bool isDtors); /// runFunctionAsMain - This is a helper function which wraps runFunction to @@ -373,13 +320,6 @@ public: /// getFunctionAddress instead. virtual void *getPointerToFunction(Function *F) = 0; - /// getPointerToBasicBlock - The different EE's represent basic blocks in - /// different ways. Return the representation for a blockaddress of the - /// specified block. - /// - /// This function will not be implemented for the MCJIT execution engine. - virtual void *getPointerToBasicBlock(BasicBlock *BB) = 0; - /// getPointerToFunctionOrStub - If the specified function has been /// code-gen'd, return a pointer to the function. If not, compile it, or use /// a stub to implement lazy compilation if available. See @@ -395,9 +335,9 @@ public: /// getGlobalValueAddress - Return the address of the specified global /// value. This may involve code generation. /// - /// This function should not be called with the JIT or interpreter engines. + /// This function should not be called with the interpreter engine. virtual uint64_t getGlobalValueAddress(const std::string &Name) { - // Default implementation for JIT and interpreter. MCJIT will override this. + // Default implementation for the interpreter. MCJIT will override this. // JIT and interpreter clients should use getPointerToGlobal instead. return 0; } @@ -405,14 +345,11 @@ public: /// getFunctionAddress - Return the address of the specified function. /// This may involve code generation. virtual uint64_t getFunctionAddress(const std::string &Name) { - // Default implementation for JIT and interpreter. MCJIT will override this. - // JIT and interpreter clients should use getPointerToFunction instead. + // Default implementation for the interpreter. MCJIT will override this. + // Interpreter clients should use getPointerToFunction instead. return 0; } - // The JIT overrides a version that actually does this. - virtual void runJITOnFunction(Function *, MachineCodeInfo * = nullptr) { } - /// getGlobalValueAtAddress - Return the LLVM global value object that starts /// at the specified address. /// @@ -427,18 +364,6 @@ public: void InitializeMemory(const Constant *Init, void *Addr); - /// recompileAndRelinkFunction - This method is used to force a function which - /// has already been compiled to be compiled again, possibly after it has been - /// modified. Then the entry to the old copy is overwritten with a branch to - /// the new copy. If there was no old copy, this acts just like - /// VM::getPointerToFunction(). - virtual void *recompileAndRelinkFunction(Function *F) = 0; - - /// freeMachineCodeForFunction - Release memory in the ExecutionEngine - /// corresponding to the machine code emitted to execute this function, useful - /// for garbage-collecting generated code. - virtual void freeMachineCodeForFunction(Function *F) = 0; - /// getOrEmitGlobalVariable - Return the address of the specified global /// variable, possibly emitting it to memory if needed. This is used by the /// Emitter. @@ -457,7 +382,7 @@ public: virtual void UnregisterJITEventListener(JITEventListener *) {} /// Sets the pre-compiled object cache. The ownership of the ObjectCache is - /// not changed. Supported by MCJIT but not JIT. + /// not changed. Supported by MCJIT but not the interpreter. virtual void setObjectCache(ObjectCache *) { llvm_unreachable("No support for an object cache"); } @@ -499,11 +424,6 @@ public: bool isCompilingLazily() const { return CompilingLazily; } - // Deprecated in favor of isCompilingLazily (to reduce double-negatives). - // Remove this in LLVM 2.8. - bool isLazyCompilationDisabled() const { - return !CompilingLazily; - } /// DisableGVCompilation - If called, the JIT will abort if it's asked to /// allocate space and populate a GlobalVariable that is not internal to @@ -544,7 +464,7 @@ public: } protected: - explicit ExecutionEngine(Module *M); + explicit ExecutionEngine(std::unique_ptr M); void emitGlobals(); @@ -564,36 +484,33 @@ namespace EngineKind { const static Kind Either = (Kind)(JIT | Interpreter); } -/// EngineBuilder - Builder class for ExecutionEngines. Use this by -/// stack-allocating a builder, chaining the various set* methods, and -/// terminating it with a .create() call. +/// Builder class for ExecutionEngines. Use this by stack-allocating a builder, +/// chaining the various set* methods, and terminating it with a .create() +/// call. class EngineBuilder { private: - Module *M; + std::unique_ptr M; EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; - RTDyldMemoryManager *MCJMM; - JITMemoryManager *JMM; - bool AllocateGVsWithCode; + std::unique_ptr MCJMM; TargetOptions Options; Reloc::Model RelocModel; CodeModel::Model CMModel; std::string MArch; std::string MCPU; SmallVector MAttrs; - bool UseMCJIT; bool VerifyModules; /// InitEngine - Does the common initialization of default options. void InitEngine(); public: - /// EngineBuilder - Constructor for EngineBuilder. If create() is called and - /// is successful, the created engine takes ownership of the module. - EngineBuilder(Module *m) : M(m) { - InitEngine(); - } + /// Constructor for EngineBuilder. + EngineBuilder(std::unique_ptr M); + + // Out-of-line since we don't have the def'n of RTDyldMemoryManager here. + ~EngineBuilder(); /// setEngineKind - Controls whether the user wants the interpreter, the JIT, /// or whichever engine works. This option defaults to EngineKind::Either. @@ -607,26 +524,8 @@ public: /// is only appropriate for the MCJIT; setting this and configuring the builder /// to create anything other than MCJIT will cause a runtime error. If create() /// is called and is successful, the created engine takes ownership of the - /// memory manager. This option defaults to NULL. Using this option nullifies - /// the setJITMemoryManager() option. - EngineBuilder &setMCJITMemoryManager(RTDyldMemoryManager *mcjmm) { - MCJMM = mcjmm; - JMM = nullptr; - return *this; - } - - /// setJITMemoryManager - Sets the JIT memory manager to use. This allows - /// clients to customize their memory allocation policies. This is only - /// appropriate for either JIT or MCJIT; setting this and configuring the - /// builder to create an interpreter will cause a runtime error. If create() - /// is called and is successful, the created engine takes ownership of the - /// memory manager. This option defaults to NULL. This option overrides - /// setMCJITMemoryManager() as well. - EngineBuilder &setJITMemoryManager(JITMemoryManager *jmm) { - MCJMM = nullptr; - JMM = jmm; - return *this; - } + /// memory manager. This option defaults to NULL. + EngineBuilder &setMCJITMemoryManager(std::unique_ptr mcjmm); /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. @@ -664,18 +563,6 @@ public: return *this; } - /// setAllocateGVsWithCode - Sets whether global values should be allocated - /// into the same buffer as code. For most applications this should be set - /// to false. Allocating globals with code breaks freeMachineCodeForFunction - /// and is probably unsafe and bad for performance. However, we have clients - /// who depend on this behavior, so we must support it. This option defaults - /// to false so that users of the new API can safely use the new memory - /// manager and free machine code. - EngineBuilder &setAllocateGVsWithCode(bool a) { - AllocateGVsWithCode = a; - return *this; - } - /// setMArch - Override the architecture set by the Module's triple. EngineBuilder &setMArch(StringRef march) { MArch.assign(march.begin(), march.end()); @@ -688,13 +575,6 @@ public: return *this; } - /// setUseMCJIT - Set whether the MC-JIT implementation should be used - /// (experimental). - EngineBuilder &setUseMCJIT(bool Value) { - UseMCJIT = Value; - return *this; - } - /// setVerifyModules - Set whether the JIT implementation should verify /// IR modules during compilation. EngineBuilder &setVerifyModules(bool Verify) { diff --git a/include/llvm/ExecutionEngine/JIT.h b/include/llvm/ExecutionEngine/JIT.h deleted file mode 100644 index 581d6e6..0000000 --- a/include/llvm/ExecutionEngine/JIT.h +++ /dev/null @@ -1,38 +0,0 @@ -//===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file forces the JIT to link in on certain operating systems. -// (Windows). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_JIT_H -#define LLVM_EXECUTIONENGINE_JIT_H - -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include - -extern "C" void LLVMLinkInJIT(); - -namespace { - struct ForceJITLinking { - ForceJITLinking() { - // We must reference JIT in such a way that compilers will not - // delete it all as dead code, even with whole program optimization, - // yet is effectively a NO-OP. As the compiler isn't smart enough - // to know that getenv() never returns -1, this will do the job. - if (std::getenv("bar") != (char*) -1) - return; - - LLVMLinkInJIT(); - } - } ForceJITLinking; -} - -#endif diff --git a/include/llvm/ExecutionEngine/JITEventListener.h b/include/llvm/ExecutionEngine/JITEventListener.h index 99fe36c..c3edec8 100644 --- a/include/llvm/ExecutionEngine/JITEventListener.h +++ b/include/llvm/ExecutionEngine/JITEventListener.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H #define LLVM_EXECUTIONENGINE_JITEVENTLISTENER_H +#include "RuntimeDyld.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/DebugLoc.h" #include "llvm/Support/DataTypes.h" @@ -25,7 +26,10 @@ class Function; class MachineFunction; class OProfileWrapper; class IntelJITEventsWrapper; -class ObjectImage; + +namespace object { + class ObjectFile; +} /// JITEvent_EmittedFunctionDetails - Helper struct for containing information /// about a generated machine code function. @@ -57,24 +61,7 @@ public: public: JITEventListener() {} - virtual ~JITEventListener(); - - /// NotifyFunctionEmitted - Called after a function has been successfully - /// emitted to memory. The function still has its MachineFunction attached, - /// if you should happen to need that. - virtual void NotifyFunctionEmitted(const Function &, - void *, size_t, - const EmittedFunctionDetails &) {} - - /// NotifyFreeingMachineCode - Called from freeMachineCodeForFunction(), after - /// the global mapping is removed, but before the machine code is returned to - /// the allocator. - /// - /// OldPtr is the address of the machine code and will be the same as the Code - /// parameter to a previous NotifyFunctionEmitted call. The Function passed - /// to NotifyFunctionEmitted may have been destroyed by the time of the - /// matching NotifyFreeingMachineCode call. - virtual void NotifyFreeingMachineCode(void *) {} + virtual ~JITEventListener() {} /// NotifyObjectEmitted - Called after an object has been successfully /// emitted to memory. NotifyFunctionEmitted will not be called for @@ -84,11 +71,15 @@ public: /// The ObjectImage contains the generated object image /// with section headers updated to reflect the address at which sections /// were loaded and with relocations performed in-place on debug sections. - virtual void NotifyObjectEmitted(const ObjectImage &Obj) {} + virtual void NotifyObjectEmitted(const object::ObjectFile &Obj, + const RuntimeDyld::LoadedObjectInfo &L) {} /// NotifyFreeingObject - Called just before the memory associated with /// a previously emitted object is released. - virtual void NotifyFreeingObject(const ObjectImage &Obj) {} + virtual void NotifyFreeingObject(const object::ObjectFile &Obj) {} + + // Get a pointe to the GDB debugger registration listener. + static JITEventListener *createGDBRegistrationListener(); #if LLVM_USE_INTEL_JITEVENTS // Construct an IntelJITEventListener @@ -122,7 +113,8 @@ public: return nullptr; } #endif // USE_OPROFILE - +private: + virtual void anchor(); }; } // end namespace llvm. diff --git a/include/llvm/ExecutionEngine/JITMemoryManager.h b/include/llvm/ExecutionEngine/JITMemoryManager.h deleted file mode 100644 index b22d899..0000000 --- a/include/llvm/ExecutionEngine/JITMemoryManager.h +++ /dev/null @@ -1,164 +0,0 @@ -//===-- JITMemoryManager.h - Interface JIT uses to Allocate Mem -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H -#define LLVM_EXECUTIONENGINE_JITMEMORYMANAGER_H - -#include "llvm/ExecutionEngine/RuntimeDyld.h" -#include "llvm/Support/DataTypes.h" -#include - -namespace llvm { - - class Function; - class GlobalValue; - -/// JITMemoryManager - This interface is used by the JIT to allocate and manage -/// memory for the code generated by the JIT. This can be reimplemented by -/// clients that have a strong desire to control how the layout of JIT'd memory -/// works. -class JITMemoryManager : public RTDyldMemoryManager { -protected: - bool HasGOT; - -public: - JITMemoryManager() : HasGOT(false) {} - virtual ~JITMemoryManager(); - - /// CreateDefaultMemManager - This is used to create the default - /// JIT Memory Manager if the client does not provide one to the JIT. - static JITMemoryManager *CreateDefaultMemManager(); - - /// setMemoryWritable - When code generation is in progress, - /// the code pages may need permissions changed. - virtual void setMemoryWritable() = 0; - - /// setMemoryExecutable - When code generation is done and we're ready to - /// start execution, the code pages may need permissions changed. - virtual void setMemoryExecutable() = 0; - - /// setPoisonMemory - Setting this flag to true makes the memory manager - /// garbage values over freed memory. This is useful for testing and - /// debugging, and may be turned on by default in debug mode. - virtual void setPoisonMemory(bool poison) = 0; - - //===--------------------------------------------------------------------===// - // Global Offset Table Management - //===--------------------------------------------------------------------===// - - /// AllocateGOT - If the current table requires a Global Offset Table, this - /// method is invoked to allocate it. This method is required to set HasGOT - /// to true. - virtual void AllocateGOT() = 0; - - /// isManagingGOT - Return true if the AllocateGOT method is called. - bool isManagingGOT() const { - return HasGOT; - } - - /// getGOTBase - If this is managing a Global Offset Table, this method should - /// return a pointer to its base. - virtual uint8_t *getGOTBase() const = 0; - - //===--------------------------------------------------------------------===// - // Main Allocation Functions - //===--------------------------------------------------------------------===// - - /// startFunctionBody - When we start JITing a function, the JIT calls this - /// method to allocate a block of free RWX memory, which returns a pointer to - /// it. If the JIT wants to request a block of memory of at least a certain - /// size, it passes that value as ActualSize, and this method returns a block - /// with at least that much space. If the JIT doesn't know ahead of time how - /// much space it will need to emit the function, it passes 0 for the - /// ActualSize. In either case, this method is required to pass back the size - /// of the allocated block through ActualSize. The JIT will be careful to - /// not write more than the returned ActualSize bytes of memory. - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize) = 0; - - /// allocateStub - This method is called by the JIT to allocate space for a - /// function stub (used to handle limited branch displacements) while it is - /// JIT compiling a function. For example, if foo calls bar, and if bar - /// either needs to be lazily compiled or is a native function that exists too - /// far away from the call site to work, this method will be used to make a - /// thunk for it. The stub should be "close" to the current function body, - /// but should not be included in the 'actualsize' returned by - /// startFunctionBody. - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) = 0; - - /// endFunctionBody - This method is called when the JIT is done codegen'ing - /// the specified function. At this point we know the size of the JIT - /// compiled function. This passes in FunctionStart (which was returned by - /// the startFunctionBody method) and FunctionEnd which is a pointer to the - /// actual end of the function. This method should mark the space allocated - /// and remember where it is in case the client wants to deallocate it. - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) = 0; - - /// allocateSpace - Allocate a memory block of the given size. This method - /// cannot be called between calls to startFunctionBody and endFunctionBody. - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0; - - /// allocateGlobal - Allocate memory for a global. - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) = 0; - - /// deallocateFunctionBody - Free the specified function body. The argument - /// must be the return value from a call to startFunctionBody() that hasn't - /// been deallocated yet. This is never called when the JIT is currently - /// emitting a function. - virtual void deallocateFunctionBody(void *Body) = 0; - - /// CheckInvariants - For testing only. Return true if all internal - /// invariants are preserved, or return false and set ErrorStr to a helpful - /// error message. - virtual bool CheckInvariants(std::string &) { - return true; - } - - /// GetDefaultCodeSlabSize - For testing only. Returns DefaultCodeSlabSize - /// from DefaultJITMemoryManager. - virtual size_t GetDefaultCodeSlabSize() { - return 0; - } - - /// GetDefaultDataSlabSize - For testing only. Returns DefaultCodeSlabSize - /// from DefaultJITMemoryManager. - virtual size_t GetDefaultDataSlabSize() { - return 0; - } - - /// GetDefaultStubSlabSize - For testing only. Returns DefaultCodeSlabSize - /// from DefaultJITMemoryManager. - virtual size_t GetDefaultStubSlabSize() { - return 0; - } - - /// GetNumCodeSlabs - For testing only. Returns the number of MemoryBlocks - /// allocated for code. - virtual unsigned GetNumCodeSlabs() { - return 0; - } - - /// GetNumDataSlabs - For testing only. Returns the number of MemoryBlocks - /// allocated for data. - virtual unsigned GetNumDataSlabs() { - return 0; - } - - /// GetNumStubSlabs - For testing only. Returns the number of MemoryBlocks - /// allocated for function stubs. - virtual unsigned GetNumStubSlabs() { - return 0; - } -}; - -} // end namespace llvm. - -#endif diff --git a/include/llvm/ExecutionEngine/ObjectBuffer.h b/include/llvm/ExecutionEngine/ObjectBuffer.h deleted file mode 100644 index 6221d3b..0000000 --- a/include/llvm/ExecutionEngine/ObjectBuffer.h +++ /dev/null @@ -1,83 +0,0 @@ -//===---- ObjectBuffer.h - Utility class to wrap object image memory -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a wrapper class to hold the memory into which an -// object will be generated. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTBUFFER_H -#define LLVM_EXECUTIONENGINE_OBJECTBUFFER_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -/// ObjectBuffer - This class acts as a container for the memory buffer used during -/// generation and loading of executable objects using MCJIT and RuntimeDyld. The -/// underlying memory for the object will be owned by the ObjectBuffer instance -/// throughout its lifetime. The getMemBuffer() method provides a way to create a -/// MemoryBuffer wrapper object instance to be owned by other classes (such as -/// ObjectFile) as needed, but the MemoryBuffer instance returned does not own the -/// actual memory it points to. -class ObjectBuffer { - virtual void anchor(); -public: - ObjectBuffer() {} - ObjectBuffer(MemoryBuffer* Buf) : Buffer(Buf) {} - virtual ~ObjectBuffer() {} - - /// getMemBuffer - Like MemoryBuffer::getMemBuffer() this function - /// returns a pointer to an object that is owned by the caller. However, - /// the caller does not take ownership of the underlying memory. - MemoryBuffer *getMemBuffer() const { - return MemoryBuffer::getMemBuffer(Buffer->getBuffer(), - Buffer->getBufferIdentifier(), false); - } - - const char *getBufferStart() const { return Buffer->getBufferStart(); } - size_t getBufferSize() const { return Buffer->getBufferSize(); } - StringRef getBuffer() const { return Buffer->getBuffer(); } - -protected: - // The memory contained in an ObjectBuffer - std::unique_ptr Buffer; -}; - -/// ObjectBufferStream - This class encapsulates the SmallVector and -/// raw_svector_ostream needed to generate an object using MC code emission -/// while providing a common ObjectBuffer interface for access to the -/// memory once the object has been generated. -class ObjectBufferStream : public ObjectBuffer { - void anchor() override; -public: - ObjectBufferStream() : OS(SV) {} - virtual ~ObjectBufferStream() {} - - raw_ostream &getOStream() { return OS; } - void flush() - { - OS.flush(); - - // Make the data accessible via the ObjectBuffer::Buffer - Buffer.reset(MemoryBuffer::getMemBuffer(StringRef(SV.data(), SV.size()), - "", - false)); - } - -protected: - SmallVector SV; // Working buffer into which we JIT. - raw_svector_ostream OS; // streaming wrapper -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h index d1849df..cc01a4e 100644 --- a/include/llvm/ExecutionEngine/ObjectCache.h +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -27,13 +27,12 @@ public: virtual ~ObjectCache() { } /// notifyObjectCompiled - Provides a pointer to compiled code for Module M. - virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) = 0; + virtual void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) = 0; - /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that - /// contains the object which corresponds with Module M, or 0 if an object is - /// not available. The caller owns both the MemoryBuffer returned by this - /// and the memory it references. - virtual MemoryBuffer* getObject(const Module* M) = 0; + /// Returns a pointer to a newly allocated MemoryBuffer that contains the + /// object which corresponds with Module M, or 0 if an object is not + /// available. + virtual std::unique_ptr getObject(const Module* M) = 0; }; } diff --git a/include/llvm/ExecutionEngine/ObjectImage.h b/include/llvm/ExecutionEngine/ObjectImage.h deleted file mode 100644 index 1fcedd8..0000000 --- a/include/llvm/ExecutionEngine/ObjectImage.h +++ /dev/null @@ -1,71 +0,0 @@ -//===---- ObjectImage.h - Format independent executuable object image -----===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares a file format independent ObjectImage class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_OBJECTIMAGE_H -#define LLVM_EXECUTIONENGINE_OBJECTIMAGE_H - -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/Object/ObjectFile.h" - -namespace llvm { - - -/// ObjectImage - A container class that represents an ObjectFile that has been -/// or is in the process of being loaded into memory for execution. -class ObjectImage { - ObjectImage() LLVM_DELETED_FUNCTION; - ObjectImage(const ObjectImage &other) LLVM_DELETED_FUNCTION; - virtual void anchor(); - -protected: - std::unique_ptr Buffer; - -public: - ObjectImage(ObjectBuffer *Input) : Buffer(Input) {} - virtual ~ObjectImage() {} - - virtual object::symbol_iterator begin_symbols() const = 0; - virtual object::symbol_iterator end_symbols() const = 0; - iterator_range symbols() const { - return iterator_range(begin_symbols(), - end_symbols()); - } - - virtual object::section_iterator begin_sections() const = 0; - virtual object::section_iterator end_sections() const = 0; - iterator_range sections() const { - return iterator_range(begin_sections(), - end_sections()); - } - - virtual /* Triple::ArchType */ unsigned getArch() const = 0; - - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - virtual void updateSectionAddress(const object::SectionRef &Sec, - uint64_t Addr) = 0; - virtual void updateSymbolAddress(const object::SymbolRef &Sym, - uint64_t Addr) = 0; - - virtual StringRef getData() const = 0; - - virtual object::ObjectFile* getObjectFile() const = 0; - - // Subclasses can override these methods to provide JIT debugging support - virtual void registerWithDebugger() = 0; - virtual void deregisterWithDebugger() = 0; -}; - -} // end namespace llvm - -#endif // LLVM_EXECUTIONENGINE_OBJECTIMAGE_H diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index b1d6810..ef81cd3 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H -#define LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H +#ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H +#define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/StringRef.h" @@ -22,7 +22,10 @@ namespace llvm { class ExecutionEngine; -class ObjectImage; + + namespace object { + class ObjectFile; + } // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of @@ -76,9 +79,15 @@ public: virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + /// This method returns the address of the specified function or variable in + /// the current process. + static uint64_t getSymbolAddressInProcess(const std::string &Name); + /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. - virtual uint64_t getSymbolAddress(const std::string &Name); + virtual uint64_t getSymbolAddress(const std::string &Name) { + return getSymbolAddressInProcess(Name); + } /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. @@ -103,7 +112,7 @@ public: /// address space can use this call to remap the section addresses for the /// newly loaded object. virtual void notifyObjectLoaded(ExecutionEngine *EE, - const ObjectImage *) {} + const object::ObjectFile &) {} /// This method is called when object loading is complete and section page /// permissions can be applied. It is up to the memory manager implementation @@ -123,4 +132,4 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS( } // namespace llvm -#endif // LLVM_EXECUTIONENGINE_RT_DYLD_MEMORY_MANAGER_H +#endif diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index f123ffb..799fc34 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -15,58 +15,75 @@ #define LLVM_EXECUTIONENGINE_RUNTIMEDYLD_H #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" +#include namespace llvm { namespace object { class ObjectFile; + template class OwningBinary; } class RuntimeDyldImpl; -class ObjectImage; +class RuntimeDyldCheckerImpl; class RuntimeDyld { - friend class RuntimeDyldChecker; + friend class RuntimeDyldCheckerImpl; RuntimeDyld(const RuntimeDyld &) LLVM_DELETED_FUNCTION; void operator=(const RuntimeDyld &) LLVM_DELETED_FUNCTION; // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public // interface. - RuntimeDyldImpl *Dyld; + std::unique_ptr Dyld; RTDyldMemoryManager *MM; bool ProcessAllSections; + RuntimeDyldCheckerImpl *Checker; protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. void reassignSectionAddress(unsigned SectionID, uint64_t Addr); public: + + /// \brief Information about the loaded object. + class LoadedObjectInfo { + friend class RuntimeDyldImpl; + public: + LoadedObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RTDyld(RTDyld), BeginIdx(BeginIdx), EndIdx(EndIdx) { } + + virtual ~LoadedObjectInfo() {} + + virtual object::OwningBinary + getObjectForDebug(const object::ObjectFile &Obj) const = 0; + + uint64_t getSectionLoadAddress(StringRef Name) const; + + protected: + virtual void anchor(); + + RuntimeDyldImpl &RTDyld; + unsigned BeginIdx, EndIdx; + }; + RuntimeDyld(RTDyldMemoryManager *); ~RuntimeDyld(); - /// Prepare the object contained in the input buffer for execution. - /// Ownership of the input buffer is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input buffer will be deleted. - ObjectImage *loadObject(ObjectBuffer *InputBuffer); - - /// Prepare the referenced object file for execution. - /// Ownership of the input object is transferred to the ObjectImage - /// instance returned from this function if successful. In the case of load - /// failure, the input object will be deleted. - ObjectImage *loadObject(std::unique_ptr InputObject); + /// Add the referenced object file to the list of objects to be loaded and + /// relocated. + std::unique_ptr loadObject(const object::ObjectFile &O); /// Get the address of our local copy of the symbol. This may or may not /// be the address used for relocation (clients can copy the data around /// and resolve relocatons based on where they put it). - void *getSymbolAddress(StringRef Name); + void *getSymbolAddress(StringRef Name) const; /// Get the address of the target copy of the symbol. This is the address /// used for relocation. - uint64_t getSymbolLoadAddress(StringRef Name); + uint64_t getSymbolLoadAddress(StringRef Name) const; /// Resolve the relocations for all symbols we currently know about. void resolveRelocations(); diff --git a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h index 8dd891e..35ceba2 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyldChecker.h +++ b/include/llvm/ExecutionEngine/RuntimeDyldChecker.h @@ -7,18 +7,19 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIMEDYLDCHECKER_H -#define LLVM_RUNTIMEDYLDCHECKER_H +#ifndef LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H +#define LLVM_EXECUTIONENGINE_RUNTIMEDYLDCHECKER_H -#include "RuntimeDyld.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" -#include +#include "llvm/ADT/StringRef.h" namespace llvm { class MCDisassembler; +class MemoryBuffer; class MCInstPrinter; +class RuntimeDyld; +class RuntimeDyldCheckerImpl; +class raw_ostream; /// \brief RuntimeDyld invariant checker for verifying that RuntimeDyld has /// correctly applied relocations. @@ -61,14 +62,16 @@ class MCInstPrinter; /// | expr '>>' expr /// class RuntimeDyldChecker { - friend class RuntimeDyldCheckerExprEval; public: - RuntimeDyldChecker(RuntimeDyld &RTDyld, - MCDisassembler *Disassembler, - MCInstPrinter *InstPrinter, - llvm::raw_ostream &ErrStream) - : RTDyld(*RTDyld.Dyld), Disassembler(Disassembler), - InstPrinter(InstPrinter), ErrStream(ErrStream) {} + RuntimeDyldChecker(RuntimeDyld &RTDyld, MCDisassembler *Disassembler, + MCInstPrinter *InstPrinter, raw_ostream &ErrStream); + ~RuntimeDyldChecker(); + + // \brief Get the associated RTDyld instance. + RuntimeDyld& getRTDyld(); + + // \brief Get the associated RTDyld instance. + const RuntimeDyld& getRTDyld() const; /// \brief Check a single expression against the attached RuntimeDyld /// instance. @@ -79,20 +82,20 @@ public: /// method to be evaluated as an expression. bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const; -private: + /// \brief Returns the address of the requested section (or an error message + /// in the second element of the pair if the address cannot be found). + /// + /// if 'LinkerAddress' is true, this returns the address of the section + /// within the linker's memory. If 'LinkerAddress' is false it returns the + /// address within the target process (i.e. the load address). + std::pair getSectionAddr(StringRef FileName, + StringRef SectionName, + bool LinkerAddress); - bool isSymbolValid(StringRef Symbol) const; - uint64_t getSymbolAddress(StringRef Symbol) const; - uint64_t readMemoryAtSymbol(StringRef Symbol, int64_t Offset, - unsigned Size) const; - StringRef getSubsectionStartingAt(StringRef Name) const; - - RuntimeDyldImpl &RTDyld; - MCDisassembler *Disassembler; - MCInstPrinter *InstPrinter; - llvm::raw_ostream &ErrStream; +private: + std::unique_ptr Impl; }; } // end namespace llvm -#endif // LLVM_RUNTIMEDYLDCHECKER_H +#endif diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index 7c398a5..dd76a90 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -105,6 +105,14 @@ public: /// its containing function. bool hasInAllocaAttr() const; + /// \brief Return true if this argument has the zext attribute on it in its + /// containing function. + bool hasZExtAttr() const; + + /// \brief Return true if this argument has the sext attribute on it in its + /// containing function. + bool hasSExtAttr() const; + /// \brief Add a Attribute to an argument. void addAttr(AttributeSet AS); diff --git a/include/llvm/IR/AssemblyAnnotationWriter.h b/include/llvm/IR/AssemblyAnnotationWriter.h index a8d52f6..19e32a2 100644 --- a/include/llvm/IR/AssemblyAnnotationWriter.h +++ b/include/llvm/IR/AssemblyAnnotationWriter.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_ASMANNOTATIONWRITER_H -#define LLVM_IR_ASMANNOTATIONWRITER_H +#ifndef LLVM_IR_ASSEMBLYANNOTATIONWRITER_H +#define LLVM_IR_ASSEMBLYANNOTATIONWRITER_H namespace llvm { diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index a19489a..7c7dd2c 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -23,6 +23,7 @@ namespace llvm { +class CallInst; class LandingPadInst; class TerminatorInst; class LLVMContext; @@ -125,6 +126,14 @@ public: TerminatorInst *getTerminator(); const TerminatorInst *getTerminator() const; + /// \brief Returns the call instruction marked 'musttail' prior to the + /// terminating return instruction of this basic block, if such a call is + /// present. Otherwise, returns null. + CallInst *getTerminatingMustTailCall(); + const CallInst *getTerminatingMustTailCall() const { + return const_cast(this)->getTerminatingMustTailCall(); + } + /// \brief Returns a pointer to the first instruction in this block that is /// not a PHINode instruction. /// @@ -173,6 +182,13 @@ public: /// right after \p MovePos in the function \p MovePos lives in. void moveAfter(BasicBlock *MovePos); + /// \brief Insert unlinked basic block into a function. + /// + /// Inserts an unlinked basic block into \c Parent. If \c InsertBefore is + /// provided, inserts before that basic block, otherwise inserts at the end. + /// + /// \pre \a getParent() is \c nullptr. + void insertInto(Function *Parent, BasicBlock *InsertBefore = nullptr); /// \brief Return the predecessor of this block if it has a single predecessor /// block. Otherwise return a null pointer. diff --git a/include/llvm/IR/CFG.h b/include/llvm/IR/CFG.h index c8be8bd..5400d23 100644 --- a/include/llvm/IR/CFG.h +++ b/include/llvm/IR/CFG.h @@ -93,6 +93,9 @@ inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} inline const_pred_iterator pred_end(const BasicBlock *BB) { return const_pred_iterator(BB, true); } +inline bool pred_empty(const BasicBlock *BB) { + return pred_begin(BB) == pred_end(BB); +} @@ -257,6 +260,9 @@ inline succ_iterator succ_end(BasicBlock *BB) { inline succ_const_iterator succ_end(const BasicBlock *BB) { return succ_const_iterator(BB->getTerminator(), true); } +inline bool succ_empty(const BasicBlock *BB) { + return succ_begin(BB) == succ_end(BB); +} template struct isPodLike > { static const bool value = isPodLike::value; diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 1eaf4f7..9872e6e 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -20,10 +20,13 @@ namespace llvm { /// the well-known calling conventions. /// namespace CallingConv { + /// LLVM IR allows to use arbitrary numbers as calling convention identifiers. + typedef unsigned ID; + /// A set of enums which specify the assigned numeric values for known llvm /// calling conventions. /// @brief LLVM Calling Convention Representation - enum ID { + enum { /// C - The default llvm calling convention, compatible with C. This /// convention is the only calling convention that supports varargs calls. /// As with typical C calling conventions, the callee/caller have to @@ -137,7 +140,11 @@ namespace CallingConv { /// convention differs from the more common \c X86_64_SysV convention /// in a number of ways, most notably in that XMM registers used to pass /// arguments are shadowed by GPRs, and vice versa. - X86_64_Win64 = 79 + X86_64_Win64 = 79, + + /// \brief MSVC calling convention that passes vectors and vector aggregates + /// in SSE registers. + X86_VectorCall = 80 }; } // End CallingConv namespace diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 82ad9fc..d26991e 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -48,11 +48,16 @@ protected: : User(ty, vty, Ops, NumOps) {} void destroyConstantImpl(); + void replaceUsesOfWithOnConstantImpl(Constant *Replacement); + public: /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. bool isNullValue() const; + /// \brief Returns true if the value is one. + bool isOneValue() const; + /// isAllOnesValue - Return true if this is the value that would be returned by /// getAllOnesValue. bool isAllOnesValue() const; @@ -64,6 +69,9 @@ public: /// Return true if the value is negative zero or null value. bool isZeroValue() const; + /// \brief Return true if the value is not the smallest signed value. + bool isNotMinSignedValue() const; + /// \brief Return true if the value is the smallest signed value. bool isMinSignedValue() const; diff --git a/include/llvm/IR/ConstantRange.h b/include/llvm/IR/ConstantRange.h index 342422c..5e8cd34 100644 --- a/include/llvm/IR/ConstantRange.h +++ b/include/llvm/IR/ConstantRange.h @@ -29,15 +29,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_CONSTANTRANGE_H -#define LLVM_SUPPORT_CONSTANTRANGE_H +#ifndef LLVM_IR_CONSTANTRANGE_H +#define LLVM_IR_CONSTANTRANGE_H #include "llvm/ADT/APInt.h" #include "llvm/Support/DataTypes.h" namespace llvm { -/// ConstantRange - This class represents an range of values. +/// This class represents a range of values. /// class ConstantRange { APInt Lower, Upper; @@ -59,7 +59,7 @@ public: /// assert out if the two APInt's are not the same bit width. ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); - /// makeICmpRegion - Produce the smallest range that contains all values that + /// Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value /// contained within Other. /// @@ -69,47 +69,46 @@ public: static ConstantRange makeICmpRegion(unsigned Pred, const ConstantRange &Other); - /// getLower - Return the lower value for this range... + /// Return the lower value for this range. /// const APInt &getLower() const { return Lower; } - /// getUpper - Return the upper value for this range... + /// Return the upper value for this range. /// const APInt &getUpper() const { return Upper; } - /// getBitWidth - get the bit width of this ConstantRange + /// Get the bit width of this ConstantRange. /// uint32_t getBitWidth() const { return Lower.getBitWidth(); } - /// isFullSet - Return true if this set contains all of the elements possible - /// for this data-type + /// Return true if this set contains all of the elements possible + /// for this data-type. /// bool isFullSet() const; - /// isEmptySet - Return true if this set contains no members. + /// Return true if this set contains no members. /// bool isEmptySet() const; - /// isWrappedSet - Return true if this set wraps around the top of the range, - /// for example: [100, 8) + /// Return true if this set wraps around the top of the range. + /// For example: [100, 8). /// bool isWrappedSet() const; - /// isSignWrappedSet - Return true if this set wraps around the INT_MIN of - /// its bitwidth, for example: i8 [120, 140). + /// Return true if this set wraps around the INT_MIN of + /// its bitwidth. For example: i8 [120, 140). /// bool isSignWrappedSet() const; - /// contains - Return true if the specified value is in the set. + /// Return true if the specified value is in the set. /// bool contains(const APInt &Val) const; - /// contains - Return true if the other range is a subset of this one. + /// Return true if the other range is a subset of this one. /// bool contains(const ConstantRange &CR) const; - /// getSingleElement - If this set contains a single element, return it, - /// otherwise return null. + /// If this set contains a single element, return it, otherwise return null. /// const APInt *getSingleElement() const { if (Upper == Lower + 1) @@ -117,35 +116,31 @@ public: return nullptr; } - /// isSingleElement - Return true if this set contains exactly one member. + /// Return true if this set contains exactly one member. /// bool isSingleElement() const { return getSingleElement() != nullptr; } - /// getSetSize - Return the number of elements in this set. + /// Return the number of elements in this set. /// APInt getSetSize() const; - /// getUnsignedMax - Return the largest unsigned value contained in the - /// ConstantRange. + /// Return the largest unsigned value contained in the ConstantRange. /// APInt getUnsignedMax() const; - /// getUnsignedMin - Return the smallest unsigned value contained in the - /// ConstantRange. + /// Return the smallest unsigned value contained in the ConstantRange. /// APInt getUnsignedMin() const; - /// getSignedMax - Return the largest signed value contained in the - /// ConstantRange. + /// Return the largest signed value contained in the ConstantRange. /// APInt getSignedMax() const; - /// getSignedMin - Return the smallest signed value contained in the - /// ConstantRange. + /// Return the smallest signed value contained in the ConstantRange. /// APInt getSignedMin() const; - /// operator== - Return true if this range is equal to another range. + /// Return true if this range is equal to another range. /// bool operator==(const ConstantRange &CR) const { return Lower == CR.Lower && Upper == CR.Upper; @@ -154,15 +149,14 @@ public: return !operator==(CR); } - /// subtract - Subtract the specified constant from the endpoints of this - /// constant range. + /// Subtract the specified constant from the endpoints of this constant range. ConstantRange subtract(const APInt &CI) const; /// \brief Subtract the specified range from this range (aka relative /// complement of the sets). ConstantRange difference(const ConstantRange &CR) const; - /// intersectWith - Return the range that results from the intersection of + /// Return the range that results from the intersection of /// this range with another range. The resultant range is guaranteed to /// include all elements contained in both input ranges, and to have the /// smallest possible set size that does so. Because there may be two @@ -171,7 +165,7 @@ public: /// ConstantRange intersectWith(const ConstantRange &CR) const; - /// unionWith - Return the range that results from the union of this range + /// Return the range that results from the union of this range /// with another range. The resultant range is guaranteed to include the /// elements of both sets, but may contain more. For example, [3, 9) union /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included @@ -179,85 +173,84 @@ public: /// ConstantRange unionWith(const ConstantRange &CR) const; - /// zeroExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// zero extended to BitWidth. ConstantRange zeroExtend(uint32_t BitWidth) const; - /// signExtend - Return a new range in the specified integer type, which must + /// Return a new range in the specified integer type, which must /// be strictly larger than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// sign extended to BitWidth. ConstantRange signExtend(uint32_t BitWidth) const; - /// truncate - Return a new range in the specified integer type, which must be + /// Return a new range in the specified integer type, which must be /// strictly smaller than the current type. The returned range will /// correspond to the possible range of values if the source range had been /// truncated to the specified type. ConstantRange truncate(uint32_t BitWidth) const; - /// zextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is zero extended, truncated, or left alone to make it that width. ConstantRange zextOrTrunc(uint32_t BitWidth) const; - /// sextOrTrunc - make this range have the bit width given by \p BitWidth. The + /// Make this range have the bit width given by \p BitWidth. The /// value is sign extended, truncated, or left alone to make it that width. ConstantRange sextOrTrunc(uint32_t BitWidth) const; - /// add - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an addition of a value in this range and a value in \p Other. ConstantRange add(const ConstantRange &Other) const; - /// sub - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a subtraction of a value in this range and a value in \p Other. ConstantRange sub(const ConstantRange &Other) const; - /// multiply - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a multiplication of a value in this range and a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange multiply(const ConstantRange &Other) const; - /// smax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a signed maximum of a value in this range and a value in \p Other. ConstantRange smax(const ConstantRange &Other) const; - /// umax - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned maximum of a value in this range and a value in \p Other. ConstantRange umax(const ConstantRange &Other) const; - /// udiv - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from an unsigned division of a value in this range and a value in /// \p Other. ConstantRange udiv(const ConstantRange &Other) const; - /// binaryAnd - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-and of a value in this range by a value in \p Other. ConstantRange binaryAnd(const ConstantRange &Other) const; - /// binaryOr - return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a binary-or of a value in this range by a value in \p Other. ConstantRange binaryOr(const ConstantRange &Other) const; - /// shl - Return a new range representing the possible values resulting + /// Return a new range representing the possible values resulting /// from a left shift of a value in this range by a value in \p Other. /// TODO: This isn't fully implemented yet. ConstantRange shl(const ConstantRange &Other) const; - /// lshr - Return a new range representing the possible values resulting - /// from a logical right shift of a value in this range and a value in - /// \p Other. + /// Return a new range representing the possible values resulting from a + /// logical right shift of a value in this range and a value in \p Other. ConstantRange lshr(const ConstantRange &Other) const; - /// inverse - Return a new range that is the logical not of the current set. + /// Return a new range that is the logical not of the current set. /// ConstantRange inverse() const; - /// print - Print out the bounds to a stream... + /// Print out the bounds to a stream. /// void print(raw_ostream &OS) const; - /// dump - Allow printing from a debugger easily... + /// Allow printing from a debugger easily. /// void dump() const; }; diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 0e72f04..1b0e1b7 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -37,12 +37,8 @@ class PointerType; class VectorType; class SequentialType; -template -struct ConstantCreator; -template -struct ConstantArrayCreator; -template -struct ConvertConstantType; +struct ConstantExprKeyType; +template struct ConstantAggrKeyType; //===----------------------------------------------------------------------===// /// This is the shared class of boolean and integer constants. This class @@ -268,6 +264,9 @@ public: /// isNegative - Return true if the sign bit is set. bool isNegative() const { return Val.isNegative(); } + /// isInfinity - Return true if the value is infinity + bool isInfinity() const { return Val.isInfinity(); } + /// isNaN - Return true if the value is a NaN. bool isNaN() const { return Val.isNaN(); } @@ -338,7 +337,7 @@ public: /// ConstantArray - Constant Array Declarations /// class ConstantArray : public Constant { - friend struct ConstantArrayCreator; + friend struct ConstantAggrKeyType; ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; protected: ConstantArray(ArrayType *T, ArrayRef Val); @@ -346,6 +345,10 @@ public: // ConstantArray accessors static Constant *get(ArrayType *T, ArrayRef V); +private: + static Constant *getImpl(ArrayType *T, ArrayRef V); + +public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -376,14 +379,14 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // ConstantStruct - Constant Struct Declarations // class ConstantStruct : public Constant { - friend struct ConstantArrayCreator; + friend struct ConstantAggrKeyType; ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; protected: ConstantStruct(StructType *T, ArrayRef Val); public: // ConstantStruct accessors static Constant *get(StructType *T, ArrayRef V); - static Constant *get(StructType *T, ...) END_WITH_NULL; + static Constant *get(StructType *T, ...) LLVM_END_WITH_NULL; /// getAnon - Return an anonymous struct that has the specified /// elements. If the struct is possibly empty, then you must specify a @@ -435,7 +438,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// ConstantVector - Constant Vector Declarations /// class ConstantVector : public Constant { - friend struct ConstantArrayCreator; + friend struct ConstantAggrKeyType; ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; protected: ConstantVector(VectorType *T, ArrayRef Val); @@ -443,6 +446,10 @@ public: // ConstantVector accessors static Constant *get(ArrayRef V); +private: + static Constant *getImpl(ArrayRef V); + +public: /// getSplat - Return a ConstantVector with the specified constant in each /// element. static Constant *getSplat(unsigned NumElts, Constant *Elt); @@ -794,9 +801,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) /// constant expressions. The Opcode field for the ConstantExpr class is /// maintained in the Value::SubclassData field. class ConstantExpr : public Constant { - friend struct ConstantCreator > >; - friend struct ConvertConstantType; + friend struct ConstantExprKeyType; protected: ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) @@ -856,19 +861,25 @@ public: bool HasNUW = false, bool HasNSW = false); static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false); static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false); - static Constant *getTrunc (Constant *C, Type *Ty); - static Constant *getSExt (Constant *C, Type *Ty); - static Constant *getZExt (Constant *C, Type *Ty); - static Constant *getFPTrunc (Constant *C, Type *Ty); - static Constant *getFPExtend(Constant *C, Type *Ty); - static Constant *getUIToFP (Constant *C, Type *Ty); - static Constant *getSIToFP (Constant *C, Type *Ty); - static Constant *getFPToUI (Constant *C, Type *Ty); - static Constant *getFPToSI (Constant *C, Type *Ty); - static Constant *getPtrToInt(Constant *C, Type *Ty); - static Constant *getIntToPtr(Constant *C, Type *Ty); - static Constant *getBitCast (Constant *C, Type *Ty); - static Constant *getAddrSpaceCast(Constant *C, Type *Ty); + static Constant *getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getSExt(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getZExt(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getFPTrunc(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getFPExtend(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced = false); + static Constant *getPtrToInt(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getIntToPtr(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getBitCast(Constant *C, Type *Ty, + bool OnlyIfReduced = false); + static Constant *getAddrSpaceCast(Constant *C, Type *Ty, + bool OnlyIfReduced = false); static Constant *getNSWNeg(Constant *C) { return getNeg(C, false, true); } static Constant *getNUWNeg(Constant *C) { return getNeg(C, true, false); } @@ -923,13 +934,14 @@ public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); - // @brief Convenience function for getting one of the casting operations - // using a CastOps opcode. - static Constant *getCast( - unsigned ops, ///< The opcode for the conversion - Constant *C, ///< The constant to be converted - Type *Ty ///< The type to which the constant is converted - ); + /// \brief Convenience function for getting a Cast operation. + /// + /// \param ops The opcode for the conversion + /// \param C The constant to be converted + /// \param Ty The type to which the constant is converted + /// \param OnlyIfReduced see \a getWithOperands() docs. + static Constant *getCast(unsigned ops, Constant *C, Type *Ty, + bool OnlyIfReduced = false); // @brief Create a ZExt or BitCast cast constant expression static Constant *getZExtOrBitCast( @@ -995,44 +1007,53 @@ public: /// Select constant expr /// - static Constant *getSelect(Constant *C, Constant *V1, Constant *V2); + /// \param OnlyIfReducedTy see \a getWithOperands() docs. + static Constant *getSelect(Constant *C, Constant *V1, Constant *V2, + Type *OnlyIfReducedTy = nullptr); /// get - Return a binary or shift operator constant expression, /// folding if possible. /// + /// \param OnlyIfReducedTy see \a getWithOperands() docs. static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags = 0); + unsigned Flags = 0, Type *OnlyIfReducedTy = nullptr); - /// @brief Return an ICmp or FCmp comparison operator constant expression. - static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2); + /// \brief Return an ICmp or FCmp comparison operator constant expression. + /// + /// \param OnlyIfReduced see \a getWithOperands() docs. + static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2, + bool OnlyIfReduced = false); /// get* - Return some common constants without having to /// specify the full Instruction::OPCODE identifier. /// - static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS); - static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS); + static Constant *getICmp(unsigned short pred, Constant *LHS, Constant *RHS, + bool OnlyIfReduced = false); + static Constant *getFCmp(unsigned short pred, Constant *LHS, Constant *RHS, + bool OnlyIfReduced = false); /// Getelementptr form. Value* is only accepted for convenience; /// all elements must be Constant's. /// - static Constant *getGetElementPtr(Constant *C, - ArrayRef IdxList, - bool InBounds = false) { - return getGetElementPtr(C, makeArrayRef((Value * const *)IdxList.data(), - IdxList.size()), - InBounds); - } - static Constant *getGetElementPtr(Constant *C, - Constant *Idx, - bool InBounds = false) { + /// \param OnlyIfReducedTy see \a getWithOperands() docs. + static Constant *getGetElementPtr(Constant *C, ArrayRef IdxList, + bool InBounds = false, + Type *OnlyIfReducedTy = nullptr) { + return getGetElementPtr( + C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), + InBounds, OnlyIfReducedTy); + } + static Constant *getGetElementPtr(Constant *C, Constant *Idx, + bool InBounds = false, + Type *OnlyIfReducedTy = nullptr) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef or // ArrayRef. - return getGetElementPtr(C, cast(Idx), InBounds); + return getGetElementPtr(C, cast(Idx), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, - ArrayRef IdxList, - bool InBounds = false); + static Constant *getGetElementPtr(Constant *C, ArrayRef IdxList, + bool InBounds = false, + Type *OnlyIfReducedTy = nullptr); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. @@ -1052,12 +1073,17 @@ public: return getGetElementPtr(C, IdxList, true); } - static Constant *getExtractElement(Constant *Vec, Constant *Idx); - static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); - static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); - static Constant *getExtractValue(Constant *Agg, ArrayRef Idxs); + static Constant *getExtractElement(Constant *Vec, Constant *Idx, + Type *OnlyIfReducedTy = nullptr); + static Constant *getInsertElement(Constant *Vec, Constant *Elt, Constant *Idx, + Type *OnlyIfReducedTy = nullptr); + static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask, + Type *OnlyIfReducedTy = nullptr); + static Constant *getExtractValue(Constant *Agg, ArrayRef Idxs, + Type *OnlyIfReducedTy = nullptr); static Constant *getInsertValue(Constant *Agg, Constant *Val, - ArrayRef Idxs); + ArrayRef Idxs, + Type *OnlyIfReducedTy = nullptr); /// getOpcode - Return the opcode at the root of this constant expression unsigned getOpcode() const { return getSubclassDataFromValue(); } @@ -1084,11 +1110,17 @@ public: return getWithOperands(Ops, getType()); } - /// getWithOperands - This returns the current constant expression with the - /// operands replaced with the specified values and with the specified result - /// type. The specified array must have the same number of operands as our - /// current one. - Constant *getWithOperands(ArrayRef Ops, Type *Ty) const; + /// \brief Get the current expression with the operands replaced. + /// + /// Return the current constant expression with the operands replaced with \c + /// Ops and the type with \c Ty. The new operands must have the same number + /// as the current ones. + /// + /// If \c OnlyIfReduced is \c true, nullptr will be returned unless something + /// gets constant-folded, the type changes, or the expression is otherwise + /// canonicalized. This parameter should almost always be \c false. + Constant *getWithOperands(ArrayRef Ops, Type *Ty, + bool OnlyIfReduced = false) const; /// getAsInstruction - Returns an Instruction which implements the same operation /// as this ConstantExpr. The instruction is not linked to any basic block. diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 2673504..ae1ac65 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/DebugInfo.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/DataTypes.h" @@ -27,6 +28,7 @@ namespace llvm { class Function; class Module; class Value; + class Constant; class LLVMContext; class MDNode; class StringRef; @@ -38,7 +40,6 @@ namespace llvm { class DIFile; class DIEnumerator; class DIType; - class DIArray; class DIGlobalVariable; class DIImportedEntity; class DINameSpace; @@ -53,7 +54,6 @@ namespace llvm { class DIObjCProperty; class DIBuilder { - private: Module &M; LLVMContext &VMContext; @@ -66,27 +66,34 @@ namespace llvm { Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value - SmallVector AllEnumTypes; - /// Use TrackingVH to collect RetainTypes, since they can be updated - /// later on. - SmallVector, 4> AllRetainTypes; - SmallVector AllSubprograms; - SmallVector AllGVs; - SmallVector, 4> AllImportedModules; + SmallVector AllEnumTypes; + /// Track the RetainTypes, since they can be updated later on. + SmallVector AllRetainTypes; + SmallVector AllSubprograms; + SmallVector AllGVs; + SmallVector AllImportedModules; - // Private use for multiple types of template parameters. - DITemplateValueParameter - createTemplateValueParameter(unsigned Tag, DIDescriptor Scope, - StringRef Name, DIType Ty, Value *Val, - MDNode *File = nullptr, unsigned LineNo = 0, - unsigned ColumnNo = 0); + /// \brief Track nodes that may be unresolved. + SmallVector UnresolvedNodes; + bool AllowUnresolvedNodes; + + /// Each subprogram's preserved local variables. + DenseMap> PreservedVariables; DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; - public: - explicit DIBuilder(Module &M); - enum ComplexAddrKind { OpPlus=1, OpDeref }; + /// \brief Create a temporary. + /// + /// Create an \a MDNodeFwdDecl and track it in \a UnresolvedNodes. + void trackIfUnresolved(MDNode *N); + + public: + /// \brief Construct a builder for a module. + /// + /// If \c AllowUnresolved, collect unresolved nodes attached to the module + /// in order to resolve cycles during \a finalize(). + explicit DIBuilder(Module &M, bool AllowUnresolved = true); enum DebugEmissionKind { FullDebug=1, LineTablesOnly }; /// finalize - Construct any deferred debug info descriptors. @@ -165,8 +172,12 @@ namespace llvm { /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. + /// @param SizeInBits Size. + /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class); + DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. @@ -218,36 +229,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIDerivedType - createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, DIType Ty, - unsigned Flags, llvm::Value *Val); - - /// createObjCIVar - Create debugging information entry for Objective-C - /// instance variable. - /// @param Name Member name. - /// @param File File where this member is defined. - /// @param LineNo Line number. - /// @param SizeInBits Member size. - /// @param AlignInBits Member alignment. - /// @param OffsetInBits Member offset. - /// @param Flags Flags to encode member attribute, e.g. private - /// @param Ty Parent type. - /// @param PropertyName Name of the Objective C property associated with - /// this ivar. - /// @param PropertyGetterName Name of the Objective C property getter - /// selector. - /// @param PropertySetterName Name of the Objective C property setter - /// selector. - /// @param PropertyAttributes Objective C property attributes. - DIDerivedType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - StringRef PropertyName = StringRef(), - StringRef PropertyGetterName = StringRef(), - StringRef PropertySetterName = StringRef(), - unsigned PropertyAttributes = 0); + DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name, + DIFile File, unsigned LineNo, + DIType Ty, unsigned Flags, + llvm::Constant *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -366,8 +351,8 @@ namespace llvm { /// @param LineNo Line number. /// @param ColumnNo Column Number. DITemplateValueParameter - createTemplateValueParameter(DIDescriptor Scope, StringRef Name, - DIType Ty, Value *Val, MDNode *File = nullptr, + createTemplateValueParameter(DIDescriptor Scope, StringRef Name, DIType Ty, + Constant *Val, MDNode *File = nullptr, unsigned LineNo = 0, unsigned ColumnNo = 0); /// \brief Create debugging information for a template template parameter. @@ -435,8 +420,9 @@ namespace llvm { /// includes return type at 0th index. /// @param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. - DICompositeType createSubroutineType(DIFile File, DIArray ParameterTypes, - unsigned Flags = 0); + DISubroutineType createSubroutineType(DIFile File, + DITypeArray ParameterTypes, + unsigned Flags = 0); /// createArtificialType - Create a new DIType with "artificial" flag set. DIType createArtificialType(DIType Ty); @@ -463,44 +449,22 @@ namespace llvm { /// through debug info anchors. void retainType(DIType T); - /// createUnspecifiedParameter - Create unspecified type descriptor + /// createUnspecifiedParameter - Create unspecified parameter type /// for a subroutine type. - DIDescriptor createUnspecifiedParameter(); + DIBasicType createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. - DIArray getOrCreateArray(ArrayRef Elements); + DIArray getOrCreateArray(ArrayRef Elements); + + /// getOrCreateTypeArray - Get a DITypeArray, create one if required. + DITypeArray getOrCreateTypeArray(ArrayRef Elements); /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); - /// createGlobalVariable - Create a new descriptor for the specified global. - /// @param Name Name of the variable. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type. - /// @param isLocalToUnit Boolean flag indicate whether this variable is - /// externally visible or not. - /// @param Val llvm::Value of the variable. - DIGlobalVariable - createGlobalVariable(StringRef Name, DIFile File, unsigned LineNo, - DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val); - /// \brief Create a new descriptor for the specified global. - /// @param Name Name of the variable. - /// @param LinkageName Mangled variable name. - /// @param File File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type. - /// @param isLocalToUnit Boolean flag indicate whether this variable is - /// externally visible or not. - /// @param Val llvm::Value of the variable. - DIGlobalVariable - createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile File, - unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, - llvm::Value *Val); - - /// createStaticVariable - Create a new descriptor for the specified + /// createGlobalVariable - Create a new descriptor for the specified /// variable. /// @param Context Variable scope. /// @param Name Name of the variable. @@ -512,12 +476,19 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. - DIGlobalVariable - createStaticVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile File, unsigned LineNo, - DITypeRef Ty, bool isLocalToUnit, llvm::Value *Val, - MDNode *Decl = nullptr); - + DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, + unsigned LineNo, DITypeRef Ty, + bool isLocalToUnit, + llvm::Constant *Val, + MDNode *Decl = nullptr); + + /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable + /// except that the resulting DbgNode is temporary and meant to be RAUWed. + DIGlobalVariable createTempGlobalVariableFwdDecl( + DIDescriptor Context, StringRef Name, StringRef LinkageName, + DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, + llvm::Constant *Val, MDNode *Decl = nullptr); /// createLocalVariable - Create a new descriptor for the specified /// local variable. @@ -540,23 +511,18 @@ namespace llvm { unsigned Flags = 0, unsigned ArgNo = 0); - - /// createComplexVariable - Create a new descriptor for the specified + /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. - /// @param Tag Dwarf TAG. Usually DW_TAG_auto_variable or - /// DW_TAG_arg_variable. - /// @param Scope Variable scope. - /// @param Name Variable name. - /// @param F File where this variable is defined. - /// @param LineNo Line number. - /// @param Ty Variable Type /// @param Addr An array of complex address operations. - /// @param ArgNo If this variable is an argument then this argument's - /// number. 1 indicates 1st argument. - DIVariable createComplexVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, DIFile F, unsigned LineNo, - DITypeRef Ty, ArrayRef Addr, - unsigned ArgNo = 0); + DIExpression createExpression(ArrayRef Addr = None); + + /// createPieceExpression - Create a descriptor to describe one part + /// of aggregate variable that is fragmented across multiple Values. + /// + /// @param OffsetInBytes Offset of the piece in bytes. + /// @param SizeInBytes Size of the piece in bytes. + DIExpression createPieceExpression(unsigned OffsetInBytes, + unsigned SizeInBytes); /// createFunction - Create a new descriptor for the specified subprogram. /// See comments in DISubprogram for descriptions of these fields. @@ -586,6 +552,21 @@ namespace llvm { MDNode *TParam = nullptr, MDNode *Decl = nullptr); + /// createTempFunctionFwdDecl - Identical to createFunction, + /// except that the resulting DbgNode is meant to be RAUWed. + DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name, + StringRef LinkageName, + DIFile File, unsigned LineNo, + DICompositeType Ty, bool isLocalToUnit, + bool isDefinition, + unsigned ScopeLine, + unsigned Flags = 0, + bool isOptimized = false, + Function *Fn = nullptr, + MDNode *TParam = nullptr, + MDNode *Decl = nullptr); + + /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. DISubprogram createFunction(DIScopeRef Scope, StringRef Name, @@ -646,8 +627,9 @@ namespace llvm { /// lexical block as it crosses a file. /// @param Scope Lexical block. /// @param File Source file. - DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, - DIFile File); + /// @param Discriminator DWARF path discriminator value. + DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File, + unsigned Discriminator = 0); /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. @@ -655,10 +637,8 @@ namespace llvm { /// @param File Source file. /// @param Line Line number. /// @param Col Column number. - /// @param Discriminator DWARF path discriminator value. DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col, - unsigned Discriminator); + unsigned Line, unsigned Col); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into @@ -679,7 +659,7 @@ namespace llvm { /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number - DIImportedEntity createImportedDeclaration(DIScope Context, DIScope Decl, + DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl, unsigned Line, StringRef Name = StringRef()); DIImportedEntity createImportedDeclaration(DIScope Context, @@ -690,36 +670,52 @@ namespace llvm { /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - BasicBlock *InsertAtEnd); + DIExpression Expr, BasicBlock *InsertAtEnd); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - Instruction *InsertBefore); - + DIExpression Expr, Instruction *InsertBefore); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, + DIVariable VarInfo, DIExpression Expr, BasicBlock *InsertAtEnd); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. + /// @param Expr A complex location expression. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, + DIVariable VarInfo, DIExpression Expr, Instruction *InsertBefore); + /// \brief Replace the vtable holder in the given composite type. + /// + /// If this creates a self reference, it may orphan some unresolved cycles + /// in the operands of \c T, so \a DIBuilder needs to track that. + void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + + /// \brief Replace arrays on a composite type. + /// + /// If \c T is resolved, but the arrays aren't -- which can happen if \c T + /// has a self-reference -- \a DIBuilder needs to track the array to + /// resolve cycles. + void replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParems = DIArray()); }; } // end namespace llvm diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index 877029f..a9e7595 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -27,7 +27,8 @@ #include "llvm/Pass.h" #include "llvm/Support/DataTypes.h" -// this needs to be outside of the namespace, to avoid conflict with llvm-c decl +// This needs to be outside of the namespace, to avoid conflict with llvm-c +// decl. typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef; namespace llvm { @@ -45,79 +46,71 @@ class ArrayRef; /// Enum used to categorize the alignment types stored by LayoutAlignElem enum AlignTypeEnum { - INVALID_ALIGN = 0, ///< An invalid alignment - INTEGER_ALIGN = 'i', ///< Integer type alignment - VECTOR_ALIGN = 'v', ///< Vector type alignment - FLOAT_ALIGN = 'f', ///< Floating point type alignment - AGGREGATE_ALIGN = 'a' ///< Aggregate alignment + INVALID_ALIGN = 0, + INTEGER_ALIGN = 'i', + VECTOR_ALIGN = 'v', + FLOAT_ALIGN = 'f', + AGGREGATE_ALIGN = 'a' }; -/// Layout alignment element. +/// \brief Layout alignment element. /// /// Stores the alignment data associated with a given alignment type (integer, /// vector, float) and type bit width. /// -/// @note The unusual order of elements in the structure attempts to reduce +/// \note The unusual order of elements in the structure attempts to reduce /// padding and make the structure slightly more cache friendly. struct LayoutAlignElem { - unsigned AlignType : 8; ///< Alignment type (AlignTypeEnum) - unsigned TypeBitWidth : 24; ///< Type bit width - unsigned ABIAlign : 16; ///< ABI alignment for this type/bitw - unsigned PrefAlign : 16; ///< Pref. alignment for this type/bitw + /// \brief Alignment type from \c AlignTypeEnum + unsigned AlignType : 8; + unsigned TypeBitWidth : 24; + unsigned ABIAlign : 16; + unsigned PrefAlign : 16; - /// Initializer static LayoutAlignElem get(AlignTypeEnum align_type, unsigned abi_align, unsigned pref_align, uint32_t bit_width); - /// Equality predicate bool operator==(const LayoutAlignElem &rhs) const; }; -/// Layout pointer alignment element. +/// \brief Layout pointer alignment element. /// /// Stores the alignment data associated with a given pointer and address space. /// -/// @note The unusual order of elements in the structure attempts to reduce +/// \note The unusual order of elements in the structure attempts to reduce /// padding and make the structure slightly more cache friendly. struct PointerAlignElem { - unsigned ABIAlign; ///< ABI alignment for this type/bitw - unsigned PrefAlign; ///< Pref. alignment for this type/bitw - uint32_t TypeByteWidth; ///< Type byte width - uint32_t AddressSpace; ///< Address space for the pointer type + unsigned ABIAlign; + unsigned PrefAlign; + uint32_t TypeByteWidth; + uint32_t AddressSpace; /// Initializer static PointerAlignElem get(uint32_t AddressSpace, unsigned ABIAlign, - unsigned PrefAlign, uint32_t TypeByteWidth); - /// Equality predicate + unsigned PrefAlign, uint32_t TypeByteWidth); bool operator==(const PointerAlignElem &rhs) const; }; -/// This class holds a parsed version of the target data layout string in a -/// module and provides methods for querying it. The target data layout string -/// is specified *by the target* - a frontend generating LLVM IR is required to -/// generate the right target data for the target being codegen'd to. +/// \brief A parsed version of the target data layout string in and methods for +/// querying it. +/// +/// The target data layout string is specified *by the target* - a frontend +/// generating LLVM IR is required to generate the right target data for the +/// target being codegen'd to. class DataLayout { private: - bool LittleEndian; ///< Defaults to false - unsigned StackNaturalAlign; ///< Stack natural alignment - - enum ManglingModeT { - MM_None, - MM_ELF, - MM_MachO, - MM_WINCOFF, - MM_Mips - }; + /// Defaults to false. + bool BigEndian; + + unsigned StackNaturalAlign; + + enum ManglingModeT { MM_None, MM_ELF, MM_MachO, MM_WINCOFF, MM_Mips }; ManglingModeT ManglingMode; - SmallVector LegalIntWidths; ///< Legal Integers. + SmallVector LegalIntWidths; - /// Alignments - Where the primitive type alignment data is stored. - /// - /// @sa reset(). - /// @note Could support multiple size pointer alignments, e.g., 32-bit - /// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now, - /// we don't. + /// \brief Primitive type alignment data. SmallVector Alignments; + typedef SmallVector PointersTy; PointersTy Pointers; @@ -128,31 +121,28 @@ private: PointersTy::iterator findPointerLowerBound(uint32_t AddressSpace); - /// InvalidAlignmentElem - This member is a signal that a requested alignment - /// type and bit width were not found in the SmallVector. + /// This member is a signal that a requested alignment type and bit width were + /// not found in the SmallVector. static const LayoutAlignElem InvalidAlignmentElem; - /// InvalidPointerElem - This member is a signal that a requested pointer - /// type and bit width were not found in the DenseSet. + /// This member is a signal that a requested pointer type and bit width were + /// not found in the DenseSet. static const PointerAlignElem InvalidPointerElem; // The StructType -> StructLayout map. mutable void *LayoutMap; - //! Set/initialize target alignments void setAlignment(AlignTypeEnum align_type, unsigned abi_align, unsigned pref_align, uint32_t bit_width); unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, bool ABIAlign, Type *Ty) const; - - //! Set/initialize pointer alignments void setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign, unsigned PrefAlign, uint32_t TypeByteWidth); - //! Internal helper method that returns requested alignment for type. + /// Internal helper method that returns requested alignment for type. unsigned getAlignment(Type *Ty, bool abi_or_pref) const; - /// Valid alignment predicate. + /// \brief Valid alignment predicate. /// /// Predicate that tests a LayoutAlignElem reference returned by get() against /// InvalidAlignmentElem. @@ -160,10 +150,10 @@ private: return &align != &InvalidAlignmentElem; } - /// Valid pointer predicate. + /// \brief Valid pointer predicate. /// - /// Predicate that tests a PointerAlignElem reference returned by get() against - /// InvalidPointerElem. + /// Predicate that tests a PointerAlignElem reference returned by get() + /// against \c InvalidPointerElem. bool validPointer(const PointerAlignElem &align) const { return &align != &InvalidPointerElem; } @@ -184,11 +174,13 @@ public: /// Initialize target data from properties stored in the module. explicit DataLayout(const Module *M); + void init(const Module *M); + DataLayout(const DataLayout &DL) : LayoutMap(nullptr) { *this = DL; } DataLayout &operator=(const DataLayout &DL) { clear(); - LittleEndian = DL.isLittleEndian(); + BigEndian = DL.isBigEndian(); StackNaturalAlign = DL.StackNaturalAlign; ManglingMode = DL.ManglingMode; LegalIntWidths = DL.LegalIntWidths; @@ -200,27 +192,28 @@ public: bool operator==(const DataLayout &Other) const; bool operator!=(const DataLayout &Other) const { return !(*this == Other); } - ~DataLayout(); // Not virtual, do not subclass this class + ~DataLayout(); // Not virtual, do not subclass this class /// Parse a data layout string (with fallback to default values). void reset(StringRef LayoutDescription); /// Layout endianness... - bool isLittleEndian() const { return LittleEndian; } - bool isBigEndian() const { return !LittleEndian; } + bool isLittleEndian() const { return !BigEndian; } + bool isBigEndian() const { return BigEndian; } - /// getStringRepresentation - Return the string representation of the - /// DataLayout. This representation is in the same format accepted by the - /// string constructor above. + /// \brief Returns the string representation of the DataLayout. + /// + /// This representation is in the same format accepted by the string + /// constructor above. std::string getStringRepresentation() const; - /// isLegalInteger - This function returns true if the specified type is - /// known to be a native integer type supported by the CPU. For example, - /// i64 is not native on most 32-bit CPUs and i37 is not native on any known - /// one. This returns false if the integer width is not legal. + /// \brief Returns true if the specified type is known to be a native integer + /// type supported by the CPU. /// - /// The width is specified in bits. + /// For example, i64 is not native on most 32-bit CPUs and i37 is not native + /// on any known one. This returns false if the integer width is not legal. /// + /// The width is specified in bits. bool isLegalInteger(unsigned Width) const { for (unsigned LegalIntWidth : LegalIntWidths) if (LegalIntWidth == Width) @@ -228,22 +221,20 @@ public: return false; } - bool isIllegalInteger(unsigned Width) const { - return !isLegalInteger(Width); - } + bool isIllegalInteger(unsigned Width) const { return !isLegalInteger(Width); } /// Returns true if the given alignment exceeds the natural stack alignment. bool exceedsNaturalStackAlignment(unsigned Align) const { return (StackNaturalAlign != 0) && (Align > StackNaturalAlign); } + unsigned getStackAlignment() const { return StackNaturalAlign; } + bool hasMicrosoftFastStdCallMangling() const { return ManglingMode == MM_WINCOFF; } - bool hasLinkerPrivateGlobalPrefix() const { - return ManglingMode == MM_MachO; - } + bool hasLinkerPrivateGlobalPrefix() const { return ManglingMode == MM_MachO; } const char *getLinkerPrivateGlobalPrefix() const { if (ManglingMode == MM_MachO) @@ -281,10 +272,11 @@ public: static const char *getManglingComponent(const Triple &T); - /// fitsInLegalInteger - This function returns true if the specified type fits - /// in a native integer type supported by the CPU. For example, if the CPU - /// only supports i32 as a native integer type, then i27 fits in a legal - /// integer type but i45 does not. + /// \brief Returns true if the specified type fits in a native integer type + /// supported by the CPU. + /// + /// For example, if the CPU only supports i32 as a native integer type, then + /// i27 fits in a legal integer type but i45 does not. bool fitsInLegalInteger(unsigned Width) const { for (unsigned LegalIntWidth : LegalIntWidths) if (Width <= LegalIntWidth) @@ -342,118 +334,116 @@ public: /// [*] The alloc size depends on the alignment, and thus on the target. /// These values are for x86-32 linux. - /// getTypeSizeInBits - Return the number of bits necessary to hold the - /// specified type. For example, returns 36 for i36 and 80 for x86_fp80. - /// The type passed must have a size (Type::isSized() must return true). + /// \brief Returns the number of bits necessary to hold the specified type. + /// + /// For example, returns 36 for i36 and 80 for x86_fp80. The type passed must + /// have a size (Type::isSized() must return true). uint64_t getTypeSizeInBits(Type *Ty) const; - /// getTypeStoreSize - Return the maximum number of bytes that may be - /// overwritten by storing the specified type. For example, returns 5 - /// for i36 and 10 for x86_fp80. + /// \brief Returns the maximum number of bytes that may be overwritten by + /// storing the specified type. + /// + /// For example, returns 5 for i36 and 10 for x86_fp80. uint64_t getTypeStoreSize(Type *Ty) const { - return (getTypeSizeInBits(Ty)+7)/8; + return (getTypeSizeInBits(Ty) + 7) / 8; } - /// getTypeStoreSizeInBits - Return the maximum number of bits that may be - /// overwritten by storing the specified type; always a multiple of 8. For - /// example, returns 40 for i36 and 80 for x86_fp80. + /// \brief Returns the maximum number of bits that may be overwritten by + /// storing the specified type; always a multiple of 8. + /// + /// For example, returns 40 for i36 and 80 for x86_fp80. uint64_t getTypeStoreSizeInBits(Type *Ty) const { - return 8*getTypeStoreSize(Ty); + return 8 * getTypeStoreSize(Ty); } - /// getTypeAllocSize - Return the offset in bytes between successive objects - /// of the specified type, including alignment padding. This is the amount - /// that alloca reserves for this type. For example, returns 12 or 16 for - /// x86_fp80, depending on alignment. + /// \brief Returns the offset in bytes between successive objects of the + /// specified type, including alignment padding. + /// + /// This is the amount that alloca reserves for this type. For example, + /// returns 12 or 16 for x86_fp80, depending on alignment. uint64_t getTypeAllocSize(Type *Ty) const { // Round up to the next alignment boundary. - return RoundUpAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); + return RoundUpToAlignment(getTypeStoreSize(Ty), getABITypeAlignment(Ty)); } - /// getTypeAllocSizeInBits - Return the offset in bits between successive - /// objects of the specified type, including alignment padding; always a - /// multiple of 8. This is the amount that alloca reserves for this type. - /// For example, returns 96 or 128 for x86_fp80, depending on alignment. + /// \brief Returns the offset in bits between successive objects of the + /// specified type, including alignment padding; always a multiple of 8. + /// + /// This is the amount that alloca reserves for this type. For example, + /// returns 96 or 128 for x86_fp80, depending on alignment. uint64_t getTypeAllocSizeInBits(Type *Ty) const { - return 8*getTypeAllocSize(Ty); + return 8 * getTypeAllocSize(Ty); } - /// getABITypeAlignment - Return the minimum ABI-required alignment for the - /// specified type. + /// \brief Returns the minimum ABI-required alignment for the specified type. unsigned getABITypeAlignment(Type *Ty) const; - /// getABIIntegerTypeAlignment - Return the minimum ABI-required alignment for - /// an integer type of the specified bitwidth. + /// \brief Returns the minimum ABI-required alignment for an integer type of + /// the specified bitwidth. unsigned getABIIntegerTypeAlignment(unsigned BitWidth) const; - /// getPrefTypeAlignment - Return the preferred stack/global alignment for - /// the specified type. This is always at least as good as the ABI alignment. + /// \brief Returns the preferred stack/global alignment for the specified + /// type. + /// + /// This is always at least as good as the ABI alignment. unsigned getPrefTypeAlignment(Type *Ty) const; - /// getPreferredTypeAlignmentShift - Return the preferred alignment for the - /// specified type, returned as log2 of the value (a shift amount). + /// \brief Returns the preferred alignment for the specified type, returned as + /// log2 of the value (a shift amount). unsigned getPreferredTypeAlignmentShift(Type *Ty) const; - /// getIntPtrType - Return an integer type with size at least as big as that - /// of a pointer in the given address space. + /// \brief Returns an integer type with size at least as big as that of a + /// pointer in the given address space. IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const; - /// getIntPtrType - Return an integer (vector of integer) type with size at - /// least as big as that of a pointer of the given pointer (vector of pointer) - /// type. + /// \brief Returns an integer (vector of integer) type with size at least as + /// big as that of a pointer of the given pointer (vector of pointer) type. Type *getIntPtrType(Type *) const; - /// getSmallestLegalIntType - Return the smallest integer type with size at - /// least as big as Width bits. + /// \brief Returns the smallest integer type with size at least as big as + /// Width bits. Type *getSmallestLegalIntType(LLVMContext &C, unsigned Width = 0) const; - /// getLargestLegalIntType - Return the largest legal integer type, or null if - /// none are set. + /// \brief Returns the largest legal integer type, or null if none are set. Type *getLargestLegalIntType(LLVMContext &C) const { unsigned LargestSize = getLargestLegalIntTypeSize(); return (LargestSize == 0) ? nullptr : Type::getIntNTy(C, LargestSize); } - /// getLargestLegalIntTypeSize - Return the size of largest legal integer - /// type size, or 0 if none are set. + /// \brief Returns the size of largest legal integer type size, or 0 if none + /// are set. unsigned getLargestLegalIntTypeSize() const; - /// getIndexedOffset - return the offset from the beginning of the type for - /// the specified indices. This is used to implement getelementptr. + /// \brief Returns the offset from the beginning of the type for the specified + /// indices. + /// + /// This is used to implement getelementptr. uint64_t getIndexedOffset(Type *Ty, ArrayRef Indices) const; - /// getStructLayout - Return a StructLayout object, indicating the alignment - /// of the struct, its size, and the offsets of its fields. Note that this - /// information is lazily cached. + /// \brief Returns a StructLayout object, indicating the alignment of the + /// struct, its size, and the offsets of its fields. + /// + /// Note that this information is lazily cached. const StructLayout *getStructLayout(StructType *Ty) const; - /// getPreferredAlignment - Return the preferred alignment of the specified - /// global. This includes an explicitly requested alignment (if the global - /// has one). + /// \brief Returns the preferred alignment of the specified global. + /// + /// This includes an explicitly requested alignment (if the global has one). unsigned getPreferredAlignment(const GlobalVariable *GV) const; - /// getPreferredAlignmentLog - Return the preferred alignment of the - /// specified global, returned in log form. This includes an explicitly - /// requested alignment (if the global has one). + /// \brief Returns the preferred alignment of the specified global, returned + /// in log form. + /// + /// This includes an explicitly requested alignment (if the global has one). unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const; - - /// RoundUpAlignment - Round the specified value up to the next alignment - /// boundary specified by Alignment. For example, 7 rounded up to an - /// alignment boundary of 4 is 8. 8 rounded up to the alignment boundary of 4 - /// is 8 because it is already aligned. - template - static UIntTy RoundUpAlignment(UIntTy Val, unsigned Alignment) { - assert((Alignment & (Alignment-1)) == 0 && "Alignment must be power of 2!"); - return (Val + (Alignment-1)) & ~UIntTy(Alignment-1); - } }; inline DataLayout *unwrap(LLVMTargetDataRef P) { - return reinterpret_cast(P); + return reinterpret_cast(P); } inline LLVMTargetDataRef wrap(const DataLayout *P) { - return reinterpret_cast(const_cast(P)); + return reinterpret_cast(const_cast(P)); } class DataLayoutPass : public ImmutablePass { @@ -466,40 +456,28 @@ public: const DataLayout &getDataLayout() const { return DL; } - // For use with the C API. C++ code should always use the constructor that - // takes a module. - explicit DataLayoutPass(const DataLayout &DL); - - explicit DataLayoutPass(const Module *M); - static char ID; // Pass identification, replacement for typeid + + bool doFinalization(Module &M) override; + bool doInitialization(Module &M) override; }; -/// StructLayout - used to lazily calculate structure layout information for a -/// target machine, based on the DataLayout structure. -/// +/// Used to lazily calculate structure layout information for a target machine, +/// based on the DataLayout structure. class StructLayout { uint64_t StructSize; unsigned StructAlignment; unsigned NumElements; - uint64_t MemberOffsets[1]; // variable sized array! + uint64_t MemberOffsets[1]; // variable sized array! public: + uint64_t getSizeInBytes() const { return StructSize; } - uint64_t getSizeInBytes() const { - return StructSize; - } + uint64_t getSizeInBits() const { return 8 * StructSize; } - uint64_t getSizeInBits() const { - return 8*StructSize; - } + unsigned getAlignment() const { return StructAlignment; } - unsigned getAlignment() const { - return StructAlignment; - } - - /// getElementContainingOffset - Given a valid byte offset into the structure, - /// return the structure index that contains it. - /// + /// \brief Given a valid byte offset into the structure, returns the structure + /// index that contains it. unsigned getElementContainingOffset(uint64_t Offset) const; uint64_t getElementOffset(unsigned Idx) const { @@ -508,15 +486,14 @@ public: } uint64_t getElementOffsetInBits(unsigned Idx) const { - return getElementOffset(Idx)*8; + return getElementOffset(Idx) * 8; } private: - friend class DataLayout; // Only DataLayout can create this class + friend class DataLayout; // Only DataLayout can create this class StructLayout(StructType *ST, const DataLayout &DL); }; - // The implementation of this method is provided inline as it is particularly // well suited to constant folding when called on a specific Type subclass. inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { @@ -546,7 +523,7 @@ inline uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const { case Type::PPC_FP128TyID: case Type::FP128TyID: return 128; - // In memory objects this is always aligned to a higher boundary, but + // In memory objects this is always aligned to a higher boundary, but // only 80 bits contain information. case Type::X86_FP80TyID: return 80; diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 088eb9f..5c85d6d 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -18,13 +18,15 @@ #define LLVM_IR_DEBUGINFO_H #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/ErrorHandling.h" +#include namespace llvm { class BasicBlock; @@ -37,6 +39,7 @@ class Value; class DbgDeclareInst; class DbgValueInst; class Instruction; +class Metadata; class MDNode; class MDString; class NamedMDNode; @@ -52,21 +55,78 @@ class DIType; class DIScope; class DIObjCProperty; -/// Maps from type identifier to the actual MDNode. +/// \brief Maps from type identifier to the actual MDNode. typedef DenseMap DITypeIdentifierMap; -/// DIDescriptor - A thin wraper around MDNode to access encoded debug info. -/// This should not be stored in a container, because the underlying MDNode -/// may change in certain situations. +class DIHeaderFieldIterator + : public std::iterator { + StringRef Header; + StringRef Current; + +public: + DIHeaderFieldIterator() {} + DIHeaderFieldIterator(StringRef Header) + : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} + StringRef operator*() const { return Current; } + const StringRef * operator->() const { return &Current; } + DIHeaderFieldIterator &operator++() { + increment(); + return *this; + } + DIHeaderFieldIterator operator++(int) { + DIHeaderFieldIterator X(*this); + increment(); + return X; + } + bool operator==(const DIHeaderFieldIterator &X) const { + return Current.data() == X.Current.data(); + } + bool operator!=(const DIHeaderFieldIterator &X) const { + return !(*this == X); + } + + StringRef getHeader() const { return Header; } + StringRef getCurrent() const { return Current; } + StringRef getPrefix() const { + if (Current.begin() == Header.begin()) + return StringRef(); + return Header.slice(0, Current.begin() - Header.begin() - 1); + } + StringRef getSuffix() const { + if (Current.end() == Header.end()) + return StringRef(); + return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); + } + +private: + void increment() { + assert(Current.data() != nullptr && "Cannot increment past the end"); + StringRef Suffix = getSuffix(); + Current = Suffix.slice(0, Suffix.find('\0')); + } +}; + +/// \brief A thin wraper around MDNode to access encoded debug info. +/// +/// This should not be stored in a container, because the underlying MDNode may +/// change in certain situations. class DIDescriptor { // Befriends DIRef so DIRef can befriend the protected member // function: getFieldAs. template friend class DIRef; public: + /// \brief Accessibility flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. enum { - FlagPrivate = 1 << 0, - FlagProtected = 1 << 1, + FlagAccessibility = 1 << 0 | 1 << 1, + FlagPrivate = 1, + FlagProtected = 2, + FlagPublic = 3, + FlagFwdDecl = 1 << 2, FlagAppleBlock = 1 << 3, FlagBlockByrefStruct = 1 << 4, @@ -108,8 +168,9 @@ public: bool Verify() const; - operator MDNode *() const { return const_cast(DbgNode); } - MDNode *operator->() const { return const_cast(DbgNode); } + MDNode *get() const { return const_cast(DbgNode); } + operator MDNode *() const { return get(); } + MDNode *operator->() const { return get(); } // An explicit operator bool so that we can do testing of DI values // easily. @@ -121,12 +182,36 @@ public: bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - uint16_t getTag() const { - return getUnsignedField(0) & ~LLVMDebugVersionMask; + StringRef getHeader() const { + return getStringField(0); + } + + size_t getNumHeaderFields() const { + return std::distance(DIHeaderFieldIterator(getHeader()), + DIHeaderFieldIterator()); } + StringRef getHeaderField(unsigned Index) const { + // Since callers expect an empty string for out-of-range accesses, we can't + // use std::advance() here. + for (DIHeaderFieldIterator I(getHeader()), E; I != E; ++I, --Index) + if (!Index) + return *I; + return StringRef(); + } + + template T getHeaderFieldAs(unsigned Index) const { + T Int; + if (getHeaderField(Index).getAsInteger(0, Int)) + return 0; + return Int; + } + + uint16_t getTag() const { return getHeaderFieldAs(0); } + bool isDerivedType() const; bool isCompositeType() const; + bool isSubroutineType() const; bool isBasicType() const; bool isVariable() const; bool isSubprogram() const; @@ -140,20 +225,21 @@ public: bool isSubrange() const; bool isEnumerator() const; bool isType() const; - bool isUnspecifiedParameter() const; bool isTemplateTypeParameter() const; bool isTemplateValueParameter() const; bool isObjCProperty() const; bool isImportedEntity() const; + bool isExpression() const; - /// print - print descriptor. void print(raw_ostream &OS) const; - - /// dump - print descriptor to dbgs() with a newline. void dump() const; + + /// \brief Replace all uses of debug info referenced by this descriptor. + void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); + void replaceAllUsesWith(MDNode *D); }; -/// DISubrange - This is used to represent ranges, for array bounds. +/// \brief This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -161,23 +247,27 @@ class DISubrange : public DIDescriptor { public: explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} - int64_t getLo() const { return getInt64Field(1); } - int64_t getCount() const { return getInt64Field(2); } + int64_t getLo() const { return getHeaderFieldAs(1); } + int64_t getCount() const { return getHeaderFieldAs(2); } bool Verify() const; }; -/// DIArray - This descriptor holds an array of descriptors. -class DIArray : public DIDescriptor { +/// \brief This descriptor holds an array of nodes with type T. +template class DITypedArray : public DIDescriptor { public: - explicit DIArray(const MDNode *N = nullptr) : DIDescriptor(N) {} - - unsigned getNumElements() const; - DIDescriptor getElement(unsigned Idx) const { - return getDescriptorField(Idx); + explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} + unsigned getNumElements() const { + return DbgNode ? DbgNode->getNumOperands() : 0; + } + T getElement(unsigned Idx) const { + return getFieldAs(Idx); } }; -/// DIEnumerator - A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +typedef DITypedArray DIArray; + +/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). +/// /// FIXME: it seems strange that this doesn't have either a reference to the /// type/precision or a file/line pair for location info. class DIEnumerator : public DIDescriptor { @@ -187,16 +277,17 @@ class DIEnumerator : public DIDescriptor { public: explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} - StringRef getName() const { return getStringField(1); } - int64_t getEnumValue() const { return getInt64Field(2); } + StringRef getName() const { return getHeaderField(1); } + int64_t getEnumValue() const { return getHeaderFieldAs(2); } bool Verify() const; }; template class DIRef; typedef DIRef DIScopeRef; typedef DIRef DITypeRef; +typedef DITypedArray DITypeArray; -/// DIScope - A base class for various scopes. +/// \brief A base class for various scopes. /// /// Although, implementation-wise, DIScope is the parent class of most /// other DIxxx classes, including DIType and its descendants, most of @@ -212,21 +303,28 @@ protected: public: explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} - /// Gets the parent scope for this scope node or returns a - /// default constructed scope. + /// \brief Get the parent scope. + /// + /// Gets the parent scope for this scope node or returns a default + /// constructed scope. DIScopeRef getContext() const; + /// \brief Get the scope name. + /// /// If the scope node has a name, return that, else return an empty string. StringRef getName() const; StringRef getFilename() const; StringRef getDirectory() const; - /// Generate a reference to this DIScope. Uses the type identifier instead - /// of the actual MDNode if possible, to help type uniquing. + /// \brief Generate a reference to this DIScope. + /// + /// Uses the type identifier instead of the actual MDNode if possible, to + /// help type uniquing. DIScopeRef getRef() const; }; -/// Represents reference to a DIDescriptor, abstracts over direct and -/// identifier-based metadata references. +/// \brief Represents reference to a DIDescriptor. +/// +/// Abstracts over direct and identifier-based metadata references. template class DIRef { template friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; @@ -234,15 +332,16 @@ template class DIRef { friend DIScopeRef DIScope::getRef() const; friend class DIType; - /// Val can be either a MDNode or a MDString, in the latter, - /// MDString specifies the type identifier. - const Value *Val; - explicit DIRef(const Value *V); + /// \brief Val can be either a MDNode or a MDString. + /// + /// In the latter, MDString specifies the type identifier. + const Metadata *Val; + explicit DIRef(const Metadata *V); public: T resolve(const DITypeIdentifierMap &Map) const; StringRef getName() const; - operator Value *() const { return const_cast(Val); } + operator Metadata *() const { return const_cast(Val); } }; template @@ -273,17 +372,18 @@ template StringRef DIRef::getName() const { return MS->getString(); } -/// Specialize getFieldAs to handle fields that are references to DIScopes. +/// \brief Handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const; -/// Specialize DIRef constructor for DIScopeRef. -template <> DIRef::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DIScopeRef. +template <> DIRef::DIRef(const Metadata *V); -/// Specialize getFieldAs to handle fields that are references to DITypes. +/// \brief Handle fields that are references to DITypes. template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const; -/// Specialize DIRef constructor for DITypeRef. -template <> DIRef::DIRef(const Value *V); +/// \brief Specialize DIRef constructor for DITypeRef. +template <> DIRef::DIRef(const Metadata *V); -/// DIType - This is a wrapper for a type. +/// \briefThis is a wrapper for a type. +/// /// FIXME: Types should be factored much better so that CV qualifiers and /// others do not require a huge and empty descriptor full of zeros. class DIType : public DIScope { @@ -299,22 +399,35 @@ public: return DITypeRef(&*getRef()); } - /// Verify - Verify that a type descriptor is well formed. bool Verify() const; DIScopeRef getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - uint64_t getSizeInBits() const { return getUInt64Field(5); } - uint64_t getAlignInBits() const { return getUInt64Field(6); } + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { + return getHeaderFieldAs(2); + } + uint64_t getSizeInBits() const { + return getHeaderFieldAs(3); + } + uint64_t getAlignInBits() const { + return getHeaderFieldAs(4); + } // FIXME: Offset is only used for DW_TAG_member nodes. Making every type // carry this is just plain insane. - uint64_t getOffsetInBits() const { return getUInt64Field(7); } - unsigned getFlags() const { return getUnsignedField(8); } - bool isPrivate() const { return (getFlags() & FlagPrivate) != 0; } - bool isProtected() const { return (getFlags() & FlagProtected) != 0; } + uint64_t getOffsetInBits() const { + return getHeaderFieldAs(5); + } + unsigned getFlags() const { return getHeaderFieldAs(6); } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } - // isAppleBlock - Return true if this is the Apple Blocks extension. bool isAppleBlockExtension() const { return (getFlags() & FlagAppleBlock) != 0; } @@ -336,27 +449,22 @@ public: return (getFlags() & FlagRValueReference) != 0; } bool isValid() const { return DbgNode && isType(); } - - /// replaceAllUsesWith - Replace all uses of debug info referenced by - /// this descriptor. - void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); - void replaceAllUsesWith(MDNode *D); }; -/// DIBasicType - A basic type, like 'int' or 'float'. +/// \brief A basic type, like 'int' or 'float'. class DIBasicType : public DIType { public: explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} - unsigned getEncoding() const { return getUnsignedField(9); } + unsigned getEncoding() const { return getHeaderFieldAs(7); } - /// Verify - Verify that a basic type descriptor is well formed. bool Verify() const; }; -/// DIDerivedType - A simple derived type, like a const qualified type, -/// a typedef, a pointer or reference, et cetera. Or, a data member of -/// a class/struct/union. +/// \brief A simple derived type +/// +/// Like a const qualified type, a typedef, a pointer or reference, et cetera. +/// Or, a data member of a class/struct/union. class DIDerivedType : public DIType { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -364,62 +472,96 @@ class DIDerivedType : public DIType { public: explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} - DITypeRef getTypeDerivedFrom() const { return getFieldAs(9); } + DITypeRef getTypeDerivedFrom() const { return getFieldAs(3); } - /// getObjCProperty - Return property node, if this ivar is - /// associated with one. + /// \brief Return property node, if this ivar is associated with one. MDNode *getObjCProperty() const; DITypeRef getClassType() const { assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - return getFieldAs(10); + return getFieldAs(4); } Constant *getConstant() const { assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - return getConstantField(10); + return getConstantField(4); } - /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; }; -/// DICompositeType - This descriptor holds a type that can refer to multiple -/// other types, like a function or struct. +/// \brief Types that refer to multiple other types. +/// +/// This descriptor holds a type that can refer to multiple other types, like a +/// function or struct. +/// /// DICompositeType is derived from DIDerivedType because some /// composite types (such as enums) can be derived from basic types // FIXME: Make this derive from DIType directly & just store the // base type in a single DIType field. class DICompositeType : public DIDerivedType { + friend class DIBuilder; friend class DIDescriptor; void printInternal(raw_ostream &OS) const; + /// \brief Set the array of member DITypes. + void setArraysHelper(MDNode *Elements, MDNode *TParams); + public: explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} - DIArray getTypeArray() const { return getFieldAs(10); } - void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); - unsigned getRunTimeLang() const { return getUnsignedField(11); } - DITypeRef getContainingType() const { return getFieldAs(12); } + DIArray getElements() const { + assert(!isSubroutineType() && "no elements for DISubroutineType"); + return getFieldAs(4); + } + +private: + template + void setArrays(DITypedArray Elements, DIArray TParams = DIArray()) { + assert((!TParams || DbgNode->getNumOperands() == 8) && + "If you're setting the template parameters this should include a slot " + "for that!"); + setArraysHelper(Elements, TParams); + } + +public: + unsigned getRunTimeLang() const { + return getHeaderFieldAs(7); + } + DITypeRef getContainingType() const { return getFieldAs(5); } + +private: + /// \brief Set the containing type. void setContainingType(DICompositeType ContainingType); - DIArray getTemplateParams() const { return getFieldAs(13); } + +public: + DIArray getTemplateParams() const { return getFieldAs(6); } MDString *getIdentifier() const; - /// Verify - Verify that a composite type descriptor is well formed. bool Verify() const; }; -/// DIFile - This is a wrapper for a file. +class DISubroutineType : public DICompositeType { +public: + explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} + DITypedArray getTypeArray() const { + return getFieldAs>(4); + } +}; + +/// \brief This is a wrapper for a file. class DIFile : public DIScope { friend class DIDescriptor; public: explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} + + /// \brief Retrieve the MDNode for the directory/file pair. MDNode *getFileNode() const; bool Verify() const; }; -/// DICompileUnit - A wrapper for a compile unit. +/// \brief A wrapper for a compile unit. class DICompileUnit : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -428,13 +570,13 @@ public: explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} dwarf::SourceLanguage getLanguage() const { - return static_cast(getUnsignedField(2)); + return static_cast(getHeaderFieldAs(1)); } - StringRef getProducer() const { return getStringField(3); } + StringRef getProducer() const { return getHeaderField(2); } - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } + bool isOptimized() const { return getHeaderFieldAs(3) != 0; } + StringRef getFlags() const { return getHeaderField(4); } + unsigned getRunTimeVersion() const { return getHeaderFieldAs(5); } DIArray getEnumTypes() const; DIArray getRetainedTypes() const; @@ -442,14 +584,16 @@ public: DIArray getGlobalVariables() const; DIArray getImportedEntities() const; - StringRef getSplitDebugFilename() const { return getStringField(12); } - unsigned getEmissionKind() const { return getUnsignedField(13); } + void replaceSubprograms(DIArray Subprograms); + void replaceGlobalVariables(DIArray GlobalVariables); + + StringRef getSplitDebugFilename() const { return getHeaderField(6); } + unsigned getEmissionKind() const { return getHeaderFieldAs(7); } - /// Verify - Verify that a compile unit is well formed. bool Verify() const; }; -/// DISubprogram - This is a wrapper for a subprogram (e.g. a function). +/// \brief This is a wrapper for a subprogram (e.g. a function). class DISubprogram : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -457,93 +601,95 @@ class DISubprogram : public DIScope { public: explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} - DIScopeRef getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - unsigned getLineNumber() const { return getUnsignedField(6); } - DICompositeType getType() const { return getFieldAs(7); } - - /// isLocalToUnit - Return true if this subprogram is local to the current - /// compile unit, like 'static' in C. - unsigned isLocalToUnit() const { return getUnsignedField(8); } - unsigned isDefinition() const { return getUnsignedField(9); } + StringRef getName() const { return getHeaderField(1); } + StringRef getDisplayName() const { return getHeaderField(2); } + StringRef getLinkageName() const { return getHeaderField(3); } + unsigned getLineNumber() const { return getHeaderFieldAs(4); } - unsigned getVirtuality() const { return getUnsignedField(10); } - unsigned getVirtualIndex() const { return getUnsignedField(11); } + /// \brief Check if this is local (like 'static' in C). + unsigned isLocalToUnit() const { return getHeaderFieldAs(5); } + unsigned isDefinition() const { return getHeaderFieldAs(6); } - DITypeRef getContainingType() const { return getFieldAs(12); } + unsigned getVirtuality() const { return getHeaderFieldAs(7); } + unsigned getVirtualIndex() const { return getHeaderFieldAs(8); } - unsigned getFlags() const { return getUnsignedField(13); } + unsigned getFlags() const { return getHeaderFieldAs(9); } - unsigned isArtificial() const { - return (getUnsignedField(13) & FlagArtificial) != 0; - } - /// isPrivate - Return true if this subprogram has "private" - /// access specifier. - bool isPrivate() const { return (getUnsignedField(13) & FlagPrivate) != 0; } - /// isProtected - Return true if this subprogram has "protected" - /// access specifier. - bool isProtected() const { - return (getUnsignedField(13) & FlagProtected) != 0; - } - /// isExplicit - Return true if this subprogram is marked as explicit. - bool isExplicit() const { return (getUnsignedField(13) & FlagExplicit) != 0; } - /// isPrototyped - Return true if this subprogram is prototyped. - bool isPrototyped() const { - return (getUnsignedField(13) & FlagPrototyped) != 0; - } + unsigned isOptimized() const { return getHeaderFieldAs(10); } - /// Return true if this subprogram is a C++11 reference-qualified - /// non-static member function (void foo() &). - unsigned isLValueReference() const { - return (getUnsignedField(13) & FlagLValueReference) != 0; - } + /// \brief Get the beginning of the scope of the function (not the name). + unsigned getScopeLineNumber() const { return getHeaderFieldAs(11); } - /// Return true if this subprogram is a C++11 - /// rvalue-reference-qualified non-static member function - /// (void foo() &&). - unsigned isRValueReference() const { - return (getUnsignedField(13) & FlagRValueReference) != 0; - } + DIScopeRef getContext() const { return getFieldAs(2); } + DISubroutineType getType() const { return getFieldAs(3); } - unsigned isOptimized() const; + DITypeRef getContainingType() const { return getFieldAs(4); } - /// Verify - Verify that a subprogram descriptor is well formed. bool Verify() const; - /// describes - Return true if this subprogram provides debugging - /// information for the function F. + /// \brief Check if this provides debugging information for the function F. bool describes(const Function *F); - Function *getFunction() const { return getFunctionField(15); } - void replaceFunction(Function *F) { replaceFunctionField(15, F); } - DIArray getTemplateParams() const { return getFieldAs(16); } + Function *getFunction() const { return getFunctionField(5); } + void replaceFunction(Function *F) { replaceFunctionField(5, F); } + DIArray getTemplateParams() const { return getFieldAs(6); } DISubprogram getFunctionDeclaration() const { - return getFieldAs(17); + return getFieldAs(7); } MDNode *getVariablesNodes() const; DIArray getVariables() const; - /// getScopeLineNumber - Get the beginning of the scope of the - /// function, not necessarily where the name of the program - /// starts. - unsigned getScopeLineNumber() const { return getUnsignedField(19); } + unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } + /// \brief Check for the "private" access specifier. + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + /// \brief Check for the "protected" access specifier. + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + /// \brief Check for the "public" access specifier. + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + /// \brief Check for "explicit". + bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; } + /// \brief Check if this is prototyped. + bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; } + + /// \brief Check if this is reference-qualified. + /// + /// Return true if this subprogram is a C++11 reference-qualified non-static + /// member function (void foo() &). + unsigned isLValueReference() const { + return (getFlags() & FlagLValueReference) != 0; + } + + /// \brief Check if this is rvalue-reference-qualified. + /// + /// Return true if this subprogram is a C++11 rvalue-reference-qualified + /// non-static member function (void foo() &&). + unsigned isRValueReference() const { + return (getFlags() & FlagRValueReference) != 0; + } + }; -/// DILexicalBlock - This is a wrapper for a lexical block. +/// \brief This is a wrapper for a lexical block. class DILexicalBlock : public DIScope { public: explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} DIScope getContext() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } - unsigned getDiscriminator() const { return getUnsignedField(5); } + unsigned getLineNumber() const { + return getHeaderFieldAs(1); + } + unsigned getColumnNumber() const { + return getHeaderFieldAs(2); + } bool Verify() const; }; -/// DILexicalBlockFile - This is a wrapper for a lexical block with -/// a filename change. +/// \brief This is a wrapper for a lexical block with a filename change. class DILexicalBlockFile : public DIScope { public: explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} @@ -555,68 +701,63 @@ public: unsigned getLineNumber() const { return getScope().getLineNumber(); } unsigned getColumnNumber() const { return getScope().getColumnNumber(); } DILexicalBlock getScope() const { return getFieldAs(2); } + unsigned getDiscriminator() const { return getHeaderFieldAs(1); } bool Verify() const; }; -/// DINameSpace - A wrapper for a C++ style name space. +/// \brief A wrapper for a C++ style name space. class DINameSpace : public DIScope { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; public: explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { return getHeaderFieldAs(2); } DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - bool Verify() const; -}; - -/// DIUnspecifiedParameter - This is a wrapper for unspecified parameters. -class DIUnspecifiedParameter : public DIDescriptor { -public: - explicit DIUnspecifiedParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} bool Verify() const; }; -/// DITemplateTypeParameter - This is a wrapper for template type parameter. +/// \brief This is a wrapper for template type parameter. class DITemplateTypeParameter : public DIDescriptor { public: explicit DITemplateTypeParameter(const MDNode *N = nullptr) : DIDescriptor(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { return getHeaderFieldAs(2); } + unsigned getColumnNumber() const { return getHeaderFieldAs(3); } + DIScopeRef getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs(3); } - StringRef getFilename() const { return getFieldAs(4).getFilename(); } + DITypeRef getType() const { return getFieldAs(2); } + StringRef getFilename() const { return getFieldAs(3).getFilename(); } StringRef getDirectory() const { - return getFieldAs(4).getDirectory(); + return getFieldAs(3).getDirectory(); } - unsigned getLineNumber() const { return getUnsignedField(5); } - unsigned getColumnNumber() const { return getUnsignedField(6); } bool Verify() const; }; -/// DITemplateValueParameter - This is a wrapper for template value parameter. +/// \brief This is a wrapper for template value parameter. class DITemplateValueParameter : public DIDescriptor { public: explicit DITemplateValueParameter(const MDNode *N = nullptr) : DIDescriptor(N) {} + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { return getHeaderFieldAs(2); } + unsigned getColumnNumber() const { return getHeaderFieldAs(3); } + DIScopeRef getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DITypeRef getType() const { return getFieldAs(3); } - Value *getValue() const; - StringRef getFilename() const { return getFieldAs(5).getFilename(); } + DITypeRef getType() const { return getFieldAs(2); } + Metadata *getValue() const; + StringRef getFilename() const { return getFieldAs(4).getFilename(); } StringRef getDirectory() const { - return getFieldAs(5).getDirectory(); + return getFieldAs(4).getDirectory(); } - unsigned getLineNumber() const { return getUnsignedField(6); } - unsigned getColumnNumber() const { return getUnsignedField(7); } bool Verify() const; }; -/// DIGlobalVariable - This is a wrapper for a global variable. +/// \brief This is a wrapper for a global variable. class DIGlobalVariable : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -624,32 +765,30 @@ class DIGlobalVariable : public DIDescriptor { public: explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - StringRef getFilename() const { return getFieldAs(6).getFilename(); } + StringRef getName() const { return getHeaderField(1); } + StringRef getDisplayName() const { return getHeaderField(2); } + StringRef getLinkageName() const { return getHeaderField(3); } + unsigned getLineNumber() const { return getHeaderFieldAs(4); } + unsigned isLocalToUnit() const { return getHeaderFieldAs(5); } + unsigned isDefinition() const { return getHeaderFieldAs(6); } + + DIScope getContext() const { return getFieldAs(1); } + StringRef getFilename() const { return getFieldAs(2).getFilename(); } StringRef getDirectory() const { - return getFieldAs(6).getDirectory(); + return getFieldAs(2).getDirectory(); } + DITypeRef getType() const { return getFieldAs(3); } - unsigned getLineNumber() const { return getUnsignedField(7); } - DITypeRef getType() const { return getFieldAs(8); } - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } - - GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } - Constant *getConstant() const { return getConstantField(11); } + GlobalVariable *getGlobal() const { return getGlobalVariableField(4); } + Constant *getConstant() const { return getConstantField(4); } DIDerivedType getStaticDataMemberDeclaration() const { - return getFieldAs(12); + return getFieldAs(5); } - /// Verify - Verify that a global variable descriptor is well formed. bool Verify() const; }; -/// DIVariable - This is a wrapper for a variable (e.g. parameter, local, -/// global etc). +/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). class DIVariable : public DIDescriptor { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; @@ -657,73 +796,107 @@ class DIVariable : public DIDescriptor { public: explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIScope getContext() const { return getFieldAs(1); } - StringRef getName() const { return getStringField(2); } - DIFile getFile() const { return getFieldAs(3); } - unsigned getLineNumber() const { return (getUnsignedField(4) << 8) >> 8; } - unsigned getArgNumber() const { - unsigned L = getUnsignedField(4); - return L >> 24; + StringRef getName() const { return getHeaderField(1); } + unsigned getLineNumber() const { + // FIXME: Line number and arg number shouldn't be merged together like this. + return (getHeaderFieldAs(2) << 8) >> 8; } - DITypeRef getType() const { return getFieldAs(5); } + unsigned getArgNumber() const { return getHeaderFieldAs(2) >> 24; } + + DIScope getContext() const { return getFieldAs(1); } + DIFile getFile() const { return getFieldAs(2); } + DITypeRef getType() const { return getFieldAs(3); } - /// isArtificial - Return true if this variable is marked as "artificial". + /// \brief Return true if this variable is marked as "artificial". bool isArtificial() const { - return (getUnsignedField(6) & FlagArtificial) != 0; + return (getHeaderFieldAs(3) & FlagArtificial) != 0; } bool isObjectPointer() const { - return (getUnsignedField(6) & FlagObjectPointer) != 0; + return (getHeaderFieldAs(3) & FlagObjectPointer) != 0; } /// \brief Return true if this variable is represented as a pointer. bool isIndirect() const { - return (getUnsignedField(6) & FlagIndirectVariable) != 0; + return (getHeaderFieldAs(3) & FlagIndirectVariable) != 0; } - /// getInlinedAt - If this variable is inlined then return inline location. + /// \brief If this variable is inlined then return inline location. MDNode *getInlinedAt() const; - /// Verify - Verify that a variable descriptor is well formed. bool Verify() const; - /// HasComplexAddr - Return true if the variable has a complex address. - bool hasComplexAddress() const { return getNumAddrElements() > 0; } - - /// \brief Return the size of this variable's complex address or - /// zero if there is none. - unsigned getNumAddrElements() const { - if (DbgNode->getNumOperands() < 9) - return 0; - return getDescriptorField(8)->getNumOperands(); - } - - /// \brief return the Idx'th complex address element. - uint64_t getAddrElement(unsigned Idx) const; - - /// isBlockByrefVariable - Return true if the variable was declared as - /// a "__block" variable (Apple Blocks). + /// \brief Check if this is a "__block" variable (Apple Blocks). bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { return (getType().resolve(Map)).isBlockByrefStruct(); } - /// isInlinedFnArgument - Return true if this variable provides debugging - /// information for an inlined function arguments. + /// \brief Check if this is an inlined function argument. bool isInlinedFnArgument(const Function *CurFn); + /// \brief Return the size reported by the variable's type. + unsigned getSizeInBits(const DITypeIdentifierMap &Map); + void printExtendedName(raw_ostream &OS) const; }; -/// DILocation - This object holds location information. This object -/// is not associated with any DWARF tag. +/// \brief A complex location expression. +class DIExpression : public DIDescriptor { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + +public: + explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} + + bool Verify() const; + + /// \brief Return the number of elements in the complex expression. + unsigned getNumElements() const { + if (!DbgNode) + return 0; + unsigned N = getNumHeaderFields(); + assert(N > 0 && "missing tag"); + return N - 1; + } + + /// \brief return the Idx'th complex address element. + uint64_t getElement(unsigned Idx) const; + + /// \brief Return whether this is a piece of an aggregate variable. + bool isVariablePiece() const; + /// \brief Return the offset of this piece in bytes. + uint64_t getPieceOffset() const; + /// \brief Return the size of this piece in bytes. + uint64_t getPieceSize() const; +}; + +/// \brief This object holds location information. +/// +/// This object is not associated with any DWARF tag. class DILocation : public DIDescriptor { public: explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - unsigned getLineNumber() const { return getUnsignedField(0); } - unsigned getColumnNumber() const { return getUnsignedField(1); } - DIScope getScope() const { return getFieldAs(2); } - DILocation getOrigLocation() const { return getFieldAs(3); } + unsigned getLineNumber() const { + if (auto *L = dyn_cast_or_null(DbgNode)) + return L->getLine(); + return 0; + } + unsigned getColumnNumber() const { + if (auto *L = dyn_cast_or_null(DbgNode)) + return L->getColumn(); + return 0; + } + DIScope getScope() const { + if (auto *L = dyn_cast_or_null(DbgNode)) + return DIScope(dyn_cast_or_null(L->getScope())); + return DIScope(nullptr); + } + DILocation getOrigLocation() const { + if (auto *L = dyn_cast_or_null(DbgNode)) + return DILocation(dyn_cast_or_null(L->getInlinedAt())); + return DILocation(nullptr); + } StringRef getFilename() const { return getScope().getFilename(); } StringRef getDirectory() const { return getScope().getDirectory(); } bool Verify() const; @@ -731,23 +904,30 @@ public: return (getLineNumber() == Other.getLineNumber() && getFilename() == Other.getFilename()); } - /// getDiscriminator - DWARF discriminators are used to distinguish - /// identical file locations for instructions that are on different - /// basic blocks. If two instructions are inside the same lexical block - /// and are in different basic blocks, we create a new lexical block - /// with identical location as the original but with a different - /// discriminator value (lib/Transforms/Util/AddDiscriminators.cpp - /// for details). + /// \brief Get the DWAF discriminator. + /// + /// DWARF discriminators are used to distinguish identical file locations for + /// instructions that are on different basic blocks. If two instructions are + /// inside the same lexical block and are in different basic blocks, we + /// create a new lexical block with identical location as the original but + /// with a different discriminator value + /// (lib/Transforms/Util/AddDiscriminators.cpp for details). unsigned getDiscriminator() const { // Since discriminators are associated with lexical blocks, make // sure this location is a lexical block before retrieving its // value. - return getScope().isLexicalBlock() - ? getFieldAs(2).getDiscriminator() + return getScope().isLexicalBlockFile() + ? DILexicalBlockFile( + cast(cast(DbgNode)->getScope())) + .getDiscriminator() : 0; } + + /// \brief Generate a new discriminator value for this location. unsigned computeNewDiscriminator(LLVMContext &Ctx); - DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlock NewScope); + + /// \brief Return a copy of this location with a different scope. + DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope); }; class DIObjCProperty : public DIDescriptor { @@ -757,36 +937,38 @@ class DIObjCProperty : public DIDescriptor { public: explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} - StringRef getObjCPropertyName() const { return getStringField(1); } - DIFile getFile() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } + StringRef getObjCPropertyName() const { return getHeaderField(1); } + DIFile getFile() const { return getFieldAs(1); } + unsigned getLineNumber() const { return getHeaderFieldAs(2); } - StringRef getObjCPropertyGetterName() const { return getStringField(4); } - StringRef getObjCPropertySetterName() const { return getStringField(5); } + StringRef getObjCPropertyGetterName() const { return getHeaderField(3); } + StringRef getObjCPropertySetterName() const { return getHeaderField(4); } + unsigned getAttributes() const { return getHeaderFieldAs(5); } bool isReadOnlyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readonly) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0; } bool isReadWriteObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; } bool isAssignObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_assign) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0; } bool isRetainObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_retain) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0; } bool isCopyObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_copy) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0; } bool isNonAtomicObjCProperty() const { - return (getUnsignedField(6) & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; + return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; } - /// Objective-C doesn't have an ODR, so there is no benefit in storing + /// \brief Get the type. + /// + /// \note Objective-C doesn't have an ODR, so there is no benefit in storing /// the type as a DITypeRef here. - DIType getType() const { return getFieldAs(7); } + DIType getType() const { return getFieldAs(2); } - /// Verify - Verify that a derived type descriptor is well formed. bool Verify() const; }; @@ -799,47 +981,47 @@ public: explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs(1); } DIScopeRef getEntity() const { return getFieldAs(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - StringRef getName() const { return getStringField(4); } + unsigned getLineNumber() const { return getHeaderFieldAs(1); } + StringRef getName() const { return getHeaderField(2); } bool Verify() const; }; -/// getDISubprogram - Find subprogram that is enclosing this scope. +/// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); -/// getDICompositeType - Find underlying composite type. -DICompositeType getDICompositeType(DIType T); - -/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable -/// to hold function specific information. -NamedMDNode *getOrInsertFnSpecificMDNode(Module &M, DISubprogram SP); +/// \brief Find debug info for a given function. +/// \returns a valid DISubprogram, if found. Otherwise, it returns an empty +/// DISubprogram. +DISubprogram getDISubprogram(const Function *F); -/// getFnSpecificMDNode - Return a NameMDNode, if available, that is -/// suitable to hold function specific information. -NamedMDNode *getFnSpecificMDNode(const Module &M, DISubprogram SP); +/// \brief Find underlying composite type. +DICompositeType getDICompositeType(DIType T); -/// createInlinedVariable - Create a new inlined variable based on current -/// variable. +/// \brief Create a new inlined variable based on current variable. +/// /// @param DV Current Variable. /// @param InlinedScope Location at current variable is inlined. DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, LLVMContext &VMContext); -/// cleanseInlinedVariable - Remove inlined scope from the variable. +/// \brief Remove inlined scope from the variable. DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); -/// Construct DITypeIdentifierMap by going through retained types of each CU. +/// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); -/// Strip debug info in the module if it exists. +/// \brief Strip debug info in the module if it exists. +/// /// To do this, we remove all calls to the debugger intrinsics and any named /// metadata for debugging. We also remove debug locations for instructions. /// Return true if module is modified. bool StripDebugInfo(Module &M); -/// Return Debug Info Metadata Version by checking module flags. +/// \brief Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); +/// \brief Utility to find all debug info in a module. +/// /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To /// list debug info MDNodes used by an instruction, DebugInfoFinder uses /// processDeclare, processValue and processLocation to handle DbgDeclareInst, @@ -850,44 +1032,29 @@ class DebugInfoFinder { public: DebugInfoFinder() : TypeMapInitialized(false) {} - /// processModule - Process entire module and collect debug info - /// anchors. + /// \brief Process entire module and collect debug info anchors. void processModule(const Module &M); - /// processDeclare - Process DbgDeclareInst. + /// \brief Process DbgDeclareInst. void processDeclare(const Module &M, const DbgDeclareInst *DDI); - /// Process DbgValueInst. + /// \brief Process DbgValueInst. void processValue(const Module &M, const DbgValueInst *DVI); - /// processLocation - Process DILocation. + /// \brief Process DILocation. void processLocation(const Module &M, DILocation Loc); - /// Clear all lists. + /// \brief Clear all lists. void reset(); private: - /// Initialize TypeIdentifierMap. void InitializeTypeMap(const Module &M); - /// processType - Process DIType. void processType(DIType DT); - - /// processSubprogram - Process DISubprogram. void processSubprogram(DISubprogram SP); - void processScope(DIScope Scope); - - /// addCompileUnit - Add compile unit into CUs. bool addCompileUnit(DICompileUnit CU); - - /// addGlobalVariable - Add global variable into GVs. bool addGlobalVariable(DIGlobalVariable DIG); - - // addSubprogram - Add subprogram into SPs. bool addSubprogram(DISubprogram SP); - - /// addType - Add type into Tys. bool addType(DIType DT); - bool addScope(DIScope Scope); public: @@ -924,14 +1091,15 @@ public: unsigned scope_count() const { return Scopes.size(); } private: - SmallVector CUs; // Compile Units - SmallVector SPs; // Subprograms - SmallVector GVs; // Global Variables; - SmallVector TYs; // Types - SmallVector Scopes; // Scopes + SmallVector CUs; + SmallVector SPs; + SmallVector GVs; + SmallVector TYs; + SmallVector Scopes; SmallPtrSet NodesSeen; DITypeIdentifierMap TypeIdentifierMap; - /// Specify if TypeIdentifierMap is initialized. + + /// \brief Specify if TypeIdentifierMap is initialized. bool TypeMapInitialized; }; diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index 3d969a8..86e6441 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -15,51 +15,41 @@ #ifndef LLVM_IR_DEBUGLOC_H #define LLVM_IR_DEBUGLOC_H +#include "llvm/IR/TrackingMDRef.h" #include "llvm/Support/DataTypes.h" namespace llvm { - template struct DenseMapInfo; - class MDNode; + class LLVMContext; class raw_ostream; + class MDNode; /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, /// and MachineInstr to compactly encode file/line/scope information for an /// operation. class DebugLoc { - friend struct DenseMapInfo; - - /// getEmptyKey() - A private constructor that returns an unknown that is - /// not equal to the tombstone key or DebugLoc(). - static DebugLoc getEmptyKey() { - DebugLoc DL; - DL.LineCol = 1; - return DL; - } + TrackingMDNodeRef Loc; - /// getTombstoneKey() - A private constructor that returns an unknown that - /// is not equal to the empty key or DebugLoc(). - static DebugLoc getTombstoneKey() { - DebugLoc DL; - DL.LineCol = 2; - return DL; + public: + DebugLoc() {} + DebugLoc(DebugLoc &&X) : Loc(std::move(X.Loc)) {} + DebugLoc(const DebugLoc &X) : Loc(X.Loc) {} + DebugLoc &operator=(DebugLoc &&X) { + Loc = std::move(X.Loc); + return *this; + } + DebugLoc &operator=(const DebugLoc &X) { + Loc = X.Loc; + return *this; } - /// LineCol - This 32-bit value encodes the line and column number for the - /// location, encoded as 24-bits for line and 8 bits for col. A value of 0 - /// for either means unknown. - uint32_t LineCol; - - /// ScopeIdx - This is an opaque ID# for Scope/InlinedAt information, - /// decoded by LLVMContext. 0 is unknown. - int ScopeIdx; - public: - DebugLoc() : LineCol(0), ScopeIdx(0) {} // Defaults to unknown. + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } /// get - Get a new DebugLoc that corresponds to the specified line/col /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, - MDNode *Scope, MDNode *InlinedAt = nullptr); + static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, + MDNode *InlinedAt = nullptr); /// getFromDILocation - Translate the DILocation quad into a DebugLoc. static DebugLoc getFromDILocation(MDNode *N); @@ -68,56 +58,54 @@ namespace llvm { static DebugLoc getFromDILexicalBlock(MDNode *N); /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return ScopeIdx == 0; } + bool isUnknown() const { return !Loc; } - unsigned getLine() const { - return (LineCol << 8) >> 8; // Mask out column. - } - - unsigned getCol() const { - return LineCol >> 24; - } + unsigned getLine() const; + unsigned getCol() const; /// getScope - This returns the scope pointer for this DebugLoc, or null if /// invalid. - MDNode *getScope(const LLVMContext &Ctx) const; + MDNode *getScope() const; + MDNode *getScope(const LLVMContext &) const { return getScope(); } /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or /// null if invalid or not present. - MDNode *getInlinedAt(const LLVMContext &Ctx) const; + MDNode *getInlinedAt() const; + MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. + void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &Ctx) const; + const LLVMContext &) const { + return getScopeAndInlinedAt(Scope, IA); + } /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode(const LLVMContext &Ctx) const; + MDNode *getScopeNode() const; + MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } // getFnDebugLoc - Walk up the scope chain of given debug loc and find line // number info for the function. - DebugLoc getFnDebugLoc(const LLVMContext &Ctx) const; + DebugLoc getFnDebugLoc() const; + DebugLoc getFnDebugLoc(const LLVMContext &) const { + return getFnDebugLoc(); + } /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation compatible MDNode. - MDNode *getAsMDNode(const LLVMContext &Ctx) const; + MDNode *getAsMDNode() const; + MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } - bool operator==(const DebugLoc &DL) const { - return LineCol == DL.LineCol && ScopeIdx == DL.ScopeIdx; - } + bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } - void dump(const LLVMContext &Ctx) const; + void dump() const; + void dump(const LLVMContext &) const { dump(); } /// \brief prints source location /path/to/file.exe:line:col @[inlined at] - void print(const LLVMContext &Ctx, raw_ostream &OS) const; + void print(raw_ostream &OS) const; + void print(const LLVMContext &, raw_ostream &OS) const { print(OS); } }; - template <> - struct DenseMapInfo { - static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } - static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } - static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } - }; } // end namespace llvm #endif /* LLVM_SUPPORT_DEBUGLOC_H */ diff --git a/include/llvm/IR/DerivedTypes.h b/include/llvm/IR/DerivedTypes.h index ff15087..182015c 100644 --- a/include/llvm/IR/DerivedTypes.h +++ b/include/llvm/IR/DerivedTypes.h @@ -123,6 +123,9 @@ public: typedef Type::subtype_iterator param_iterator; param_iterator param_begin() const { return ContainedTys + 1; } param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + ArrayRef params() const { + return makeArrayRef(param_begin(), param_end()); + } /// Parameter type accessors. Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } @@ -204,9 +207,6 @@ class StructType : public CompositeType { /// void *SymbolTableEntry; public: - ~StructType() { - delete [] ContainedTys; // Delete the body. - } /// StructType::create - This creates an identified struct. static StructType *create(LLVMContext &Context, StringRef Name); @@ -221,7 +221,7 @@ public: StringRef Name, bool isPacked = false); static StructType *create(LLVMContext &Context, ArrayRef Elements); - static StructType *create(StringRef Name, Type *elt1, ...) END_WITH_NULL; + static StructType *create(StringRef Name, Type *elt1, ...) LLVM_END_WITH_NULL; /// StructType::get - This static method is the primary way to create a /// literal StructType. @@ -236,7 +236,7 @@ public: /// structure types by specifying the elements as arguments. Note that this /// method always returns a non-packed struct, and requires at least one /// element type. - static StructType *get(Type *elt1, ...) END_WITH_NULL; + static StructType *get(Type *elt1, ...) LLVM_END_WITH_NULL; bool isPacked() const { return (getSubclassData() & SCDB_Packed) != 0; } @@ -249,7 +249,7 @@ public: bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; } /// isSized - Return true if this is a sized type. - bool isSized(SmallPtrSet *Visited = nullptr) const; + bool isSized(SmallPtrSetImpl *Visited = nullptr) const; /// hasName - Return true if this is a named struct that has a non-empty name. bool hasName() const { return SymbolTableEntry != nullptr; } @@ -266,7 +266,7 @@ public: /// setBody - Specify a body for an opaque identified type. void setBody(ArrayRef Elements, bool isPacked = false); - void setBody(Type *elt1, ...) END_WITH_NULL; + void setBody(Type *elt1, ...) LLVM_END_WITH_NULL; /// isValidElementType - Return true if the specified type is valid as a /// element type. @@ -277,6 +277,9 @@ public: typedef Type::subtype_iterator element_iterator; element_iterator element_begin() const { return ContainedTys; } element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef const elements() const { + return makeArrayRef(element_begin(), element_end()); + } /// isLayoutIdentical - Return true if this is layout identical to the /// specified struct. diff --git a/include/llvm/IR/DiagnosticInfo.h b/include/llvm/IR/DiagnosticInfo.h index 9c9f236..c6a8854 100644 --- a/include/llvm/IR/DiagnosticInfo.h +++ b/include/llvm/IR/DiagnosticInfo.h @@ -12,12 +12,13 @@ // Diagnostics reporting is still done as part of the LLVMContext. //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_DIAGNOSTICINFO_H -#define LLVM_SUPPORT_DIAGNOSTICINFO_H +#ifndef LLVM_IR_DIAGNOSTICINFO_H +#define LLVM_IR_DIAGNOSTICINFO_H #include "llvm-c/Core.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" namespace llvm { @@ -44,8 +45,10 @@ enum DiagnosticSeverity { /// \brief Defines the different supported kind of a diagnostic. /// This enum should be extended with a new ID for each added concrete subclass. enum DiagnosticKind { + DK_Bitcode, DK_InlineAsm, DK_StackSize, + DK_Linker, DK_DebugMetadataVersion, DK_SampleProfile, DK_OptimizationRemark, @@ -95,6 +98,8 @@ public: virtual void print(DiagnosticPrinter &DP) const = 0; }; +typedef std::function DiagnosticHandlerFunction; + /// Diagnostic information for inline asm reporting. /// This is basically a message and an optional location. class DiagnosticInfoInlineAsm : public DiagnosticInfo { @@ -324,7 +329,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; /// Diagnostic information for missed-optimization remarks. @@ -350,7 +355,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; /// Diagnostic information for optimization analysis remarks. @@ -377,7 +382,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; // Create wrappers for C Binding types (see CBindingWrapping.h). @@ -432,7 +437,7 @@ public: } /// \see DiagnosticInfoOptimizationBase::isEnabled. - virtual bool isEnabled() const override; + bool isEnabled() const override; }; /// Emit a warning when loop vectorization is specified but fails. \p Fn is the diff --git a/include/llvm/IR/DiagnosticPrinter.h b/include/llvm/IR/DiagnosticPrinter.h index 411c781..db5779a 100644 --- a/include/llvm/IR/DiagnosticPrinter.h +++ b/include/llvm/IR/DiagnosticPrinter.h @@ -13,8 +13,8 @@ // on their needs. //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_DIAGNOSTICPRINTER_H -#define LLVM_SUPPORT_DIAGNOSTICPRINTER_H +#ifndef LLVM_IR_DIAGNOSTICPRINTER_H +#define LLVM_IR_DIAGNOSTICPRINTER_H #include diff --git a/include/llvm/IR/Dominators.h b/include/llvm/IR/Dominators.h index e2d1ccc..c1f208e 100644 --- a/include/llvm/IR/Dominators.h +++ b/include/llvm/IR/Dominators.h @@ -31,6 +31,11 @@ namespace llvm { +// FIXME: Replace this brittle forward declaration with the include of the new +// PassManager.h when doing so doesn't break the PassManagerBuilder. +template class AnalysisManager; +class PreservedAnalyses; + EXTERN_TEMPLATE_INSTANTIATION(class DomTreeNodeBase); EXTERN_TEMPLATE_INSTANTIATION(class DominatorTreeBase); @@ -69,6 +74,13 @@ public: DominatorTree() : DominatorTreeBase(false) {} + DominatorTree(DominatorTree &&Arg) + : Base(std::move(static_cast(Arg))) {} + DominatorTree &operator=(DominatorTree &&RHS) { + Base::operator=(std::move(static_cast(RHS))); + return *this; + } + /// \brief Returns *false* if the other dominator tree matches this dominator /// tree. inline bool compare(const DominatorTree &Other) const { @@ -155,6 +167,43 @@ template <> struct GraphTraits }; /// \brief Analysis pass which computes a \c DominatorTree. +class DominatorTreeAnalysis { +public: + /// \brief Provide the result typedef for this analysis pass. + typedef DominatorTree Result; + + /// \brief Opaque, unique identifier for this analysis pass. + static void *ID() { return (void *)&PassID; } + + /// \brief Run the analysis pass over a function and produce a dominator tree. + DominatorTree run(Function &F); + + /// \brief Provide access to a name for this pass for debugging purposes. + static StringRef name() { return "DominatorTreeAnalysis"; } + +private: + static char PassID; +}; + +/// \brief Printer pass for the \c DominatorTree. +class DominatorTreePrinterPass { + raw_ostream &OS; + +public: + explicit DominatorTreePrinterPass(raw_ostream &OS); + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreePrinterPass"; } +}; + +/// \brief Verifier pass for the \c DominatorTree. +struct DominatorTreeVerifierPass { + PreservedAnalyses run(Function &F, AnalysisManager *AM); + + static StringRef name() { return "DominatorTreeVerifierPass"; } +}; + +/// \brief Legacy analysis pass which computes a \c DominatorTree. class DominatorTreeWrapperPass : public FunctionPass { DominatorTree DT; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index ad4b139..5140328 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -87,11 +87,14 @@ private: ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes - // HasLazyArguments is stored in Value::SubclassData. - /*bool HasLazyArguments;*/ - - // The Calling Convention is stored in Value::SubclassData. - /*CallingConv::ID CallingConvention;*/ + /* + * Value::SubclassData + * + * bit 0 : HasLazyArguments + * bit 1 : HasPrefixData + * bit 2 : HasPrologueData + * bit 3-6: CallingConvention + */ friend class SymbolTableListTraits; @@ -102,7 +105,7 @@ private: /// needs it. The hasLazyArguments predicate returns true if the arg list /// hasn't been set up yet. bool hasLazyArguments() const { - return getSubclassDataFromValue() & 1; + return getSubclassDataFromValue() & (1<<0); } void CheckLazyArguments() const { if (hasLazyArguments()) @@ -143,6 +146,9 @@ public: /// arguments. bool isVarArg() const; + bool isMaterializable() const; + void setIsMaterializable(bool V); + /// getIntrinsicID - This method returns the ID number of the specified /// function, or Intrinsic::not_intrinsic if the function is not an /// intrinsic, or if the pointer is null. This value is always defined to be @@ -159,11 +165,11 @@ public: /// calling convention of this function. The enum values for the known /// calling conventions are defined in CallingConv.h. CallingConv::ID getCallingConv() const { - return static_cast(getSubclassDataFromValue() >> 2); + return static_cast(getSubclassDataFromValue() >> 3); } void setCallingConv(CallingConv::ID CC) { - setValueSubclassData((getSubclassDataFromValue() & 3) | - (static_cast(CC) << 2)); + setValueSubclassData((getSubclassDataFromValue() & 7) | + (static_cast(CC) << 3)); } /// @brief Return the attribute list for this Function. @@ -445,12 +451,19 @@ public: bool arg_empty() const; bool hasPrefixData() const { - return getSubclassDataFromValue() & 2; + return getSubclassDataFromValue() & (1<<1); } Constant *getPrefixData() const; void setPrefixData(Constant *PrefixData); + bool hasPrologueData() const { + return getSubclassDataFromValue() & (1<<2); + } + + Constant *getPrologueData() const; + void setPrologueData(Constant *PrologueData); + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index a1216a1..6f57dc2 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -19,11 +19,13 @@ #define LLVM_IR_GVMATERIALIZER_H #include +#include namespace llvm { class Function; class GlobalValue; class Module; +class StructType; class GVMaterializer { protected: @@ -32,17 +34,13 @@ protected: public: virtual ~GVMaterializer(); - /// True if GV can be materialized from whatever backing store this - /// GVMaterializer uses and has not been materialized yet. - virtual bool isMaterializable(const GlobalValue *GV) const = 0; - /// True if GV has been materialized and can be dematerialized back to /// whatever backing store this GVMaterializer uses. virtual bool isDematerializable(const GlobalValue *GV) const = 0; /// Make sure the given GlobalValue is fully read. /// - virtual std::error_code Materialize(GlobalValue *GV) = 0; + virtual std::error_code materialize(GlobalValue *GV) = 0; /// If the given GlobalValue is read in, and if the GVMaterializer supports /// it, release the memory for the GV, and set it up to be materialized @@ -55,7 +53,7 @@ public: /// virtual std::error_code MaterializeModule(Module *M) = 0; - virtual void releaseBuffer() = 0; + virtual std::vector getIdentifiedStructTypes() const = 0; }; } // End llvm namespace diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 2e042f4..546fea2 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -1,4 +1,4 @@ -//===-- llvm/GlobalObject.h - Class to represent a global object *- C++ -*-===// +//===-- llvm/GlobalObject.h - Class to represent global objects -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -35,12 +35,24 @@ protected: std::string Section; // Section to emit this into, empty means default Comdat *ObjComdat; + static const unsigned AlignmentBits = 5; + static const unsigned GlobalObjectSubClassDataBits = + GlobalValueSubClassDataBits - AlignmentBits; + +private: + static const unsigned AlignmentMask = (1 << AlignmentBits) - 1; + public: unsigned getAlignment() const { - return (1u << getGlobalValueSubClassData()) >> 1; + unsigned Data = getGlobalValueSubClassData(); + unsigned AlignmentData = Data & AlignmentMask; + return (1u << AlignmentData) >> 1; } void setAlignment(unsigned Align); + unsigned getGlobalObjectSubClassData() const; + void setGlobalObjectSubClassData(unsigned Val); + bool hasSection() const { return !StringRef(getSection()).empty(); } const char *getSection() const { return Section.c_str(); } void setSection(StringRef S); diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 68e410b..d0f7e9a 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -20,6 +20,7 @@ #include "llvm/IR/Constant.h" #include "llvm/IR/DerivedTypes.h" +#include namespace llvm { @@ -84,6 +85,7 @@ private: // (19 + 3 + 2 + 1 + 2 + 5) == 32. unsigned SubClassData : 19; protected: + static const unsigned GlobalValueSubClassDataBits = 19; unsigned getGlobalValueSubClassData() const { return SubClassData; } @@ -246,6 +248,7 @@ public: bool hasLinkOnceLinkage() const { return isLinkOnceLinkage(Linkage); } + bool hasLinkOnceODRLinkage() const { return isLinkOnceODRLinkage(Linkage); } bool hasWeakLinkage() const { return isWeakLinkage(Linkage); } @@ -309,7 +312,7 @@ public: /// Make sure this GlobalValue is fully read. If the module is corrupt, this /// returns true and fills in the optional string with information about the /// problem. If successful, this returns false. - bool Materialize(std::string *ErrInfo = nullptr); + std::error_code materialize(); /// If this GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized @@ -325,6 +328,13 @@ public: /// the current translation unit. bool isDeclaration() const; + bool isDeclarationForLinker() const { + if (hasAvailableExternallyLinkage()) + return true; + + return isDeclaration(); + } + /// This method unlinks 'this' from the containing module, but does not delete /// it. virtual void removeFromParent() = 0; diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index aed2463..e5f62fb 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -28,7 +28,7 @@ #include "llvm/Support/CBindingWrapping.h" namespace llvm { - class MDNode; +class MDNode; /// \brief This provides the default implementation of the IRBuilder /// 'InsertHelper' method that is called whenever an instruction is created by @@ -364,43 +364,60 @@ public: /// \brief Create and insert a memset to the specified pointer and the /// specified value. /// - /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr) { - return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create and insert a memcpy between the specified pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr) { + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag, - TBAAStructTag); + TBAAStructTag, ScopeTag, NoAliasTag); } CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, bool isVolatile = false, MDNode *TBAATag = nullptr, - MDNode *TBAAStructTag = nullptr); + MDNode *TBAAStructTag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create and insert a memmove between the specified /// pointers. /// /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. + /// specified, it will be added to the instruction. Likewise with alias.scope + /// and noalias tags. CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr) { - return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr) { + return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, + TBAATag, ScopeTag, NoAliasTag); } CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = nullptr); + bool isVolatile = false, MDNode *TBAATag = nullptr, + MDNode *ScopeTag = nullptr, + MDNode *NoAliasTag = nullptr); /// \brief Create a lifetime.start intrinsic. /// @@ -412,7 +429,46 @@ public: /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); + /// \brief Create a call to Masked Load intrinsic + CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, + Value *PassThru = 0, const Twine &Name = ""); + + /// \brief Create a call to Masked Store intrinsic + CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, + Value *Mask); + + /// \brief Create an assume intrinsic call that allows the optimizer to + /// assume that the provided condition will be true. + CallInst *CreateAssumption(Value *Cond); + + /// \brief Create a call to the experimental.gc.statepoint intrinsic to + /// start a new statepoint sequence. + CallInst *CreateGCStatepoint(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.result intrinsic to extract + /// the result from a call wrapped in a statepoint. + CallInst *CreateGCResult(Instruction *Statepoint, + Type *ResultType, + const Twine &Name = ""); + + /// \brief Create a call to the experimental.gc.relocate intrinsics to + /// project the relocated value of one pointer from the statepoint. + CallInst *CreateGCRelocate(Instruction *Statepoint, + int BaseOffset, + int DerivedOffset, + Type *ResultType, + const Twine &Name = ""); + private: + /// \brief Create a call to a masked intrinsic with given Id. + /// Masked intrinsic has only one overloaded type - data type. + CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef Ops, + Type *DataTy, const Twine &Name = ""); + Value *getCastedInt8PtrValue(Value *Ptr); }; @@ -429,7 +485,7 @@ private: /// The first template argument handles whether or not to preserve names in the /// final instruction output. This defaults to on. The second template argument /// specifies a class to use for creating constants. This defaults to creating -/// minimally folded constants. The fourth template argument allows clients to +/// minimally folded constants. The third template argument allows clients to /// specify custom insertion hooks that are called on every newly created /// insertion. template()), + return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, None), Name); } InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, @@ -1226,6 +1281,18 @@ public: return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); } + + Value *CreateBitOrPointerCast(Value *V, Type *DestTy, + const Twine &Name = "") { + if (V->getType() == DestTy) + return V; + if (V->getType()->isPointerTy() && DestTy->isIntegerTy()) + return CreatePtrToInt(V, DestTy, Name); + if (V->getType()->isIntegerTy() && DestTy->isPointerTy()) + return CreateIntToPtr(V, DestTy, Name); + + return CreateBitCast(V, DestTy, Name); + } private: // \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the @@ -1508,6 +1575,44 @@ public: } return V; } + + /// \brief Create an assume intrinsic call that represents an alignment + /// assumption on the provided pointer. + /// + /// An optional offset can be provided, and if it is provided, the offset + /// must be subtracted from the provided pointer to get the pointer with the + /// specified alignment. + CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, + unsigned Alignment, + Value *OffsetValue = nullptr) { + assert(isa(PtrValue->getType()) && + "trying to create an alignment assumption on a non-pointer?"); + + PointerType *PtrTy = cast(PtrValue->getType()); + Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace()); + Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + Value *Mask = ConstantInt::get(IntPtrTy, + Alignment > 0 ? Alignment - 1 : 0); + if (OffsetValue) { + bool IsOffsetZero = false; + if (ConstantInt *CI = dyn_cast(OffsetValue)) + IsOffsetZero = CI->isZero(); + + if (!IsOffsetZero) { + if (OffsetValue->getType() != IntPtrTy) + OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true, + "offsetcast"); + PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr"); + } + } + + Value *Zero = ConstantInt::get(IntPtrTy, 0); + Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr"); + Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond"); + + return CreateAssumption(InvCond); + } }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 2f78c83..7f2027b 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -16,8 +16,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_IR_PRINTING_PASSES_H -#define LLVM_IR_IR_PRINTING_PASSES_H +#ifndef LLVM_IR_IRPRINTINGPASSES_H +#define LLVM_IR_IRPRINTINGPASSES_H #include "llvm/ADT/StringRef.h" #include @@ -58,7 +58,7 @@ public: PrintModulePass(); PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Module *M); + PreservedAnalyses run(Module &M); static StringRef name() { return "PrintModulePass"; } }; @@ -75,7 +75,7 @@ public: PrintFunctionPass(); PrintFunctionPass(raw_ostream &OS, const std::string &Banner = ""); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Function &F); static StringRef name() { return "PrintFunctionPass"; } }; diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index ac19089..b2d79d0 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -25,12 +25,9 @@ namespace llvm { class PointerType; class FunctionType; class Module; + struct InlineAsmKeyType; -template -class ConstantUniqueMap; -template -struct ConstantCreator; +template class ConstantUniqueMap; class InlineAsm : public Value { public: @@ -40,9 +37,8 @@ public: }; private: - friend struct ConstantCreator; - friend class ConstantUniqueMap; + friend struct InlineAsmKeyType; + friend class ConstantUniqueMap; InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 981aad8..030f5d6 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -29,8 +29,8 @@ class LLVMContext; // TerminatorInst Class //===----------------------------------------------------------------------===// -/// TerminatorInst - Subclasses of this class are all able to terminate a basic -/// block. Thus, these are all the flow control type of operations. +/// Subclasses of this class are all able to terminate a basic +/// block. Thus, these are all the flow control type of operations. /// class TerminatorInst : public Instruction { protected: @@ -51,23 +51,19 @@ protected: virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; virtual unsigned getNumSuccessorsV() const = 0; virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; - TerminatorInst *clone_impl() const override = 0; public: - /// getNumSuccessors - Return the number of successors that this terminator - /// has. + /// Return the number of successors that this terminator has. unsigned getNumSuccessors() const { return getNumSuccessorsV(); } - /// getSuccessor - Return the specified successor. - /// + /// Return the specified successor. BasicBlock *getSuccessor(unsigned idx) const { return getSuccessorV(idx); } - /// setSuccessor - Update the specified successor to point at the provided - /// block. + /// Update the specified successor to point at the provided block. void setSuccessor(unsigned idx, BasicBlock *B) { setSuccessorV(idx, B); } @@ -153,7 +149,7 @@ public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); - /// Create() - Construct a binary instruction, given the opcode and the two + /// Construct a binary instruction, given the opcode and the two /// operands. Optionally (if InstBefore is specified) insert the instruction /// into a BasicBlock right before the specified instruction. The specified /// Instruction is allowed to be a dereferenced end iterator. @@ -162,14 +158,14 @@ public: const Twine &Name = Twine(), Instruction *InsertBefore = nullptr); - /// Create() - Construct a binary instruction, given the opcode and the two + /// Construct a binary instruction, given the opcode and the two /// operands. Also automatically insert this instruction to the end of the /// BasicBlock specified. /// static BinaryOperator *Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); - /// Create* - These methods just forward to Create, and are useful when you + /// These methods just forward to Create, and are useful when you /// statically know what type of instruction you're going to create. These /// helpers just save some typing. #define HANDLE_BINARY_INST(N, OPC, CLASS) \ @@ -281,8 +277,7 @@ public: /// Helper functions to construct and inspect unary operations (NEG and NOT) /// via binary operators SUB and XOR: /// - /// CreateNeg, CreateNot - Create the NEG and NOT - /// instructions out of SUB and XOR instructions. + /// Create the NEG and NOT instructions out of SUB and XOR instructions. /// static BinaryOperator *CreateNeg(Value *Op, const Twine &Name = "", Instruction *InsertBefore = nullptr); @@ -305,16 +300,14 @@ public: static BinaryOperator *CreateNot(Value *Op, const Twine &Name, BasicBlock *InsertAtEnd); - /// isNeg, isFNeg, isNot - Check if the given Value is a - /// NEG, FNeg, or NOT instruction. + /// Check if the given Value is a NEG, FNeg, or NOT instruction. /// static bool isNeg(const Value *V); static bool isFNeg(const Value *V, bool IgnoreZeroSign=false); static bool isNot(const Value *V); - /// getNegArgument, getNotArgument - Helper functions to extract the - /// unary argument of a NEG, FNEG or NOT operation implemented via - /// Sub, FSub, or Xor. + /// Helper functions to extract the unary argument of a NEG, FNEG or NOT + /// operation implemented via Sub, FSub, or Xor. /// static const Value *getNegArgument(const Value *BinOp); static Value *getNegArgument( Value *BinOp); @@ -327,37 +320,42 @@ public: return static_cast(Instruction::getOpcode()); } - /// swapOperands - Exchange the two operands to this instruction. + /// Exchange the two operands to this instruction. /// This instruction is safe to use on any binary instruction and /// does not modify the semantics of the instruction. If the instruction /// cannot be reversed (ie, it's a Div), then return true. /// bool swapOperands(); - /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. + /// Set or clear the nsw flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. void setHasNoUnsignedWrap(bool b = true); - /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. + /// Set or clear the nsw flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. void setHasNoSignedWrap(bool b = true); - /// setIsExact - Set or clear the exact flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. + /// Set or clear the exact flag on this instruction, which must be an operator + /// which supports this flag. See LangRef.html for the meaning of this flag. void setIsExact(bool b = true); - /// hasNoUnsignedWrap - Determine whether the no unsigned wrap flag is set. + /// Determine whether the no unsigned wrap flag is set. bool hasNoUnsignedWrap() const; - /// hasNoSignedWrap - Determine whether the no signed wrap flag is set. + /// Determine whether the no signed wrap flag is set. bool hasNoSignedWrap() const; - /// isExact - Determine whether the exact flag is set. + /// Determine whether the exact flag is set. bool isExact() const; + /// Convenience method to copy supported wrapping, exact, and fast-math flags + /// from V to this instruction. + void copyIRFlags(const Value *V); + + /// Logical 'and' of any supported wrapping, exact, and fast-math flags of + /// V and this instruction. + void andIRFlags(const Value *V); + // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Instruction *I) { return I->isBinaryOp(); @@ -378,7 +376,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryOperator, Value) // CastInst Class //===----------------------------------------------------------------------===// -/// CastInst - This is the base class for all instructions that perform data +/// This is the base class for all instructions that perform data /// casts. It is simply provided so that instruction category testing /// can be performed with code like: /// @@ -491,6 +489,19 @@ public: Instruction *InsertBefore = 0 ///< Place to insert the instruction ); + /// @brief Create a BitCast, a PtrToInt, or an IntToPTr cast instruction. + /// + /// If the value is a pointer type and the destination an integer type, + /// creates a PtrToInt cast. If the value is an integer type and the + /// destination a pointer type, creates an IntToPtr cast. Otherwise, creates + /// a bitcast. + static CastInst *CreateBitOrPointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + Type *Ty, ///< The type to which cast should be made + const Twine &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. static CastInst *CreateIntegerCast( Value *S, ///< The pointer value to be casted (operand 0) @@ -553,6 +564,17 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast, inttoptr, or ptrtoint cast between these + /// types is valid and a no-op. + /// + /// This ensures that any pointer<->integer cast has enough bits in the + /// integer and any other cast is a bitcast. + static bool isBitOrNoopPointerCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy, ///< The Type to which the value should be cast. + const DataLayout *Layout = 0 ///< Optional DataLayout. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. /// @brief Infer the opcode for cast operand and type diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index bac6a95..ba7791c 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -25,6 +25,7 @@ namespace llvm { class FastMathFlags; class LLVMContext; class MDNode; +struct AAMDNodes; template class SymbolTableListTraits; @@ -155,19 +156,25 @@ public: /// getAllMetadata - Get all metadata attached to this Instruction. The first /// element of each pair returned is the KindID, the second element is the /// metadata value. This list is returned sorted by the KindID. - void getAllMetadata(SmallVectorImpl > &MDs)const{ + void + getAllMetadata(SmallVectorImpl> &MDs) const { if (hasMetadata()) getAllMetadataImpl(MDs); } /// getAllMetadataOtherThanDebugLoc - This does the same thing as /// getAllMetadata, except that it filters out the debug location. - void getAllMetadataOtherThanDebugLoc(SmallVectorImpl > &MDs) const { + void getAllMetadataOtherThanDebugLoc( + SmallVectorImpl> &MDs) const { if (hasMetadataOtherThanDebugLoc()) getAllMetadataOtherThanDebugLocImpl(MDs); } + /// getAAMetadata - Fills the AAMDNodes structure with AA metadata from + /// this instruction. When Merge is true, the existing AA metadata is + /// merged with that from this instruction providing the most-general result. + void getAAMetadata(AAMDNodes &N, bool Merge = false) const; + /// setMetadata - Set the metadata of the specified kind to the specified /// node. This updates/replaces metadata if already present, or removes it if /// Node is null. @@ -179,7 +186,7 @@ public: /// convenience method for passes to do so. void dropUnknownMetadata(ArrayRef KnownIDs); void dropUnknownMetadata() { - return dropUnknownMetadata(ArrayRef()); + return dropUnknownMetadata(None); } void dropUnknownMetadata(unsigned ID1) { return dropUnknownMetadata(makeArrayRef(ID1)); @@ -189,6 +196,10 @@ public: return dropUnknownMetadata(IDs); } + /// setAAMetadata - Sets the metadata on this instruction from the + /// AAMDNodes structure. + void setAAMetadata(const AAMDNodes &N); + /// setDebugLoc - Set the debug location information for this instruction. void setDebugLoc(const DebugLoc &Loc) { DbgLoc = Loc; } @@ -220,11 +231,16 @@ public: /// this flag. void setHasAllowReciprocal(bool B); - /// Convenience function for setting all the fast-math flags on this + /// Convenience function for setting multiple fast-math flags on this /// instruction, which must be an operator which supports these flags. See - /// LangRef.html for the meaning of these flats. + /// LangRef.html for the meaning of these flags. void setFastMathFlags(FastMathFlags FMF); + /// Convenience function for transferring all fast-math flag values to this + /// instruction, which must be an operator which supports these flags. See + /// LangRef.html for the meaning of these flags. + void copyFastMathFlags(FastMathFlags FMF); + /// Determine whether the unsafe-algebra flag is set. bool hasUnsafeAlgebra() const; @@ -242,7 +258,7 @@ public: /// Convenience function for getting all the fast-math flags, which must be an /// operator which supports these flags. See LangRef.html for the meaning of - /// these flats. + /// these flags. FastMathFlags getFastMathFlags() const; /// Copy I's fast-math flags @@ -258,9 +274,10 @@ private: // These are all implemented in Metadata.cpp. MDNode *getMetadataImpl(unsigned KindID) const; MDNode *getMetadataImpl(StringRef Kind) const; - void getAllMetadataImpl(SmallVectorImpl > &)const; - void getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl > &) const; + void + getAllMetadataImpl(SmallVectorImpl> &) const; + void getAllMetadataOtherThanDebugLocImpl( + SmallVectorImpl> &) const; void clearMetadataHashEntries(); public: //===--------------------------------------------------------------------===// @@ -323,6 +340,11 @@ public: return mayReadFromMemory() || mayWriteToMemory(); } + /// isAtomic - Return true if this instruction has an + /// AtomicOrdering of unordered or higher. + /// + bool isAtomic() const; + /// mayThrow - Return true if this instruction may throw an exception. /// bool mayThrow() const; diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 308467f..045e51e 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -17,8 +17,8 @@ #define LLVM_IR_INSTRUCTIONS_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/DerivedTypes.h" @@ -50,6 +50,22 @@ enum SynchronizationScope { CrossThread = 1 }; +/// Returns true if the ordering is at least as strong as acquire +/// (i.e. acquire, acq_rel or seq_cst) +inline bool isAtLeastAcquire(AtomicOrdering Ord) { + return (Ord == Acquire || + Ord == AcquireRelease || + Ord == SequentiallyConsistent); +} + +/// Returns true if the ordering is at least as strong as release +/// (i.e. release, acq_rel or seq_cst) +inline bool isAtLeastRelease(AtomicOrdering Ord) { +return (Ord == Release || + Ord == AcquireRelease || + Ord == SequentiallyConsistent); +} + //===----------------------------------------------------------------------===// // AllocaInst Class //===----------------------------------------------------------------------===// @@ -119,7 +135,7 @@ public: return getSubclassDataFromInstruction() & 32; } - /// \brief Specify whether this alloca is used to represent a the arguments to + /// \brief Specify whether this alloca is used to represent the arguments to /// a call. void setUsedWithInAlloca(bool V) { setInstructionSubclassData((getSubclassDataFromInstruction() & ~32) | @@ -225,7 +241,6 @@ public: (xthread << 6)); } - bool isAtomic() const { return getOrdering() != NotAtomic; } void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope = CrossThread) { setOrdering(Ordering); @@ -345,7 +360,6 @@ public: (xthread << 6)); } - bool isAtomic() const { return getOrdering() != NotAtomic; } void setAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope = CrossThread) { setOrdering(Ordering); @@ -637,7 +651,7 @@ public: Sub, /// *p = old & v And, - /// *p = ~old & v + /// *p = ~(old & v) Nand, /// *p = old | v Or, diff --git a/include/llvm/IR/IntrinsicInst.h b/include/llvm/IR/IntrinsicInst.h index e053f78..c227ea0 100644 --- a/include/llvm/IR/IntrinsicInst.h +++ b/include/llvm/IR/IntrinsicInst.h @@ -28,6 +28,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Metadata.h" namespace llvm { /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic @@ -81,7 +82,14 @@ namespace llvm { class DbgDeclareInst : public DbgInfoIntrinsic { public: Value *getAddress() const; - MDNode *getVariable() const { return cast(getArgOperand(1)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(1))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -102,7 +110,14 @@ namespace llvm { return cast( const_cast(getArgOperand(1)))->getZExtValue(); } - MDNode *getVariable() const { return cast(getArgOperand(2)); } + MDNode *getVariable() const { + return cast( + cast(getArgOperand(2))->getMetadata()); + } + MDNode *getExpression() const { + return cast( + cast(getArgOperand(3))->getMetadata()); + } // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const IntrinsicInst *I) { @@ -320,6 +335,33 @@ namespace llvm { Value *getSrc() const { return const_cast(getArgOperand(1)); } }; + /// This represents the llvm.instrprof_increment intrinsic. + class InstrProfIncrementInst : public IntrinsicInst { + public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::instrprof_increment; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } + + GlobalVariable *getName() const { + return cast( + const_cast(getArgOperand(0))->stripPointerCasts()); + } + + ConstantInt *getHash() const { + return cast(const_cast(getArgOperand(1))); + } + + ConstantInt *getNumCounters() const { + return cast(const_cast(getArgOperand(2))); + } + + ConstantInt *getIndex() const { + return cast(const_cast(getArgOperand(3))); + } + }; } #endif diff --git a/include/llvm/IR/Intrinsics.h b/include/llvm/IR/Intrinsics.h index b0d746b..56d1e4a 100644 --- a/include/llvm/IR/Intrinsics.h +++ b/include/llvm/IR/Intrinsics.h @@ -28,10 +28,9 @@ class LLVMContext; class Module; class AttributeSet; -/// Intrinsic Namespace - This namespace contains an enum with a value for -/// every intrinsic/builtin function known by LLVM. These enum values are -/// returned by Function::getIntrinsicID(). -/// +/// This namespace contains an enum with a value for every intrinsic/builtin +/// function known by LLVM. The enum values are returned by +/// Function::getIntrinsicID(). namespace Intrinsic { enum ID { not_intrinsic = 0, // Must be zero @@ -43,25 +42,21 @@ namespace Intrinsic { , num_intrinsics }; - /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as - /// "llvm.ppc.altivec.lvx". + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". std::string getName(ID id, ArrayRef Tys = None); - /// Intrinsic::getType(ID) - Return the function type for an intrinsic. - /// + /// Return the function type for an intrinsic. FunctionType *getType(LLVMContext &Context, ID id, ArrayRef Tys = None); - /// Intrinsic::isOverloaded(ID) - Returns true if the intrinsic can be - /// overloaded. + /// Returns true if the intrinsic can be overloaded. bool isOverloaded(ID id); - /// Intrinsic::getAttributes(ID) - Return the attributes for an intrinsic. - /// + /// Return the attributes for an intrinsic. AttributeSet getAttributes(LLVMContext &C, ID id); - /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function - /// declaration for an intrinsic, and return it. + /// Create or insert an LLVM Function declaration for an intrinsic, and return + /// it. /// /// The Tys parameter is for intrinsics with overloaded types (e.g., those /// using iAny, fAny, vAny, or iPTRAny). For a declaration of an overloaded @@ -75,14 +70,14 @@ namespace Intrinsic { /// Map a MS builtin name to an intrinsic ID. ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); - /// IITDescriptor - This is a type descriptor which explains the type - /// requirements of an intrinsic. This is returned by - /// getIntrinsicInfoTableEntries. + /// This is a type descriptor which explains the type requirements of an + /// intrinsic. This is returned by getIntrinsicInfoTableEntries. struct IITDescriptor { enum IITDescriptorKind { Void, VarArg, MMX, Metadata, Half, Float, Double, Integer, Vector, Pointer, Struct, - Argument, ExtendArgument, TruncArgument, HalfVecArgument + Argument, ExtendArgument, TruncArgument, HalfVecArgument, + SameVecWidthArgument, PtrToArgument } Kind; union { @@ -102,13 +97,15 @@ namespace Intrinsic { }; unsigned getArgumentNumber() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument); return Argument_Info >> 2; } ArgKind getArgumentKind() const { assert(Kind == Argument || Kind == ExtendArgument || - Kind == TruncArgument || Kind == HalfVecArgument); - return (ArgKind)(Argument_Info&3); + Kind == TruncArgument || Kind == HalfVecArgument || + Kind == SameVecWidthArgument || Kind == PtrToArgument); + return (ArgKind)(Argument_Info & 3); } static IITDescriptor get(IITDescriptorKind K, unsigned Field) { @@ -117,9 +114,8 @@ namespace Intrinsic { } }; - /// getIntrinsicInfoTableEntries - Return the IIT table descriptor for the - /// specified intrinsic into an array of IITDescriptors. - /// + /// Return the IIT table descriptor for the specified intrinsic into an array + /// of IITDescriptors. void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl &T); } // End Intrinsic namespace diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index 0b8f64f..a1188bc 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -112,6 +112,11 @@ class LLVMMatchType // the intrinsic is overloaded, so the matched type should be declared as iAny. class LLVMExtendedType : LLVMMatchType; class LLVMTruncatedType : LLVMMatchType; +class LLVMVectorSameWidth + : LLVMMatchType { + ValueType ElTy = elty.VT; +} +class LLVMPointerTo : LLVMMatchType; // Match the type of another intrinsic parameter that is expected to be a // vector type, but change the element count to be half as many @@ -254,6 +259,10 @@ def int_gcwrite : Intrinsic<[], // def int_returnaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; def int_frameaddress : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty], [IntrNoMem]>; +def int_frameallocate : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; +def int_framerecover : Intrinsic<[llvm_ptr_ty], + [llvm_ptr_ty, llvm_ptr_ty], + [IntrNoMem]>; def int_read_register : Intrinsic<[llvm_anyint_ty], [llvm_metadata_ty], [IntrNoMem], "llvm.read_register">; def int_write_register : Intrinsic<[], [llvm_metadata_ty, llvm_anyint_ty], @@ -277,12 +286,22 @@ def int_pcmarker : Intrinsic<[], [llvm_i32_ty]>; def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; +// The assume intrinsic is marked as arbitrarily writing so that proper +// control dependencies will be maintained. +def int_assume : Intrinsic<[], [llvm_i1_ty], []>; + // Stack Protector Intrinsic - The stackprotector intrinsic writes the stack // guard to the correct place on the stack frame. def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_stackprotectorcheck : Intrinsic<[], [llvm_ptrptr_ty], [IntrReadWriteArgMem]>; +// A counter increment for instrumentation based profiling. +def int_instrprof_increment : Intrinsic<[], + [llvm_ptr_ty, llvm_i64_ty, + llvm_i32_ty, llvm_i32_ty], + []>; + //===------------------- Standard C Library Intrinsics --------------------===// // @@ -324,6 +343,8 @@ let Properties = [IntrNoMem] in { def int_exp : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_exp2 : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; def int_fabs : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; + def int_minnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; + def int_maxnum : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_copysign : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>]>; def int_floor : Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>]>; @@ -369,9 +390,12 @@ let Properties = [IntrNoMem] in { // places. let Properties = [IntrNoMem] in { def int_dbg_declare : Intrinsic<[], - [llvm_metadata_ty, llvm_metadata_ty]>; + [llvm_metadata_ty, + llvm_metadata_ty, + llvm_metadata_ty]>; def int_dbg_value : Intrinsic<[], [llvm_metadata_ty, llvm_i64_ty, + llvm_metadata_ty, llvm_metadata_ty]>; } @@ -476,11 +500,29 @@ def int_experimental_stackmap : Intrinsic<[], def int_experimental_patchpoint_void : Intrinsic<[], [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, - llvm_vararg_ty]>; + llvm_vararg_ty], + [Throws]>; def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i32_ty, llvm_ptr_ty, llvm_i32_ty, - llvm_vararg_ty]>; + llvm_vararg_ty], + [Throws]>; + + +//===------------------------ Garbage Collection Intrinsics ---------------===// +// These are documented in docs/Statepoint.rst + +def int_experimental_gc_statepoint : Intrinsic<[llvm_i32_ty], + [llvm_anyptr_ty, llvm_i32_ty, + llvm_i32_ty, llvm_vararg_ty]>; + +def int_experimental_gc_result_int : Intrinsic<[llvm_anyint_ty], [llvm_i32_ty]>; +def int_experimental_gc_result_float : Intrinsic<[llvm_anyfloat_ty], + [llvm_i32_ty]>; +def int_experimental_gc_result_ptr : Intrinsic<[llvm_anyptr_ty], [llvm_i32_ty]>; + +def int_experimental_gc_relocate : Intrinsic<[llvm_anyptr_ty], + [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty]>; //===-------------------------- Other Intrinsics --------------------------===// // @@ -528,6 +570,17 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], def int_clear_cache : Intrinsic<[], [llvm_ptr_ty, llvm_ptr_ty], [], "llvm.clear_cache">; +//===-------------------------- Masked Intrinsics -------------------------===// +// +def int_masked_store : Intrinsic<[], [llvm_anyvector_ty, LLVMPointerTo<0>, + llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>], + [IntrReadWriteArgMem]>; + +def int_masked_load : Intrinsic<[llvm_anyvector_ty], + [LLVMPointerTo<0>, llvm_i32_ty, + LLVMVectorSameWidth<0, llvm_i1_ty>, LLVMMatchType<0>], + [IntrReadArgMem]>; //===----------------------------------------------------------------------===// // Target-specific intrinsics //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index a02d707..ce758e2 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -20,8 +20,13 @@ let TargetPrefix = "arm" in { // All intrinsics start with "llvm.arm.". def int_arm_thread_pointer : GCCBuiltin<"__builtin_thread_pointer">, Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; +// A space-consuming intrinsic primarily for testing ARMConstantIslands. The +// first argument is the number of bytes this "instruction" takes up, the second +// and return value are essentially chains, used to force ordering during ISel. +def int_arm_space : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], []>; + //===----------------------------------------------------------------------===// -// Saturating Arithmentic +// Saturating Arithmetic def int_arm_qadd : GCCBuiltin<"__builtin_arm_qadd">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], @@ -132,6 +137,7 @@ def int_arm_crc32cw : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], // HINT def int_arm_hint : Intrinsic<[], [llvm_i32_ty]>; +def int_arm_dbg : Intrinsic<[], [llvm_i32_ty]>; //===----------------------------------------------------------------------===// // RBIT @@ -340,10 +346,6 @@ def int_arm_neon_vqneg : Neon_1Arg_Intrinsic; // Vector Count Leading Sign/Zero Bits. def int_arm_neon_vcls : Neon_1Arg_Intrinsic; -def int_arm_neon_vclz : Neon_1Arg_Intrinsic; - -// Vector Count One Bits. -def int_arm_neon_vcnt : Neon_1Arg_Intrinsic; // Vector Reciprocal Estimate. def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index cd51284..9deed41 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -797,24 +797,30 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType; // (space)i64* // Generated within nvvm. Use for ldu on sm_20 or later def int_nvvm_ldu_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.i">; def int_nvvm_ldu_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.f">; def int_nvvm_ldu_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldu.global.p">; // Generated within nvvm. Use for ldg on sm_35 or later def int_nvvm_ldg_global_i : Intrinsic<[llvm_anyint_ty], - [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.i">; def int_nvvm_ldg_global_f : Intrinsic<[llvm_anyfloat_ty], - [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.f">; def int_nvvm_ldg_global_p : Intrinsic<[llvm_anyptr_ty], - [LLVMAnyPointerType>], [IntrReadMem, NoCapture<0>], + [LLVMAnyPointerType>, llvm_i32_ty], + [IntrReadMem, NoCapture<0>], "llvm.nvvm.ldg.global.p">; // Use for generic pointers diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 49ddfb8..5cdabde 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -28,8 +28,10 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". def int_ppc_dcbz : Intrinsic<[], [llvm_ptr_ty], []>; def int_ppc_dcbzl : Intrinsic<[], [llvm_ptr_ty], []>; - // sync instruction + // sync instruction (i.e. sync 0, a.k.a hwsync) def int_ppc_sync : Intrinsic<[], [], []>; + // lwsync is sync 1 + def int_ppc_lwsync : Intrinsic<[], [], []>; // Intrinsics used to generate ctr-based loops. These should only be // generated by the PowerPC backend! @@ -45,6 +47,13 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". list properties> : GCCBuiltin, Intrinsic; + + /// PowerPC_VSX_Intrinsic - Base class for all VSX intrinsics. + class PowerPC_VSX_Intrinsic ret_types, + list param_types, + list properties> + : GCCBuiltin, + Intrinsic; } //===----------------------------------------------------------------------===// @@ -87,6 +96,32 @@ class PowerPC_Vec_WWW_Intrinsic //===----------------------------------------------------------------------===// +// PowerPC VSX Intrinsic Class Definitions. +// + +/// PowerPC_VSX_Vec_DDD_Intrinsic - A PowerPC intrinsic that takes two v2f64 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_VSX_Vec_DDD_Intrinsic + : PowerPC_VSX_Intrinsic; + +/// PowerPC_VSX_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_VSX_Vec_FFF_Intrinsic + : PowerPC_VSX_Intrinsic; + +/// PowerPC_VSX_Sca_DDD_Intrinsic - A PowerPC intrinsic that takes two f64 +/// scalars and returns one. These intrinsics have no side effects. +class PowerPC_VSX_Sca_DDD_Intrinsic + : PowerPC_VSX_Intrinsic; + + +//===----------------------------------------------------------------------===// // PowerPC Altivec Intrinsic Definitions. let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". @@ -474,3 +509,36 @@ def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">; def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; + + +//===----------------------------------------------------------------------===// +// PowerPC VSX Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + +// Vector load. +def int_ppc_vsx_lxvw4x : + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty], [IntrReadArgMem]>; +def int_ppc_vsx_lxvd2x : + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty], [IntrReadArgMem]>; + +// Vector store. +def int_ppc_vsx_stxvw4x : + Intrinsic<[], [llvm_v4i32_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>; +def int_ppc_vsx_stxvd2x : + Intrinsic<[], [llvm_v2f64_ty, llvm_ptr_ty], [IntrReadWriteArgMem]>; + +// Vector and scalar maximum. +def int_ppc_vsx_xvmaxdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmaxdp">; +def int_ppc_vsx_xvmaxsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvmaxsp">; +def int_ppc_vsx_xsmaxdp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmaxdp">; + +// Vector and scalar minimum. +def int_ppc_vsx_xvmindp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvmindp">; +def int_ppc_vsx_xvminsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvminsp">; +def int_ppc_vsx_xsmindp : PowerPC_VSX_Sca_DDD_Intrinsic<"xsmindp">; + +// Vector divide. +def int_ppc_vsx_xvdivdp : PowerPC_VSX_Vec_DDD_Intrinsic<"xvdivdp">; +def int_ppc_vsx_xvdivsp : PowerPC_VSX_Vec_FFF_Intrinsic<"xvdivsp">; +} diff --git a/include/llvm/IR/IntrinsicsR600.td b/include/llvm/IR/IntrinsicsR600.td index ba69eaa..5055667 100644 --- a/include/llvm/IR/IntrinsicsR600.td +++ b/include/llvm/IR/IntrinsicsR600.td @@ -33,10 +33,14 @@ defm int_r600_read_tgid : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tgid">; defm int_r600_read_tidig : R600ReadPreloadRegisterIntrinsic_xyz < "__builtin_r600_read_tidig">; - } // End TargetPrefix = "r600" let TargetPrefix = "AMDGPU" in { + +class AMDGPUReadPreloadRegisterIntrinsic + : Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>, + GCCBuiltin; + def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, // 1st parameter: Numerator // 2nd parameter: Denominator @@ -48,7 +52,7 @@ def int_AMDGPU_div_scale : GCCBuiltin<"__builtin_amdgpu_div_scale">, def int_AMDGPU_div_fmas : GCCBuiltin<"__builtin_amdgpu_div_fmas">, Intrinsic<[llvm_anyfloat_ty], - [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], + [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty], [IntrNoMem]>; def int_AMDGPU_div_fixup : GCCBuiltin<"__builtin_amdgpu_div_fixup">, @@ -69,4 +73,13 @@ def int_AMDGPU_rsq : GCCBuiltin<"__builtin_amdgpu_rsq">, def int_AMDGPU_rsq_clamped : GCCBuiltin<"__builtin_amdgpu_rsq_clamped">, Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; +def int_AMDGPU_ldexp : GCCBuiltin<"__builtin_amdgpu_ldexp">, + Intrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i32_ty], [IntrNoMem]>; + +def int_AMDGPU_class : GCCBuiltin<"__builtin_amdgpu_class">, + Intrinsic<[llvm_i1_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; + +def int_AMDGPU_read_workdim : AMDGPUReadPreloadRegisterIntrinsic < + "__builtin_amdgpu_read_workdim">; + } // End TargetPrefix = "AMDGPU" diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 5de9508..81c7290 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -886,7 +886,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector insert let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_insertps : GCCBuiltin<"__builtin_ia32_insertps128">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; } @@ -896,13 +896,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_v16i8_ty], [IntrNoMem]>; def int_x86_sse41_pblendw : GCCBuiltin<"__builtin_ia32_pblendw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty], + Intrinsic<[llvm_v8i16_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_sse41_blendpd : GCCBuiltin<"__builtin_ia32_blendpd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i32_ty], + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_sse41_blendps : GCCBuiltin<"__builtin_ia32_blendps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i32_ty], + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_sse41_blendvpd : GCCBuiltin<"__builtin_ia32_blendvpd">, Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_v2f64_ty], @@ -915,17 +915,17 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". // Vector dot product let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_dppd : GCCBuiltin<"__builtin_ia32_dppd">, - Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty,llvm_i32_ty], + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem, Commutative]>; def int_x86_sse41_dpps : GCCBuiltin<"__builtin_ia32_dpps">, - Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty,llvm_i32_ty], + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem, Commutative]>; } // Vector sum of absolute differences let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_sse41_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw128">, - Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i32_ty], + Intrinsic<[llvm_v8i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty,llvm_i8_ty], [IntrNoMem, Commutative]>; } @@ -1171,10 +1171,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, - llvm_v4f64_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; def int_x86_avx_blendv_pd_256 : GCCBuiltin<"__builtin_ia32_blendvpd256">, Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; @@ -1187,7 +1187,7 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx_dp_ps_256 : GCCBuiltin<"__builtin_ia32_dpps256">, Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, - llvm_v8f32_ty, llvm_i32_ty], [IntrNoMem]>; + llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; } // Vector compare @@ -1389,6 +1389,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". GCCBuiltin<"__builtin_ia32_storeupd512_mask">, Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_store_ss : + GCCBuiltin<"__builtin_ia32_storess_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrReadWriteArgMem]>; } //===----------------------------------------------------------------------===// @@ -1580,6 +1584,44 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psrl_dq_bs : GCCBuiltin<"__builtin_ia32_psrldqi256_byteshift">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_pslli_d : GCCBuiltin<"__builtin_ia32_pslldi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pslli_q : GCCBuiltin<"__builtin_ia32_psllqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrli_d : GCCBuiltin<"__builtin_ia32_psrldi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrli_q : GCCBuiltin<"__builtin_ia32_psrlqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrai_d : GCCBuiltin<"__builtin_ia32_psradi512">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrai_q : GCCBuiltin<"__builtin_ia32_psraqi512">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psll_d : GCCBuiltin<"__builtin_ia32_pslld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psll_q : GCCBuiltin<"__builtin_ia32_psllq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_d : GCCBuiltin<"__builtin_ia32_psrld512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_d : GCCBuiltin<"__builtin_ia32_psrad512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v4i32_ty, llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psra_q : GCCBuiltin<"__builtin_ia32_psraq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v2i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Pack ops. @@ -1706,13 +1748,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v32i8_ty], [IntrNoMem]>; def int_x86_avx2_pblendw : GCCBuiltin<"__builtin_ia32_pblendw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty], [IntrNoMem]>; def int_x86_avx2_pblendd_128 : GCCBuiltin<"__builtin_ia32_pblendd128">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty], [IntrNoMem]>; def int_x86_avx2_pblendd_256 : GCCBuiltin<"__builtin_ia32_pblendd256">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, - llvm_i32_ty], [IntrNoMem]>; + llvm_i8_ty], [IntrNoMem]>; } // Vector load with broadcast @@ -1787,6 +1829,23 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_vinserti128 : GCCBuiltin<"__builtin_ia32_insert128i256">, Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_vextractf32x4_512 : + GCCBuiltin<"__builtin_ia32_extractf32x4_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i8_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vextracti32x4_512 : + GCCBuiltin<"__builtin_ia32_extracti32x4_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v16i32_ty, llvm_i8_ty, + llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vextractf64x4_512 : + GCCBuiltin<"__builtin_ia32_extractf64x4_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v8f64_ty, llvm_i8_ty, + llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_vextracti64x4_512 : + GCCBuiltin<"__builtin_ia32_extracti64x4_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v8i64_ty, llvm_i8_ty, + llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Conditional load ops @@ -1871,6 +1930,31 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psrav_d_256 : GCCBuiltin<"__builtin_ia32_psrav8si">, Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_psllv_d : GCCBuiltin<"__builtin_ia32_psllv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psllv_q : GCCBuiltin<"__builtin_ia32_psllv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_d : GCCBuiltin<"__builtin_ia32_psrav16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrav_q : GCCBuiltin<"__builtin_ia32_psrav8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_d : GCCBuiltin<"__builtin_ia32_psrlv16si_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, + llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_psrlv_q : GCCBuiltin<"__builtin_ia32_psrlv8di_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, + llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; } // Gather ops @@ -1951,11 +2035,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v32i8_ty], [IntrNoMem]>; def int_x86_avx2_mpsadbw : GCCBuiltin<"__builtin_ia32_mpsadbw256">, Intrinsic<[llvm_v16i16_ty], [llvm_v32i8_ty, llvm_v32i8_ty, - llvm_i32_ty], [IntrNoMem, Commutative]>; + llvm_i8_ty], [IntrNoMem, Commutative]>; def int_x86_avx2_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa256">, Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty], [IntrReadMem]>; - def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, - Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } //===----------------------------------------------------------------------===// @@ -1986,13 +2068,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512">, + def int_x86_fma_mask_vfmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_fma_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512">, + def int_x86_fma_mask_vfmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfmsub_ss : GCCBuiltin<"__builtin_ia32_vfmsubss">, Intrinsic<[llvm_v4f32_ty], @@ -2018,13 +2122,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512">, + def int_x86_fma_mask_vfmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512">, + def int_x86_fma_mask_vfmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfnmadd_ss : GCCBuiltin<"__builtin_ia32_vfnmaddss">, Intrinsic<[llvm_v4f32_ty], @@ -2050,13 +2176,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512">, + def int_x86_fma_mask_vfnmadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmaddps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512">, + def int_x86_fma_mask_vfnmadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfnmsub_ss : GCCBuiltin<"__builtin_ia32_vfnmsubss">, Intrinsic<[llvm_v4f32_ty], @@ -2082,13 +2230,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512">, + def int_x86_fma_mask_vfnmsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfnmsubps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_fma_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512">, + def int_x86_fma_mask_vfnmsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfnmsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfnmsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfnmsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfnmsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfnmsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfnmsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfmaddsub_ps : GCCBuiltin<"__builtin_ia32_vfmaddsubps">, Intrinsic<[llvm_v4f32_ty], @@ -2108,13 +2278,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512">, + def int_x86_fma_mask_vfmaddsub_ps_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_ps_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512">, + def int_x86_fma_mask_vfmaddsub_pd_512 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_256 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmaddsub_pd_128 : GCCBuiltin<"__builtin_ia32_vfmaddsubpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; def int_x86_fma_vfmsubadd_ps : GCCBuiltin<"__builtin_ia32_vfmsubaddps">, Intrinsic<[llvm_v4f32_ty], @@ -2134,13 +2326,35 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty], [IntrNoMem]>; - def int_x86_fma_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512">, + def int_x86_fma_mask_vfmsubadd_ps_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddps512_mask">, Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty], + [llvm_v16f32_ty, llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_ps_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddps256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; - def int_x86_fma_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512">, + def int_x86_fma_mask_vfmsubadd_ps_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddps128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_512 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd512_mask">, Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty], + [llvm_v8f64_ty, llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_256 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], + [IntrNoMem]>; + def int_x86_fma_mask_vfmsubadd_pd_128 : GCCBuiltin<"__builtin_ia32_vfmsubaddpd128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; } @@ -2749,6 +2963,30 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". } //===----------------------------------------------------------------------===// +// ADX + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_addcarryx_u32: GCCBuiltin<"__builtin_ia32_addcarryx_u32">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_addcarryx_u64: GCCBuiltin<"__builtin_ia32_addcarryx_u64">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_addcarry_u32: GCCBuiltin<"__builtin_ia32_addcarry_u32">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_addcarry_u64: GCCBuiltin<"__builtin_ia32_addcarry_u64">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_subborrow_u32: GCCBuiltin<"__builtin_ia32_subborrow_u32">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; + def int_x86_subborrow_u64: GCCBuiltin<"__builtin_ia32_subborrow_u64">, + Intrinsic<[llvm_i8_ty], [llvm_i8_ty, llvm_i64_ty, llvm_i64_ty, + llvm_ptr_ty], [IntrReadWriteArgMem]>; +} + +//===----------------------------------------------------------------------===// // RTM intrinsics. Transactional Memory support. let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". @@ -2955,10 +3193,12 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty], [IntrNoMem]>; - def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512">, - Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty], [IntrNoMem]>; - def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512">, - Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_pd_512 : GCCBuiltin<"__builtin_ia32_sqrtpd512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_sqrt_ps_512 : GCCBuiltin<"__builtin_ia32_sqrtps512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; def int_x86_avx512_rsqrt14_ss : GCCBuiltin<"__builtin_ia32_rsqrt14ss_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, @@ -2993,6 +3233,13 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx512_rcp28_pd : GCCBuiltin<"__builtin_ia32_rcp28pd_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_exp2_ps : GCCBuiltin<"__builtin_ia32_exp2ps_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_exp2_pd : GCCBuiltin<"__builtin_ia32_exp2pd_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_rcp28_ss : GCCBuiltin<"__builtin_ia32_rcp28ss_mask">, Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty, llvm_i32_ty], @@ -3167,10 +3414,26 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_256 : GCCBuiltin<"__builtin_ia32_blendmps_256_mask">, + Intrinsic<[llvm_v8f32_ty], + [llvm_v8f32_ty, llvm_v8f32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_ps_128 : GCCBuiltin<"__builtin_ia32_blendmps_128_mask">, + Intrinsic<[llvm_v4f32_ty], + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_pd_512 : GCCBuiltin<"__builtin_ia32_blendmpd_512_mask">, Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_256 : GCCBuiltin<"__builtin_ia32_blendmpd_256_mask">, + Intrinsic<[llvm_v4f64_ty], + [llvm_v4f64_ty, llvm_v4f64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_pd_128 : GCCBuiltin<"__builtin_ia32_blendmpd_128_mask">, + Intrinsic<[llvm_v2f64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty, llvm_i8_ty], + [IntrNoMem]>; def int_x86_avx512_mask_blend_d_512 : GCCBuiltin<"__builtin_ia32_blendmd_512_mask">, Intrinsic<[llvm_v16i32_ty], @@ -3180,8 +3443,428 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_256 : GCCBuiltin<"__builtin_ia32_blendmd_256_mask">, + Intrinsic<[llvm_v8i32_ty], + [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_256 : GCCBuiltin<"__builtin_ia32_blendmq_256_mask">, + Intrinsic<[llvm_v4i64_ty], + [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_d_128 : GCCBuiltin<"__builtin_ia32_blendmd_128_mask">, + Intrinsic<[llvm_v4i32_ty], + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_q_128 : GCCBuiltin<"__builtin_ia32_blendmq_128_mask">, + Intrinsic<[llvm_v2i64_ty], + [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_blend_w_512 : GCCBuiltin<"__builtin_ia32_blendmw_512_mask">, + Intrinsic<[llvm_v32i16_ty], + [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_256 : GCCBuiltin<"__builtin_ia32_blendmw_256_mask">, + Intrinsic<[llvm_v16i16_ty], + [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_w_128 : GCCBuiltin<"__builtin_ia32_blendmw_128_mask">, + Intrinsic<[llvm_v8i16_ty], + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_512 : GCCBuiltin<"__builtin_ia32_blendmb_512_mask">, + Intrinsic<[llvm_v64i8_ty], + [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_256 : GCCBuiltin<"__builtin_ia32_blendmb_256_mask">, + Intrinsic<[llvm_v32i8_ty], + [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_blend_b_128 : GCCBuiltin<"__builtin_ia32_blendmb_128_mask">, + Intrinsic<[llvm_v16i8_ty], + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + +} + +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_valign_q_512 : GCCBuiltin<"__builtin_ia32_alignq512_mask">, + Intrinsic<[llvm_v8i64_ty], + [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_valign_d_512 : GCCBuiltin<"__builtin_ia32_alignd512_mask">, + Intrinsic<[llvm_v16i32_ty], + [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i8_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; } +// Compares +let TargetPrefix = "x86" in { + // 512-bit + def int_x86_avx512_mask_pcmpeq_b_512 : GCCBuiltin<"__builtin_ia32_pcmpeqb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_w_512 : GCCBuiltin<"__builtin_ia32_pcmpeqw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pcmpgt_b_512: GCCBuiltin<"__builtin_ia32_pcmpgtb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_w_512: GCCBuiltin<"__builtin_ia32_pcmpgtw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_d_512: GCCBuiltin<"__builtin_ia32_pcmpgtd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_q_512: GCCBuiltin<"__builtin_ia32_pcmpgtq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cmp_b_512: GCCBuiltin<"__builtin_ia32_cmpb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_w_512: GCCBuiltin<"__builtin_ia32_cmpw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_d_512: GCCBuiltin<"__builtin_ia32_cmpd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem ]>; + def int_x86_avx512_mask_cmp_q_512: GCCBuiltin<"__builtin_ia32_cmpq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_ucmp_b_512: GCCBuiltin<"__builtin_ia32_ucmpb512_mask">, + Intrinsic<[llvm_i64_ty], [llvm_v64i8_ty, llvm_v64i8_ty, llvm_i32_ty, + llvm_i64_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_w_512: GCCBuiltin<"__builtin_ia32_ucmpw512_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i16_ty, llvm_v32i16_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_d_512: GCCBuiltin<"__builtin_ia32_ucmpd512_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_q_512: GCCBuiltin<"__builtin_ia32_ucmpq512_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + // 256-bit + def int_x86_avx512_mask_pcmpeq_b_256 : GCCBuiltin<"__builtin_ia32_pcmpeqb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_w_256 : GCCBuiltin<"__builtin_ia32_pcmpeqw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_d_256 : GCCBuiltin<"__builtin_ia32_pcmpeqd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_q_256 : GCCBuiltin<"__builtin_ia32_pcmpeqq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pcmpgt_b_256: GCCBuiltin<"__builtin_ia32_pcmpgtb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_w_256: GCCBuiltin<"__builtin_ia32_pcmpgtw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_d_256: GCCBuiltin<"__builtin_ia32_pcmpgtd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_q_256: GCCBuiltin<"__builtin_ia32_pcmpgtq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cmp_b_256: GCCBuiltin<"__builtin_ia32_cmpb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_w_256: GCCBuiltin<"__builtin_ia32_cmpw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_d_256: GCCBuiltin<"__builtin_ia32_cmpd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_q_256: GCCBuiltin<"__builtin_ia32_cmpq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_ucmp_b_256: GCCBuiltin<"__builtin_ia32_ucmpb256_mask">, + Intrinsic<[llvm_i32_ty], [llvm_v32i8_ty, llvm_v32i8_ty, llvm_i32_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_w_256: GCCBuiltin<"__builtin_ia32_ucmpw256_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i16_ty, llvm_v16i16_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_d_256: GCCBuiltin<"__builtin_ia32_ucmpd256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i32_ty, llvm_v8i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_q_256: GCCBuiltin<"__builtin_ia32_ucmpq256_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i64_ty, llvm_v4i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + // 128-bit + def int_x86_avx512_mask_pcmpeq_b_128 : GCCBuiltin<"__builtin_ia32_pcmpeqb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_w_128 : GCCBuiltin<"__builtin_ia32_pcmpeqw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_d_128 : GCCBuiltin<"__builtin_ia32_pcmpeqd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpeq_q_128 : GCCBuiltin<"__builtin_ia32_pcmpeqq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_pcmpgt_b_128: GCCBuiltin<"__builtin_ia32_pcmpgtb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_w_128: GCCBuiltin<"__builtin_ia32_pcmpgtw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_d_128: GCCBuiltin<"__builtin_ia32_pcmpgtd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i8_ty], + [IntrNoMem]>; + def int_x86_avx512_mask_pcmpgt_q_128: GCCBuiltin<"__builtin_ia32_pcmpgtq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i8_ty], + [IntrNoMem]>; + + def int_x86_avx512_mask_cmp_b_128: GCCBuiltin<"__builtin_ia32_cmpb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_w_128: GCCBuiltin<"__builtin_ia32_cmpw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_d_128: GCCBuiltin<"__builtin_ia32_cmpd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_cmp_q_128: GCCBuiltin<"__builtin_ia32_cmpq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_ucmp_b_128: GCCBuiltin<"__builtin_ia32_ucmpb128_mask">, + Intrinsic<[llvm_i16_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_w_128: GCCBuiltin<"__builtin_ia32_ucmpw128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v8i16_ty, llvm_v8i16_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_d_128: GCCBuiltin<"__builtin_ia32_ucmpd128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v4i32_ty, llvm_v4i32_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_ucmp_q_128: GCCBuiltin<"__builtin_ia32_ucmpq128_mask">, + Intrinsic<[llvm_i8_ty], [llvm_v2i64_ty, llvm_v2i64_ty, llvm_i32_ty, + llvm_i8_ty], [IntrNoMem]>; +} + +// Compress, Expand +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_compress_ps_512 : + GCCBuiltin<"__builtin_ia32_compresssf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_512 : + GCCBuiltin<"__builtin_ia32_compressdf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_256 : + GCCBuiltin<"__builtin_ia32_compresssf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_256 : + GCCBuiltin<"__builtin_ia32_compressdf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_ps_128 : + GCCBuiltin<"__builtin_ia32_compresssf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_pd_128 : + GCCBuiltin<"__builtin_ia32_compressdf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_ps_512 : + GCCBuiltin<"__builtin_ia32_compressstoresf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_512 : + GCCBuiltin<"__builtin_ia32_compressstoredf512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_256 : + GCCBuiltin<"__builtin_ia32_compressstoresf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_256 : + GCCBuiltin<"__builtin_ia32_compressstoredf256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_ps_128 : + GCCBuiltin<"__builtin_ia32_compressstoresf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_pd_128 : + GCCBuiltin<"__builtin_ia32_compressstoredf128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + + def int_x86_avx512_mask_compress_d_512 : + GCCBuiltin<"__builtin_ia32_compresssi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_512 : + GCCBuiltin<"__builtin_ia32_compressdi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_256 : + GCCBuiltin<"__builtin_ia32_compresssi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_256 : + GCCBuiltin<"__builtin_ia32_compressdi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_d_128 : + GCCBuiltin<"__builtin_ia32_compresssi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_compress_q_128 : + GCCBuiltin<"__builtin_ia32_compressdi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_compress_store_d_512 : + GCCBuiltin<"__builtin_ia32_compressstoresi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_512 : + GCCBuiltin<"__builtin_ia32_compressstoredi512_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_256 : + GCCBuiltin<"__builtin_ia32_compressstoresi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_256 : + GCCBuiltin<"__builtin_ia32_compressstoredi256_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_d_128 : + GCCBuiltin<"__builtin_ia32_compressstoresi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + def int_x86_avx512_mask_compress_store_q_128 : + GCCBuiltin<"__builtin_ia32_compressstoredi128_mask">, + Intrinsic<[], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadWriteArgMem]>; + +// expand + def int_x86_avx512_mask_expand_ps_512 : + GCCBuiltin<"__builtin_ia32_expandsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_v16f32_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_512 : + GCCBuiltin<"__builtin_ia32_expanddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_v8f64_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_256 : + GCCBuiltin<"__builtin_ia32_expandsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_v8f32_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_256 : + GCCBuiltin<"__builtin_ia32_expanddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_v4f64_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_ps_128 : + GCCBuiltin<"__builtin_ia32_expandsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_pd_128 : + GCCBuiltin<"__builtin_ia32_expanddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_ps_512 : + GCCBuiltin<"__builtin_ia32_expandloadsf512_mask">, + Intrinsic<[llvm_v16f32_ty], [llvm_ptr_ty, llvm_v16f32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_512 : + GCCBuiltin<"__builtin_ia32_expandloaddf512_mask">, + Intrinsic<[llvm_v8f64_ty], [llvm_ptr_ty, llvm_v8f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_256 : + GCCBuiltin<"__builtin_ia32_expandloadsf256_mask">, + Intrinsic<[llvm_v8f32_ty], [llvm_ptr_ty, llvm_v8f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_256 : + GCCBuiltin<"__builtin_ia32_expandloaddf256_mask">, + Intrinsic<[llvm_v4f64_ty], [llvm_ptr_ty, llvm_v4f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_ps_128 : + GCCBuiltin<"__builtin_ia32_expandloadsf128_mask">, + Intrinsic<[llvm_v4f32_ty], [llvm_ptr_ty, llvm_v4f32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_pd_128 : + GCCBuiltin<"__builtin_ia32_expandloaddf128_mask">, + Intrinsic<[llvm_v2f64_ty], [llvm_ptr_ty, llvm_v2f64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + + def int_x86_avx512_mask_expand_d_512 : + GCCBuiltin<"__builtin_ia32_expandsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_512 : + GCCBuiltin<"__builtin_ia32_expanddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_256 : + GCCBuiltin<"__builtin_ia32_expandsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_v8i32_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_256 : + GCCBuiltin<"__builtin_ia32_expanddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_v4i64_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_d_128 : + GCCBuiltin<"__builtin_ia32_expandsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_expand_q_128 : + GCCBuiltin<"__builtin_ia32_expanddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrNoMem]>; + + def int_x86_avx512_mask_expand_load_d_512 : + GCCBuiltin<"__builtin_ia32_expandloadsi512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_ptr_ty, llvm_v16i32_ty, + llvm_i16_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_512 : + GCCBuiltin<"__builtin_ia32_expandloaddi512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty, llvm_v8i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_256 : + GCCBuiltin<"__builtin_ia32_expandloadsi256_mask">, + Intrinsic<[llvm_v8i32_ty], [llvm_ptr_ty, llvm_v8i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_256 : + GCCBuiltin<"__builtin_ia32_expandloaddi256_mask">, + Intrinsic<[llvm_v4i64_ty], [llvm_ptr_ty, llvm_v4i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_d_128 : + GCCBuiltin<"__builtin_ia32_expandloadsi128_mask">, + Intrinsic<[llvm_v4i32_ty], [llvm_ptr_ty, llvm_v4i32_ty, + llvm_i8_ty], [IntrReadArgMem]>; + def int_x86_avx512_mask_expand_load_q_128 : + GCCBuiltin<"__builtin_ia32_expandloaddi128_mask">, + Intrinsic<[llvm_v2i64_ty], [llvm_ptr_ty, llvm_v2i64_ty, + llvm_i8_ty], [IntrReadArgMem]>; + +} // Misc. let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_ps_512 : GCCBuiltin<"__builtin_ia32_cmpps512_mask">, @@ -3190,13 +3873,6 @@ let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i32_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_pcmpeq_d_512 : GCCBuiltin<"__builtin_ia32_pcmpeqd512_mask">, - Intrinsic<[llvm_i16_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pcmpeq_q_512 : GCCBuiltin<"__builtin_ia32_pcmpeqq512_mask">, - Intrinsic<[llvm_i8_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, llvm_v16i32_ty, llvm_i16_ty], @@ -3205,6 +3881,8 @@ let TargetPrefix = "x86" in { Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, + Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } //===----------------------------------------------------------------------===// diff --git a/include/llvm/IR/LLVMContext.h b/include/llvm/IR/LLVMContext.h index 4d940d5..2f18782 100644 --- a/include/llvm/IR/LLVMContext.h +++ b/include/llvm/IR/LLVMContext.h @@ -18,6 +18,7 @@ #include "llvm-c/Core.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Options.h" namespace llvm { @@ -52,7 +53,12 @@ public: MD_fpmath = 3, // "fpmath" MD_range = 4, // "range" MD_tbaa_struct = 5, // "tbaa.struct" - MD_invariant_load = 6 // "invariant.load" + MD_invariant_load = 6, // "invariant.load" + MD_alias_scope = 7, // "alias.scope" + MD_noalias = 8, // "noalias", + MD_nontemporal = 9, // "nontemporal" + MD_mem_parallel_loop_access = 10, // "llvm.mem.parallel_loop_access" + MD_nonnull = 11 // "nonnull" }; /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. @@ -97,12 +103,14 @@ public: /// setDiagnosticHandler - This method sets a handler that is invoked /// when the backend needs to report anything to the user. The first /// argument is a function pointer and the second is a context pointer that - /// gets passed into the DiagHandler. + /// gets passed into the DiagHandler. The third argument should be set to + /// true if the handler only expects enabled diagnostics. /// /// LLVMContext doesn't take ownership or interpret either of these /// pointers. void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler, - void *DiagContext = nullptr); + void *DiagContext = nullptr, + bool RespectFilters = false); /// getDiagnosticHandler - Return the diagnostic handler set by /// setDiagnosticHandler. @@ -112,14 +120,16 @@ public: /// setDiagnosticContext. void *getDiagnosticContext() const; - /// diagnose - Report a message to the currently installed diagnostic handler. + /// \brief Report a message to the currently installed diagnostic handler. + /// /// This function returns, in particular in the case of error reporting - /// (DI.Severity == RS_Error), so the caller should leave the compilation + /// (DI.Severity == \a DS_Error), so the caller should leave the compilation /// process in a self-consistent state, even though the generated code /// need not be correct. - /// The diagnostic message will be implicitly prefixed with a severity - /// keyword according to \p DI.getSeverity(), i.e., "error: " - /// for RS_Error, "warning: " for RS_Warning, and "note: " for RS_Note. + /// + /// The diagnostic message will be implicitly prefixed with a severity keyword + /// according to \p DI.getSeverity(), i.e., "error: " for \a DS_Error, + /// "warning: " for \a DS_Warning, and "note: " for \a DS_Note. void diagnose(const DiagnosticInfo &DI); /// \brief Registers a yield callback with the given context. @@ -157,6 +167,14 @@ public: void emitError(const Instruction *I, const Twine &ErrorStr); void emitError(const Twine &ErrorStr); + /// \brief Query for a debug option's value. + /// + /// This function returns typed data populated from command line parsing. + template + ValT getOption() const { + return OptionRegistry::instance().template get(); + } + private: LLVMContext(LLVMContext&) LLVM_DELETED_FUNCTION; void operator=(LLVMContext&) LLVM_DELETED_FUNCTION; diff --git a/include/llvm/IR/LeakDetector.h b/include/llvm/IR/LeakDetector.h deleted file mode 100644 index cb18df8..0000000 --- a/include/llvm/IR/LeakDetector.h +++ /dev/null @@ -1,92 +0,0 @@ -//===- LeakDetector.h - Provide leak detection ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a class that can be used to provide very simple memory leak -// checks for an API. Basically LLVM uses this to make sure that Instructions, -// for example, are deleted when they are supposed to be, and not leaked away. -// -// When compiling with NDEBUG (Release build), this class does nothing, thus -// adding no checking overhead to release builds. Note that this class is -// implemented in a very simple way, requiring completely manual manipulation -// and checking for garbage, but this is intentional: users should not be using -// this API, only other APIs should. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_IR_LEAKDETECTOR_H -#define LLVM_IR_LEAKDETECTOR_H - -#include - -namespace llvm { - -class LLVMContext; -class Value; - -struct LeakDetector { - /// addGarbageObject - Add a pointer to the internal set of "garbage" object - /// pointers. This should be called when objects are created, or if they are - /// taken out of an owning collection. - /// - static void addGarbageObject(void *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - - /// removeGarbageObject - Remove a pointer from our internal representation of - /// our "garbage" objects. This should be called when an object is added to - /// an "owning" collection. - /// - static void removeGarbageObject(void *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - - /// checkForGarbage - Traverse the internal representation of garbage - /// pointers. If there are any pointers that have been add'ed, but not - /// remove'd, big obnoxious warnings about memory leaks are issued. - /// - /// The specified message will be printed indicating when the check was - /// performed. - /// - static void checkForGarbage(LLVMContext &C, const std::string &Message) { -#ifndef NDEBUG - checkForGarbageImpl(C, Message); -#endif - } - - /// Overload the normal methods to work better with Value*'s because they are - /// by far the most common in LLVM. This does not affect the actual - /// functioning of this class, it just makes the warning messages nicer. - /// - static void addGarbageObject(const Value *Object) { -#ifndef NDEBUG - addGarbageObjectImpl(Object); -#endif - } - static void removeGarbageObject(const Value *Object) { -#ifndef NDEBUG - removeGarbageObjectImpl(Object); -#endif - } - -private: - // If we are debugging, the actual implementations will be called... - static void addGarbageObjectImpl(const Value *Object); - static void removeGarbageObjectImpl(const Value *Object); - static void addGarbageObjectImpl(void *Object); - static void removeGarbageObjectImpl(void *Object); - static void checkForGarbageImpl(LLVMContext &C, const std::string &Message); -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index c967a6b..6c04e9d 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -37,9 +37,10 @@ class PassManagerBase { public: virtual ~PassManagerBase(); - /// add - Add a pass to the queue of passes to run. This passes ownership of + /// Add a pass to the queue of passes to run. This passes ownership of /// the Pass to the PassManager. When the PassManager is destroyed, the pass /// will be destroyed as well, so there is no need to delete the pass. This + /// may even destroy the pass right away if it is found to be redundant. This /// implies that all passes MUST be allocated with 'new'. virtual void add(Pass *P) = 0; }; @@ -51,10 +52,6 @@ public: PassManager(); ~PassManager(); - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep track of @@ -75,11 +72,6 @@ public: explicit FunctionPassManager(Module *M); ~FunctionPassManager(); - /// add - Add a pass to the queue of passes to run. This passes - /// ownership of the Pass to the PassManager. When the - /// PassManager_X is destroyed, the pass will be destroyed as well, so - /// there is no need to delete the pass. - /// This implies that all passes MUST be allocated with 'new'. void add(Pass *P) override; /// run - Execute all of the passes scheduled for execution. Keep diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index f6065a4..ab500a1 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PASSMANAGERS_H -#define LLVM_PASSMANAGERS_H +#ifndef LLVM_IR_LEGACYPASSMANAGERS_H +#define LLVM_IR_LEGACYPASSMANAGERS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" @@ -61,7 +61,7 @@ // // [o] class FunctionPassManager; // -// This is a external interface used by JIT to manage FunctionPasses. This +// This is a external interface used to manage FunctionPasses. This // interface relies on FunctionPassManagerImpl to do all the tasks. // // [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager, @@ -248,7 +248,7 @@ private: DenseMap > InversedLastUser; /// Immutable passes are managed by top level manager. - SmallVector ImmutablePasses; + SmallVector ImmutablePasses; DenseMap AnUsageMap; }; @@ -393,7 +393,7 @@ private: // Collection of higher level analysis used by the pass managed by // this manager. - SmallVector HigherLevelAnalysis; + SmallVector HigherLevelAnalysis; unsigned Depth; }; diff --git a/include/llvm/IR/MDBuilder.h b/include/llvm/IR/MDBuilder.h index 37d263b..91a6685 100644 --- a/include/llvm/IR/MDBuilder.h +++ b/include/llvm/IR/MDBuilder.h @@ -15,6 +15,7 @@ #ifndef LLVM_IR_MDBUILDER_H #define LLVM_IR_MDBUILDER_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include @@ -23,9 +24,10 @@ namespace llvm { class APInt; template class ArrayRef; class LLVMContext; +class Constant; +class ConstantAsMetadata; class MDNode; class MDString; -class StringRef; class MDBuilder { LLVMContext &Context; @@ -36,6 +38,9 @@ public: /// \brief Return the given string as metadata. MDString *createString(StringRef Str); + /// \brief Return the given constant as metadata. + ConstantAsMetadata *createConstant(Constant *C); + //===------------------------------------------------------------------===// // FPMath metadata. //===------------------------------------------------------------------===// @@ -63,19 +68,54 @@ public: MDNode *createRange(const APInt &Lo, const APInt &Hi); //===------------------------------------------------------------------===// - // TBAA metadata. + // AA metadata. //===------------------------------------------------------------------===// - /// \brief Return metadata appropriate for a TBAA root node. Each returned +protected: + /// \brief Return metadata appropriate for a AA root node (scope or TBAA). + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAARoot(StringRef Name = StringRef(), + MDNode *Extra = nullptr); + +public: + /// \brief Return metadata appropriate for a TBAA root node. Each returned /// node is distinct from all other metadata and will never be identified /// (uniqued) with anything else. - MDNode *createAnonymousTBAARoot(); + MDNode *createAnonymousTBAARoot() { + return createAnonymousAARoot(); + } + + /// \brief Return metadata appropriate for an alias scope domain node. + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAliasScopeDomain(StringRef Name = StringRef()) { + return createAnonymousAARoot(Name); + } + + /// \brief Return metadata appropriate for an alias scope root node. + /// Each returned node is distinct from all other metadata and will never + /// be identified (uniqued) with anything else. + MDNode *createAnonymousAliasScope(MDNode *Domain, + StringRef Name = StringRef()) { + return createAnonymousAARoot(Name, Domain); + } /// \brief Return metadata appropriate for a TBAA root node with the given /// name. This may be identified (uniqued) with other roots with the same /// name. MDNode *createTBAARoot(StringRef Name); + /// \brief Return metadata appropriate for an alias scope domain node with + /// the given name. This may be identified (uniqued) with other roots with + /// the same name. + MDNode *createAliasScopeDomain(StringRef Name); + + /// \brief Return metadata appropriate for an alias scope node with + /// the given name. This may be identified (uniqued) with other scopes with + /// the same name and domain. + MDNode *createAliasScope(StringRef Name, MDNode *Domain); + /// \brief Return metadata for a non-root TBAA node with the given name, /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. MDNode *createTBAANode(StringRef Name, MDNode *Parent, diff --git a/include/llvm/IR/Mangler.h b/include/llvm/IR/Mangler.h index c1ba585..1e6b5b1 100644 --- a/include/llvm/IR/Mangler.h +++ b/include/llvm/IR/Mangler.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TARGET_MANGLER_H -#define LLVM_TARGET_MANGLER_H +#ifndef LLVM_IR_MANGLER_H +#define LLVM_IR_MANGLER_H #include "llvm/ADT/DenseMap.h" #include "llvm/Support/raw_ostream.h" @@ -66,4 +66,4 @@ public: } // End llvm namespace -#endif // LLVM_TARGET_MANGLER_H +#endif diff --git a/include/llvm/IR/Metadata.def b/include/llvm/IR/Metadata.def new file mode 100644 index 0000000..2098bb5 --- /dev/null +++ b/include/llvm/IR/Metadata.def @@ -0,0 +1,59 @@ +//===- llvm/Metadata.def - Metadata definitions -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through all types of metadata. +// +//===----------------------------------------------------------------------===// + +#if !(defined HANDLE_METADATA || defined HANDLE_METADATA_LEAF || \ + defined HANDLE_METADATA_BRANCH || defined HANDLE_UNIQUABLE_LEAF || \ + defined HANDLE_UNIQUABLE_BRANCH) +#error "Missing macro definition of HANDLE_METADATA*" +#endif + +// Handler for all types of metadata. +#ifndef HANDLE_METADATA +#define HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_LEAF +#define HANDLE_METADATA_LEAF(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for non-leaf nodes in the class hierarchy. +#ifndef HANDLE_METADATA_BRANCH +#define HANDLE_METADATA_BRANCH(CLASS) HANDLE_METADATA(CLASS) +#endif + +// Handler for leaf nodes under UniquableMDNode. +#ifndef HANDLE_UNIQUABLE_LEAF +#define HANDLE_UNIQUABLE_LEAF(CLASS) HANDLE_METADATA_LEAF(CLASS) +#endif + +// Handler for non-leaf nodes under UniquableMDNode. +#ifndef HANDLE_UNIQUABLE_BRANCH +#define HANDLE_UNIQUABLE_BRANCH(CLASS) HANDLE_METADATA_BRANCH(CLASS) +#endif + +HANDLE_METADATA_LEAF(MDString) +HANDLE_METADATA_BRANCH(ValueAsMetadata) +HANDLE_METADATA_LEAF(ConstantAsMetadata) +HANDLE_METADATA_LEAF(LocalAsMetadata) +HANDLE_METADATA_BRANCH(MDNode) +HANDLE_METADATA_LEAF(MDNodeFwdDecl) +HANDLE_UNIQUABLE_BRANCH(UniquableMDNode) +HANDLE_UNIQUABLE_LEAF(MDTuple) +HANDLE_UNIQUABLE_LEAF(MDLocation) + +#undef HANDLE_METADATA +#undef HANDLE_METADATA_LEAF +#undef HANDLE_METADATA_BRANCH +#undef HANDLE_UNIQUABLE_LEAF +#undef HANDLE_UNIQUABLE_BRANCH diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 7a0ca88..3bf6d38 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -17,10 +17,14 @@ #define LLVM_IR_METADATA_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/ilist_node.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/MetadataTracking.h" #include "llvm/IR/Value.h" +#include "llvm/Support/ErrorHandling.h" +#include namespace llvm { class LLVMContext; @@ -30,169 +34,887 @@ template enum LLVMConstants : uint32_t { - DEBUG_METADATA_VERSION = 1 // Current debug info version number. + DEBUG_METADATA_VERSION = 2 // Current debug info version number. }; +/// \brief Root of the metadata hierarchy. +/// +/// This is a root class for typeless data in the IR. +class Metadata { + friend class ReplaceableMetadataImpl; + + /// \brief RTTI. + const unsigned char SubclassID; + +protected: + /// \brief Storage flag for non-uniqued, otherwise unowned, metadata. + bool IsDistinctInContext : 1; + // TODO: expose remaining bits to subclasses. + + unsigned short SubclassData16; + unsigned SubclassData32; + +public: + enum MetadataKind { + MDTupleKind, + MDLocationKind, + MDNodeFwdDeclKind, + ConstantAsMetadataKind, + LocalAsMetadataKind, + MDStringKind + }; + +protected: + Metadata(unsigned ID) + : SubclassID(ID), IsDistinctInContext(false), SubclassData16(0), + SubclassData32(0) {} + ~Metadata() {} + + /// \brief Store this in a big non-uniqued untyped bucket. + bool isStoredDistinctInContext() const { return IsDistinctInContext; } + + /// \brief Default handling of a changed operand, which asserts. + /// + /// If subclasses pass themselves in as owners to a tracking node reference, + /// they must provide an implementation of this method. + void handleChangedOperand(void *, Metadata *) { + llvm_unreachable("Unimplemented in Metadata subclass"); + } + +public: + unsigned getMetadataID() const { return SubclassID; } + + /// \brief User-friendly dump. + void dump() const; + void print(raw_ostream &OS) const; + void printAsOperand(raw_ostream &OS, bool PrintType = true, + const Module *M = nullptr) const; +}; + +#define HANDLE_METADATA(CLASS) class CLASS; +#include "llvm/IR/Metadata.def" + +inline raw_ostream &operator<<(raw_ostream &OS, const Metadata &MD) { + MD.print(OS); + return OS; +} + +/// \brief Metadata wrapper in the Value hierarchy. +/// +/// A member of the \a Value hierarchy to represent a reference to metadata. +/// This allows, e.g., instrinsics to have metadata as operands. +/// +/// Notably, this is the only thing in either hierarchy that is allowed to +/// reference \a LocalAsMetadata. +class MetadataAsValue : public Value { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Metadata *MD; + + MetadataAsValue(Type *Ty, Metadata *MD); + ~MetadataAsValue(); + + /// \brief Drop use of metadata (during teardown). + void dropUse() { MD = nullptr; } + +public: + static MetadataAsValue *get(LLVMContext &Context, Metadata *MD); + static MetadataAsValue *getIfExists(LLVMContext &Context, Metadata *MD); + Metadata *getMetadata() const { return MD; } + + static bool classof(const Value *V) { + return V->getValueID() == MetadataAsValueVal; + } + +private: + void handleChangedMetadata(Metadata *MD); + void track(); + void untrack(); +}; + +/// \brief Shared implementation of use-lists for replaceable metadata. +/// +/// Most metadata cannot be RAUW'ed. This is a shared implementation of +/// use-lists and associated API for the two that support it (\a ValueAsMetadata +/// and \a TempMDNode). +class ReplaceableMetadataImpl { + friend class MetadataTracking; + +public: + typedef MetadataTracking::OwnerTy OwnerTy; + +private: + uint64_t NextIndex; + SmallDenseMap, 4> UseMap; + +public: + ReplaceableMetadataImpl() : NextIndex(0) {} + ~ReplaceableMetadataImpl() { + assert(UseMap.empty() && "Cannot destroy in-use replaceable metadata"); + } + + /// \brief Replace all uses of this with MD. + /// + /// Replace all uses of this with \c MD, which is allowed to be null. + void replaceAllUsesWith(Metadata *MD); + + /// \brief Resolve all uses of this. + /// + /// Resolve all uses of this, turning off RAUW permanently. If \c + /// ResolveUsers, call \a UniquableMDNode::resolve() on any users whose last + /// operand is resolved. + void resolveAllUses(bool ResolveUsers = true); + +private: + void addRef(void *Ref, OwnerTy Owner); + void dropRef(void *Ref); + void moveRef(void *Ref, void *New, const Metadata &MD); + + static ReplaceableMetadataImpl *get(Metadata &MD); +}; + +/// \brief Value wrapper in the Metadata hierarchy. +/// +/// This is a custom value handle that allows other metadata to refer to +/// classes in the Value hierarchy. +/// +/// Because of full uniquing support, each value is only wrapped by a single \a +/// ValueAsMetadata object, so the lookup maps are far more efficient than +/// those using ValueHandleBase. +class ValueAsMetadata : public Metadata, ReplaceableMetadataImpl { + friend class ReplaceableMetadataImpl; + friend class LLVMContextImpl; + + Value *V; + + /// \brief Drop users without RAUW (during teardown). + void dropUsers() { + ReplaceableMetadataImpl::resolveAllUses(/* ResolveUsers */ false); + } + +protected: + ValueAsMetadata(unsigned ID, Value *V) + : Metadata(ID), V(V) { + assert(V && "Expected valid value"); + } + ~ValueAsMetadata() {} + +public: + static ValueAsMetadata *get(Value *V); + static ConstantAsMetadata *getConstant(Value *C) { + return cast(get(C)); + } + static LocalAsMetadata *getLocal(Value *Local) { + return cast(get(Local)); + } + + static ValueAsMetadata *getIfExists(Value *V); + static ConstantAsMetadata *getConstantIfExists(Value *C) { + return cast_or_null(getIfExists(C)); + } + static LocalAsMetadata *getLocalIfExists(Value *Local) { + return cast_or_null(getIfExists(Local)); + } + + Value *getValue() const { return V; } + Type *getType() const { return V->getType(); } + LLVMContext &getContext() const { return V->getContext(); } + + static void handleDeletion(Value *V); + static void handleRAUW(Value *From, Value *To); + +protected: + /// \brief Handle collisions after \a Value::replaceAllUsesWith(). + /// + /// RAUW isn't supported directly for \a ValueAsMetadata, but if the wrapped + /// \a Value gets RAUW'ed and the target already exists, this is used to + /// merge the two metadata nodes. + void replaceAllUsesWith(Metadata *MD) { + ReplaceableMetadataImpl::replaceAllUsesWith(MD); + } + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind || + MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class ConstantAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + ConstantAsMetadata(Constant *C) + : ValueAsMetadata(ConstantAsMetadataKind, C) {} + +public: + static ConstantAsMetadata *get(Constant *C) { + return ValueAsMetadata::getConstant(C); + } + static ConstantAsMetadata *getIfExists(Constant *C) { + return ValueAsMetadata::getConstantIfExists(C); + } + + Constant *getValue() const { + return cast(ValueAsMetadata::getValue()); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == ConstantAsMetadataKind; + } +}; + +class LocalAsMetadata : public ValueAsMetadata { + friend class ValueAsMetadata; + + LocalAsMetadata(Value *Local) + : ValueAsMetadata(LocalAsMetadataKind, Local) { + assert(!isa(Local) && "Expected local value"); + } + +public: + static LocalAsMetadata *get(Value *Local) { + return ValueAsMetadata::getLocal(Local); + } + static LocalAsMetadata *getIfExists(Value *Local) { + return ValueAsMetadata::getLocalIfExists(Local); + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == LocalAsMetadataKind; + } +}; + +/// \brief Transitional API for extracting constants from Metadata. +/// +/// This namespace contains transitional functions for metadata that points to +/// \a Constants. +/// +/// In prehistory -- when metadata was a subclass of \a Value -- \a MDNode +/// operands could refer to any \a Value. There's was a lot of code like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// Now that \a Value and \a Metadata are in separate hierarchies, maintaining +/// the semantics for \a isa(), \a cast(), \a dyn_cast() (etc.) requires three +/// steps: cast in the \a Metadata hierarchy, extraction of the \a Value, and +/// cast in the \a Value hierarchy. Besides creating boiler-plate, this +/// requires subtle control flow changes. +/// +/// The end-goal is to create a new type of metadata, called (e.g.) \a MDInt, +/// so that metadata can refer to numbers without traversing a bridge to the \a +/// Value hierarchy. In this final state, the code above would look like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *MI = dyn_cast(N->getOperand(2)); +/// \endcode +/// +/// The API in this namespace supports the transition. \a MDInt doesn't exist +/// yet, and even once it does, changing each metadata schema to use it is its +/// own mini-project. In the meantime this API prevents us from introducing +/// complex and bug-prone control flow that will disappear in the end. In +/// particular, the above code looks like this: +/// +/// \code +/// MDNode *N = ...; +/// auto *CI = mdconst::dyn_extract(N->getOperand(2)); +/// \endcode +/// +/// The full set of provided functions includes: +/// +/// mdconst::hasa <=> isa +/// mdconst::extract <=> cast +/// mdconst::extract_or_null <=> cast_or_null +/// mdconst::dyn_extract <=> dyn_cast +/// mdconst::dyn_extract_or_null <=> dyn_cast_or_null +/// +/// The target of the cast must be a subclass of \a Constant. +namespace mdconst { + +namespace detail { +template T &make(); +template struct HasDereference { + typedef char Yes[1]; + typedef char No[2]; + template struct SFINAE {}; + + template + static Yes &hasDereference(SFINAE(*make()))> * = 0); + template static No &hasDereference(...); + + static const bool value = + sizeof(hasDereference(nullptr)) == sizeof(Yes); +}; +template struct IsValidPointer { + static const bool value = std::is_base_of::value && + HasDereference::value; +}; +template struct IsValidReference { + static const bool value = std::is_base_of::value && + std::is_convertible::value; +}; +} // end namespace detail + +/// \brief Check whether Metadata has a Value. +/// +/// As an analogue to \a isa(), check whether \c MD has an \a Value inside of +/// type \c X. +template +inline typename std::enable_if::value, bool>::type +hasa(Y &&MD) { + assert(MD && "Null pointer sent into hasa"); + if (auto *V = dyn_cast(MD)) + return isa(V->getValue()); + return false; +} +template +inline + typename std::enable_if::value, bool>::type + hasa(Y &MD) { + return hasa(&MD); +} + +/// \brief Extract a Value from Metadata. +/// +/// As an analogue to \a cast(), extract the \a Value subclass \c X from \c MD. +template +inline typename std::enable_if::value, X *>::type +extract(Y &&MD) { + return cast(cast(MD)->getValue()); +} +template +inline + typename std::enable_if::value, X *>::type + extract(Y &MD) { + return extract(&MD); +} + +/// \brief Extract a Value from Metadata, allowing null. +/// +/// As an analogue to \a cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +extract_or_null(Y &&MD) { + if (auto *V = cast_or_null(MD)) + return cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass. +template +inline typename std::enable_if::value, X *>::type +dyn_extract(Y &&MD) { + if (auto *V = dyn_cast(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +/// \brief Extract a Value from Metadata, if any, allowing null. +/// +/// As an analogue to \a dyn_cast_or_null(), extract the \a Value subclass \c X +/// from \c MD, return null if \c MD doesn't contain a \a Value or if the \a +/// Value it does contain is of the wrong subclass, allowing \c MD to be null. +template +inline typename std::enable_if::value, X *>::type +dyn_extract_or_null(Y &&MD) { + if (auto *V = dyn_cast_or_null(MD)) + return dyn_cast(V->getValue()); + return nullptr; +} + +} // end namespace mdconst + //===----------------------------------------------------------------------===// -/// MDString - a single uniqued string. +/// \brief A single uniqued string. +/// /// These are used to efficiently contain a byte sequence for metadata. /// MDString is always unnamed. -class MDString : public Value { - virtual void anchor(); +class MDString : public Metadata { + friend class StringMapEntry; + MDString(const MDString &) LLVM_DELETED_FUNCTION; + MDString &operator=(MDString &&) LLVM_DELETED_FUNCTION; + MDString &operator=(const MDString &) LLVM_DELETED_FUNCTION; + + StringMapEntry *Entry; + MDString() : Metadata(MDStringKind), Entry(nullptr) {} + MDString(MDString &&) : Metadata(MDStringKind) {} - explicit MDString(LLVMContext &C); public: static MDString *get(LLVMContext &Context, StringRef Str); static MDString *get(LLVMContext &Context, const char *Str) { return get(Context, Str ? StringRef(Str) : StringRef()); } - StringRef getString() const { return getName(); } + StringRef getString() const; - unsigned getLength() const { return (unsigned)getName().size(); } + unsigned getLength() const { return (unsigned)getString().size(); } typedef StringRef::iterator iterator; - /// begin() - Pointer to the first byte of the string. - iterator begin() const { return getName().begin(); } + /// \brief Pointer to the first byte of the string. + iterator begin() const { return getString().begin(); } - /// end() - Pointer to one byte past the end of the string. - iterator end() const { return getName().end(); } + /// \brief Pointer to one byte past the end of the string. + iterator end() const { return getString().end(); } - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == MDStringVal; + const unsigned char *bytes_begin() const { return getString().bytes_begin(); } + const unsigned char *bytes_end() const { return getString().bytes_end(); } + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast. + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDStringKind; } }; +/// \brief A collection of metadata nodes that might be associated with a +/// memory access used by the alias-analysis infrastructure. +struct AAMDNodes { + explicit AAMDNodes(MDNode *T = nullptr, MDNode *S = nullptr, + MDNode *N = nullptr) + : TBAA(T), Scope(S), NoAlias(N) {} + + bool operator==(const AAMDNodes &A) const { + return TBAA == A.TBAA && Scope == A.Scope && NoAlias == A.NoAlias; + } + + bool operator!=(const AAMDNodes &A) const { return !(*this == A); } + + LLVM_EXPLICIT operator bool() const { return TBAA || Scope || NoAlias; } + + /// \brief The tag for type-based alias analysis. + MDNode *TBAA; -class MDNodeOperand; + /// \brief The tag for alias scope specification (used with noalias). + MDNode *Scope; + + /// \brief The tag specifying the noalias scope. + MDNode *NoAlias; +}; + +// Specialize DenseMapInfo for AAMDNodes. +template<> +struct DenseMapInfo { + static inline AAMDNodes getEmptyKey() { + return AAMDNodes(DenseMapInfo::getEmptyKey(), 0, 0); + } + static inline AAMDNodes getTombstoneKey() { + return AAMDNodes(DenseMapInfo::getTombstoneKey(), 0, 0); + } + static unsigned getHashValue(const AAMDNodes &Val) { + return DenseMapInfo::getHashValue(Val.TBAA) ^ + DenseMapInfo::getHashValue(Val.Scope) ^ + DenseMapInfo::getHashValue(Val.NoAlias); + } + static bool isEqual(const AAMDNodes &LHS, const AAMDNodes &RHS) { + return LHS == RHS; + } +}; + +/// \brief Tracking metadata reference owned by Metadata. +/// +/// Similar to \a TrackingMDRef, but it's expected to be owned by an instance +/// of \a Metadata, which has the option of registering itself for callbacks to +/// re-unique itself. +/// +/// In particular, this is used by \a MDNode. +class MDOperand { + MDOperand(MDOperand &&) LLVM_DELETED_FUNCTION; + MDOperand(const MDOperand &) LLVM_DELETED_FUNCTION; + MDOperand &operator=(MDOperand &&) LLVM_DELETED_FUNCTION; + MDOperand &operator=(const MDOperand &) LLVM_DELETED_FUNCTION; + + Metadata *MD; + +public: + MDOperand() : MD(nullptr) {} + ~MDOperand() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD, Metadata *Owner) { + untrack(); + this->MD = MD; + track(Owner); + } + +private: + void track(Metadata *Owner) { + if (MD) { + if (Owner) + MetadataTracking::track(this, *MD, *Owner); + else + MetadataTracking::track(MD); + } + } + void untrack() { + assert(static_cast(this) == &MD && "Expected same address"); + if (MD) + MetadataTracking::untrack(MD); + } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(MDOperand &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const MDOperand &MD) { return MD.get(); } +}; //===----------------------------------------------------------------------===// -/// MDNode - a tuple of other values. -class MDNode : public Value, public FoldingSetNode { +/// \brief Tuple of metadata. +class MDNode : public Metadata { MDNode(const MDNode &) LLVM_DELETED_FUNCTION; void operator=(const MDNode &) LLVM_DELETED_FUNCTION; - friend class MDNodeOperand; - friend class LLVMContextImpl; - friend struct FoldingSetTrait; - - /// Hash - If the MDNode is uniqued cache the hash to speed up lookup. - unsigned Hash; + void *operator new(size_t) LLVM_DELETED_FUNCTION; - /// NumOperands - This many 'MDNodeOperand' items are co-allocated onto the - /// end of this MDNode. + LLVMContext &Context; unsigned NumOperands; - // Subclass data enums. - enum { - /// FunctionLocalBit - This bit is set if this MDNode is function local. - /// This is true when it (potentially transitively) contains a reference to - /// something in a function, like an argument, basicblock, or instruction. - FunctionLocalBit = 1 << 0, +protected: + unsigned MDNodeSubclassData; - /// NotUniquedBit - This is set on MDNodes that are not uniqued because they - /// have a null operand. - NotUniquedBit = 1 << 1, + void *operator new(size_t Size, unsigned NumOps); + void operator delete(void *Mem); - /// DestroyFlag - This bit is set by destroy() so the destructor can assert - /// that the node isn't being destroyed with a plain 'delete'. - DestroyFlag = 1 << 2 - }; + /// \brief Required by std, but never called. + void operator delete(void *, unsigned) { + llvm_unreachable("Constructor throws?"); + } - // FunctionLocal enums. - enum FunctionLocalness { - FL_Unknown = -1, - FL_No = 0, - FL_Yes = 1 - }; + /// \brief Required by std, but never called. + void operator delete(void *, unsigned, bool) { + llvm_unreachable("Constructor throws?"); + } - /// replaceOperand - Replace each instance of F from the operand list of this - /// node with T. - void replaceOperand(MDNodeOperand *Op, Value *NewVal); - ~MDNode(); + MDNode(LLVMContext &Context, unsigned ID, ArrayRef MDs); + ~MDNode() {} - MDNode(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal); + void dropAllReferences(); + + MDOperand *mutable_begin() { return mutable_end() - NumOperands; } + MDOperand *mutable_end() { return reinterpret_cast(this); } - static MDNode *getMDNode(LLVMContext &C, ArrayRef Vals, - FunctionLocalness FL, bool Insert = true); public: - // Constructors and destructors. - static MDNode *get(LLVMContext &Context, ArrayRef Vals); - // getWhenValsUnresolved - Construct MDNode determining function-localness - // from isFunctionLocal argument, not by analyzing Vals. - static MDNode *getWhenValsUnresolved(LLVMContext &Context, - ArrayRef Vals, - bool isFunctionLocal); - - static MDNode *getIfExists(LLVMContext &Context, ArrayRef Vals); - - /// getTemporary - Return a temporary MDNode, for use in constructing - /// cyclic MDNode structures. A temporary MDNode is not uniqued, - /// may be RAUW'd, and must be manually deleted with deleteTemporary. - static MDNode *getTemporary(LLVMContext &Context, ArrayRef Vals); - - /// deleteTemporary - Deallocate a node created by getTemporary. The - /// node must not have any users. + static inline MDNode *get(LLVMContext &Context, ArrayRef MDs); + static inline MDNode *getIfExists(LLVMContext &Context, + ArrayRef MDs); + static inline MDNode *getDistinct(LLVMContext &Context, + ArrayRef MDs); + + /// \brief Return a temporary MDNode + /// + /// For use in constructing cyclic MDNode structures. A temporary MDNode is + /// not uniqued, may be RAUW'd, and must be manually deleted with + /// deleteTemporary. + static MDNodeFwdDecl *getTemporary(LLVMContext &Context, + ArrayRef MDs); + + /// \brief Deallocate a node created by getTemporary. + /// + /// The node must not have any users. static void deleteTemporary(MDNode *N); - /// replaceOperandWith - Replace a specific operand. - void replaceOperandWith(unsigned i, Value *NewVal); + LLVMContext &getContext() const { return Context; } - /// getOperand - Return specified operand. - Value *getOperand(unsigned i) const LLVM_READONLY; + /// \brief Replace a specific operand. + void replaceOperandWith(unsigned I, Metadata *New); - /// getNumOperands - Return number of MDNode operands. - unsigned getNumOperands() const { return NumOperands; } + /// \brief Check if node is fully resolved. + bool isResolved() const; - /// isFunctionLocal - Return whether MDNode is local to a function. - bool isFunctionLocal() const { - return (getSubclassDataFromValue() & FunctionLocalBit) != 0; + /// \brief Check if node is distinct. + /// + /// Distinct nodes are not uniqued, and will not be returned by \a + /// MDNode::get(). + bool isDistinct() const { + return isStoredDistinctInContext() || isa(this); } - // getFunction - If this metadata is function-local and recursively has a - // function-local operand, return the first such operand's parent function. - // Otherwise, return null. getFunction() should not be used for performance- - // critical code because it recursively visits all the MDNode's operands. - const Function *getFunction() const; +protected: + /// \brief Set an operand. + /// + /// Sets the operand directly, without worrying about uniquing. + void setOperand(unsigned I, Metadata *New); - /// Profile - calculate a unique identifier for this MDNode to collapse - /// duplicates - void Profile(FoldingSetNodeID &ID) const; +public: + typedef const MDOperand *op_iterator; + typedef iterator_range op_range; - /// Methods for support type inquiry through isa, cast, and dyn_cast: - static bool classof(const Value *V) { - return V->getValueID() == MDNodeVal; + op_iterator op_begin() const { + return const_cast(this)->mutable_begin(); + } + op_iterator op_end() const { + return const_cast(this)->mutable_end(); + } + op_range operands() const { return op_range(op_begin(), op_end()); } + + const MDOperand &getOperand(unsigned I) const { + assert(I < NumOperands && "Out of range"); + return op_begin()[I]; + } + + /// \brief Return number of MDNode operands. + unsigned getNumOperands() const { return NumOperands; } + + /// \brief Methods for support type inquiry through isa, cast, and dyn_cast: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind || + MD->getMetadataID() == MDLocationKind || + MD->getMetadataID() == MDNodeFwdDeclKind; } - /// Check whether MDNode is a vtable access. + /// \brief Check whether MDNode is a vtable access. bool isTBAAVtableAccess() const; - /// Methods for metadata merging. + /// \brief Methods for metadata merging. + static MDNode *concatenate(MDNode *A, MDNode *B); + static MDNode *intersect(MDNode *A, MDNode *B); static MDNode *getMostGenericTBAA(MDNode *A, MDNode *B); + static AAMDNodes getMostGenericAA(const AAMDNodes &A, const AAMDNodes &B); static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B); static MDNode *getMostGenericRange(MDNode *A, MDNode *B); +}; + +/// \brief Uniquable metadata node. +/// +/// A uniquable metadata node. This contains the basic functionality +/// for implementing sub-types of \a MDNode that can be uniqued like +/// constants. +/// +/// There is limited support for RAUW at construction time. At +/// construction time, if any operands are an instance of \a +/// MDNodeFwdDecl (or another unresolved \a UniquableMDNode, which +/// indicates an \a MDNodeFwdDecl in its path), the node itself will be +/// unresolved. As soon as all operands become resolved, it will drop +/// RAUW support permanently. +/// +/// If an unresolved node is part of a cycle, \a resolveCycles() needs +/// to be called on some member of the cycle when each \a MDNodeFwdDecl +/// has been removed. +class UniquableMDNode : public MDNode { + friend class ReplaceableMetadataImpl; + friend class MDNode; + friend class LLVMContextImpl; + + /// \brief Support RAUW as long as one of its arguments is replaceable. + /// + /// FIXME: Save memory by storing this in a pointer union with the + /// LLVMContext, and adding an LLVMContext reference to RMI. + std::unique_ptr ReplaceableUses; + +protected: + /// \brief Create a new node. + /// + /// If \c AllowRAUW, then if any operands are unresolved support RAUW. RAUW + /// will be dropped once all operands have been resolved (or if \a + /// resolveCycles() is called). + UniquableMDNode(LLVMContext &C, unsigned ID, ArrayRef Vals, + bool AllowRAUW); + ~UniquableMDNode() {} + + void storeDistinctInContext(); + +public: + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind || + MD->getMetadataID() == MDLocationKind; + } + + /// \brief Check whether any operands are forward declarations. + /// + /// Returns \c true as long as any operands (or their operands, etc.) are \a + /// MDNodeFwdDecl. + /// + /// As forward declarations are resolved, their containers should get + /// resolved automatically. However, if this (or one of its operands) is + /// involved in a cycle, \a resolveCycles() needs to be called explicitly. + bool isResolved() const { return !ReplaceableUses; } + + /// \brief Resolve cycles. + /// + /// Once all forward declarations have been resolved, force cycles to be + /// resolved. + /// + /// \pre No operands (or operands' operands, etc.) are \a MDNodeFwdDecl. + void resolveCycles(); + +private: + void handleChangedOperand(void *Ref, Metadata *New); + + void resolve(); + void resolveAfterOperandChange(Metadata *Old, Metadata *New); + void decrementUnresolvedOperandCount(); + + void deleteAsSubclass(); + UniquableMDNode *uniquify(); + void eraseFromStore(); +}; + +/// \brief Tuple of metadata. +/// +/// This is the simple \a MDNode arbitrary tuple. Nodes are uniqued by +/// default based on their operands. +class MDTuple : public UniquableMDNode { + friend class LLVMContextImpl; + friend class UniquableMDNode; + + MDTuple(LLVMContext &C, ArrayRef Vals, bool AllowRAUW) + : UniquableMDNode(C, MDTupleKind, Vals, AllowRAUW) {} + ~MDTuple() { dropAllReferences(); } + + void setHash(unsigned Hash) { MDNodeSubclassData = Hash; } + void recalculateHash(); + + static MDTuple *getImpl(LLVMContext &Context, ArrayRef MDs, + bool ShouldCreate); + +public: + /// \brief Get the hash, if any. + unsigned getHash() const { return MDNodeSubclassData; } + + static MDTuple *get(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, /* ShouldCreate */ true); + } + static MDTuple *getIfExists(LLVMContext &Context, ArrayRef MDs) { + return getImpl(Context, MDs, /* ShouldCreate */ false); + } + + /// \brief Return a distinct node. + /// + /// Return a distinct node -- i.e., a node that is not uniqued. + static MDTuple *getDistinct(LLVMContext &Context, ArrayRef MDs); + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDTupleKind; + } + +private: + MDTuple *uniquifyImpl(); + void eraseFromStoreImpl(); +}; + +MDNode *MDNode::get(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::get(Context, MDs); +} +MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getIfExists(Context, MDs); +} +MDNode *MDNode::getDistinct(LLVMContext &Context, ArrayRef MDs) { + return MDTuple::getDistinct(Context, MDs); +} + +/// \brief Debug location. +/// +/// A debug location in source code, used for debug info and otherwise. +class MDLocation : public UniquableMDNode { + friend class LLVMContextImpl; + friend class UniquableMDNode; + + MDLocation(LLVMContext &C, unsigned Line, unsigned Column, + ArrayRef MDs, bool AllowRAUW); + ~MDLocation() { dropAllReferences(); } + + static MDLocation *constructHelper(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, bool AllowRAUW); + + static MDLocation *getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, bool ShouldCreate); + + // Disallow replacing operands. + void replaceOperandWith(unsigned I, Metadata *New) LLVM_DELETED_FUNCTION; + +public: + static MDLocation *get(LLVMContext &Context, unsigned Line, unsigned Column, + Metadata *Scope, Metadata *InlinedAt = nullptr) { + return getImpl(Context, Line, Column, Scope, InlinedAt, + /* ShouldCreate */ true); + } + static MDLocation *getIfExists(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr) { + return getImpl(Context, Line, Column, Scope, InlinedAt, + /* ShouldCreate */ false); + } + static MDLocation *getDistinct(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt = nullptr); + + unsigned getLine() const { return MDNodeSubclassData; } + unsigned getColumn() const { return SubclassData16; } + Metadata *getScope() const { return getOperand(0); } + Metadata *getInlinedAt() const { + if (getNumOperands() == 2) + return getOperand(1); + return nullptr; + } + + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDLocationKind; + } + private: - // destroy - Delete this node. Only when there are no uses. - void destroy(); + MDLocation *uniquifyImpl(); + void eraseFromStoreImpl(); +}; + +/// \brief Forward declaration of metadata. +/// +/// Forward declaration of metadata, in the form of a basic tuple. Unlike \a +/// MDTuple, this class has full support for RAUW, is not owned, is not +/// uniqued, and is suitable for forward references. +class MDNodeFwdDecl : public MDNode, ReplaceableMetadataImpl { + friend class Metadata; + friend class ReplaceableMetadataImpl; + + MDNodeFwdDecl(LLVMContext &C, ArrayRef Vals) + : MDNode(C, MDNodeFwdDeclKind, Vals) {} + +public: + ~MDNodeFwdDecl() { dropAllReferences(); } + + // MSVC doesn't see the alternative: "using MDNode::operator delete". + void operator delete(void *Mem) { MDNode::operator delete(Mem); } - bool isNotUniqued() const { - return (getSubclassDataFromValue() & NotUniquedBit) != 0; + static MDNodeFwdDecl *get(LLVMContext &Context, ArrayRef MDs) { + return new (MDs.size()) MDNodeFwdDecl(Context, MDs); } - void setIsNotUniqued(); - // Shadow Value::setValueSubclassData with a private forwarding method so that - // any future subclasses cannot accidentally use it. - void setValueSubclassData(unsigned short D) { - Value::setValueSubclassData(D); + static bool classof(const Metadata *MD) { + return MD->getMetadataID() == MDNodeFwdDeclKind; } + + using ReplaceableMetadataImpl::replaceAllUsesWith; }; //===----------------------------------------------------------------------===// -/// NamedMDNode - a tuple of MDNodes. Despite its name, a NamedMDNode isn't -/// itself an MDNode. NamedMDNodes belong to modules, have names, and contain -/// lists of MDNodes. +/// \brief A tuple of MDNodes. +/// +/// Despite its name, a NamedMDNode isn't itself an MDNode. NamedMDNodes belong +/// to modules, have names, and contain lists of MDNodes. +/// +/// TODO: Inherit from Metadata. class NamedMDNode : public ilist_node { friend class SymbolTableListTraits; friend struct ilist_traits; @@ -202,7 +924,7 @@ class NamedMDNode : public ilist_node { std::string Name; Module *Parent; - void *Operands; // SmallVector, 4> + void *Operands; // SmallVector void setParent(Module *M) { Parent = M; } @@ -245,46 +967,34 @@ class NamedMDNode : public ilist_node { }; public: - /// eraseFromParent - Drop all references and remove the node from parent - /// module. + /// \brief Drop all references and remove the node from parent module. void eraseFromParent(); - /// dropAllReferences - Remove all uses and clear node vector. + /// \brief Remove all uses and clear node vector. void dropAllReferences(); - /// ~NamedMDNode - Destroy NamedMDNode. ~NamedMDNode(); - /// getParent - Get the module that holds this named metadata collection. + /// \brief Get the module that holds this named metadata collection. inline Module *getParent() { return Parent; } inline const Module *getParent() const { return Parent; } - /// getOperand - Return specified operand. MDNode *getOperand(unsigned i) const; - - /// getNumOperands - Return the number of NamedMDNode operands. unsigned getNumOperands() const; - - /// addOperand - Add metadata operand. void addOperand(MDNode *M); - - /// getName - Return a constant reference to this named metadata's name. + void setOperand(unsigned I, MDNode *New); StringRef getName() const; - - /// print - Implement operator<< on NamedMDNode. void print(raw_ostream &ROS) const; - - /// dump() - Allow printing of NamedMDNodes from the debugger. void dump() const; // --------------------------------------------------------------------------- // Operand Iterator interface... // - typedef op_iterator_impl op_iterator; + typedef op_iterator_impl op_iterator; op_iterator op_begin() { return op_iterator(this, 0); } op_iterator op_end() { return op_iterator(this, getNumOperands()); } - typedef op_iterator_impl const_op_iterator; + typedef op_iterator_impl const_op_iterator; const_op_iterator op_begin() const { return const_op_iterator(this, 0); } const_op_iterator op_end() const { return const_op_iterator(this, getNumOperands()); } diff --git a/include/llvm/IR/MetadataTracking.h b/include/llvm/IR/MetadataTracking.h new file mode 100644 index 0000000..541d9b3 --- /dev/null +++ b/include/llvm/IR/MetadataTracking.h @@ -0,0 +1,99 @@ +//===- llvm/IR/MetadataTracking.h - Metadata tracking ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Low-level functions to enable tracking of metadata that could RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_METADATATRACKING_H +#define LLVM_IR_METADATATRACKING_H + +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Casting.h" +#include + +namespace llvm { + +class Metadata; +class MetadataAsValue; + +/// \brief API for tracking metadata references through RAUW and deletion. +/// +/// Shared API for updating \a Metadata pointers in subclasses that support +/// RAUW. +/// +/// This API is not meant to be used directly. See \a TrackingMDRef for a +/// user-friendly tracking reference. +class MetadataTracking { +public: + /// \brief Track the reference to metadata. + /// + /// Register \c MD with \c *MD, if the subclass supports tracking. If \c *MD + /// gets RAUW'ed, \c MD will be updated to the new address. If \c *MD gets + /// deleted, \c MD will be set to \c nullptr. + /// + /// If tracking isn't supported, \c *MD will not change. + /// + /// \return true iff tracking is supported by \c MD. + static bool track(Metadata *&MD) { + return track(&MD, *MD, static_cast(nullptr)); + } + + /// \brief Track the reference to metadata for \a Metadata. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, Metadata &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Track the reference to metadata for \a MetadataAsValue. + /// + /// As \a track(Metadata*&), but with support for calling back to \c Owner to + /// tell it that its operand changed. This could trigger \c Owner being + /// re-uniqued. + static bool track(void *Ref, Metadata &MD, MetadataAsValue &Owner) { + return track(Ref, MD, &Owner); + } + + /// \brief Stop tracking a reference to metadata. + /// + /// Stops \c *MD from tracking \c MD. + static void untrack(Metadata *&MD) { untrack(&MD, *MD); } + static void untrack(void *Ref, Metadata &MD); + + /// \brief Move tracking from one reference to another. + /// + /// Semantically equivalent to \c untrack(MD) followed by \c track(New), + /// except that ownership callbacks are maintained. + /// + /// Note: it is an error if \c *MD does not equal \c New. + /// + /// \return true iff tracking is supported by \c MD. + static bool retrack(Metadata *&MD, Metadata *&New) { + return retrack(&MD, *MD, &New); + } + static bool retrack(void *Ref, Metadata &MD, void *New); + + /// \brief Check whether metadata is replaceable. + static bool isReplaceable(const Metadata &MD); + + typedef PointerUnion OwnerTy; + +private: + /// \brief Track a reference to metadata for an owner. + /// + /// Generalized version of tracking. + static bool track(void *Ref, Metadata &MD, OwnerTy Owner); +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 26f62db..b24023b 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -23,6 +23,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/DataTypes.h" #include @@ -32,8 +33,6 @@ class GVMaterializer; class LLVMContext; class RandomNumberGenerator; class StructType; -template struct DenseMapInfo; -template class DenseMap; template<> struct ilist_traits : public SymbolTableListTraits { @@ -137,6 +136,11 @@ public: /// The Function constant iterator typedef FunctionListType::const_iterator const_iterator; + /// The Function reverse iterator. + typedef FunctionListType::reverse_iterator reverse_iterator; + /// The Function constant reverse iterator. + typedef FunctionListType::const_reverse_iterator const_reverse_iterator; + /// The Global Alias iterators. typedef AliasListType::iterator alias_iterator; /// The Global Alias constant iterator @@ -144,7 +148,7 @@ public: /// The named metadata iterators. typedef NamedMDListType::iterator named_metadata_iterator; - /// The named metadata constant interators. + /// The named metadata constant iterators. typedef NamedMDListType::const_iterator const_named_metadata_iterator; /// This enumeration defines the supported behaviors of module flags. @@ -177,15 +181,23 @@ public: /// Appends the two values, which are required to be metadata /// nodes. However, duplicate entries in the second list are dropped /// during the append operation. - AppendUnique = 6 + AppendUnique = 6, + + // Markers: + ModFlagBehaviorFirstVal = Error, + ModFlagBehaviorLastVal = AppendUnique }; + /// Checks if Metadata represents a valid ModFlagBehavior, and stores the + /// converted result in MFB. + static bool isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB); + struct ModuleFlagEntry { ModFlagBehavior Behavior; MDString *Key; - Value *Val; - ModuleFlagEntry(ModFlagBehavior B, MDString *K, Value *V) - : Behavior(B), Key(K), Val(V) {} + Metadata *Val; + ModuleFlagEntry(ModFlagBehavior B, MDString *K, Metadata *V) + : Behavior(B), Key(K), Val(V) {} }; /// @} @@ -205,9 +217,8 @@ private: Materializer; ///< Used to materialize GlobalValues std::string ModuleID; ///< Human readable identifier for the module std::string TargetTriple; ///< Platform target triple Module compiled on + ///< Format: (arch)(sub)-(vendor)-(sys0-(abi) void *NamedMDSymTab; ///< NamedMDNode names. - // Allow lazy initialization in const method. - mutable RandomNumberGenerator *RNG; ///< The random number generator for this module. // We need to keep the string because the C API expects us to own the string // representation. @@ -237,6 +248,12 @@ public: /// @returns the module identifier as a string const std::string &getModuleIdentifier() const { return ModuleID; } + /// \brief Get a short "name" for the module. + /// + /// This is useful for debugging or logging. It is essentially a convenience + /// wrapper around getModuleIdentifier(). + StringRef getName() const { return ModuleID; } + /// Get the data layout string for the module's target platform. This is /// equivalent to getDataLayout()->getStringRepresentation(). const std::string &getDataLayoutStr() const { return DataLayoutStr; } @@ -256,10 +273,16 @@ public: /// @returns a string containing the module-scope inline assembly blocks. const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } - /// Get the RandomNumberGenerator for this module. The RNG can be - /// seeded via -rng-seed= and is salted with the ModuleID. - /// The returned RNG should not be shared across threads. - RandomNumberGenerator &getRNG() const; + /// Get a RandomNumberGenerator salted for use with this module. The + /// RNG can be seeded via -rng-seed= and is salted with the + /// ModuleID and the provided pass salt. The returned RNG should not + /// be shared across threads or passes. + /// + /// A unique RNG per pass ensures a reproducible random stream even + /// when other randomness consuming passes are added or removed. In + /// addition, the random stream will be reproducible across LLVM + /// versions when the pass does not change. + RandomNumberGenerator *createRNG(const Pass* P) const; /// @} /// @name Module Level Mutators @@ -313,6 +336,8 @@ public: /// name. StructType *getTypeByName(StringRef Name) const; + std::vector getIdentifiedStructTypes() const; + /// @} /// @name Function Accessors /// @{ @@ -339,11 +364,11 @@ public: /// function arguments, which makes it easier for clients to use. Constant *getOrInsertFunction(StringRef Name, AttributeSet AttributeList, - Type *RetTy, ...) END_WITH_NULL; + Type *RetTy, ...) LLVM_END_WITH_NULL; /// Same as above, but without the attributes. Constant *getOrInsertFunction(StringRef Name, Type *RetTy, ...) - END_WITH_NULL; + LLVM_END_WITH_NULL; /// Look up the specified function in the module symbol table. If it does not /// exist, return null. @@ -357,8 +382,11 @@ public: /// does not exist, return null. If AllowInternal is set to true, this /// function will return types that have InternalLinkage. By default, these /// types are not returned. - const GlobalVariable *getGlobalVariable(StringRef Name, - bool AllowInternal = false) const { + GlobalVariable *getGlobalVariable(StringRef Name) const { + return getGlobalVariable(Name, false); + } + + GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal) const { return const_cast(this)->getGlobalVariable(Name, AllowInternal); } @@ -424,7 +452,7 @@ public: /// Return the corresponding value if Key appears in module flags, otherwise /// return null. - Value *getModuleFlag(StringRef Key) const; + Metadata *getModuleFlag(StringRef Key) const; /// Returns the NamedMDNode in the module that represents module-level flags. /// This method returns null if there are no module-level flags. @@ -437,7 +465,8 @@ public: /// Add a module-level flag to the module-level flags metadata. It will create /// the module-level flags named metadata if it doesn't already exist. - void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Value *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Metadata *Val); + void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, Constant *Val); void addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val); void addModuleFlag(MDNode *Node); @@ -456,9 +485,6 @@ public: /// Retrieves the GVMaterializer, if any, for this Module. GVMaterializer *getMaterializer() const { return Materializer.get(); } - /// True if the definition of GV has yet to be materializedfrom the - /// GVMaterializer. - bool isMaterializable(const GlobalValue *GV) const; /// Returns true if this GV was loaded from this Module's GVMaterializer and /// the GVMaterializer knows how to dematerialize the GV. bool isDematerializable(const GlobalValue *GV) const; @@ -466,10 +492,10 @@ public: /// Make sure the GlobalValue is fully read. If the module is corrupt, this /// returns true and fills in the optional string with information about the /// problem. If successful, this returns false. - bool Materialize(GlobalValue *GV, std::string *ErrInfo = nullptr); + std::error_code materialize(GlobalValue *GV); /// If the GlobalValue is read in, and if the GVMaterializer supports it, /// release the memory for the function, and set it up to be materialized - /// lazily. If !isDematerializable(), this method is a noop. + /// lazily. If !isDematerializable(), this method is a no-op. void Dematerialize(GlobalValue *GV); /// Make sure all GlobalValues in this Module are fully read. @@ -478,7 +504,7 @@ public: /// Make sure all GlobalValues in this Module are fully read and clear the /// Materializer. If the module is corrupt, this DOES NOT clear the old /// Materializer. - std::error_code materializeAllPermanently(bool ReleaseBuffer = false); + std::error_code materializeAllPermanently(); /// @} /// @name Direct access to the globals list, functions list, and symbol table @@ -546,9 +572,20 @@ public: const_iterator begin() const { return FunctionList.begin(); } iterator end () { return FunctionList.end(); } const_iterator end () const { return FunctionList.end(); } + reverse_iterator rbegin() { return FunctionList.rbegin(); } + const_reverse_iterator rbegin() const{ return FunctionList.rbegin(); } + reverse_iterator rend() { return FunctionList.rend(); } + const_reverse_iterator rend() const { return FunctionList.rend(); } size_t size() const { return FunctionList.size(); } bool empty() const { return FunctionList.empty(); } + iterator_range functions() { + return iterator_range(begin(), end()); + } + iterator_range functions() const { + return iterator_range(begin(), end()); + } + /// @} /// @name Alias Iteration /// @{ @@ -620,6 +657,15 @@ public: unsigned getDwarfVersion() const; /// @} +/// @name Utility functions for querying and setting PIC level +/// @{ + + /// \brief Returns the PIC level (small or large model) + PICLevel::Level getPICLevel() const; + + /// \brief Set the PIC level (small or large model) + void setPICLevel(PICLevel::Level PL); +/// @} }; /// An raw_ostream inserter for modules. diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index 888cabf..0933f21 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -28,9 +28,8 @@ class GetElementPtrInst; class BinaryOperator; class ConstantExpr; -/// Operator - This is a utility class that provides an abstraction for the -/// common functionality between Instructions and ConstantExprs. -/// +/// This is a utility class that provides an abstraction for the common +/// functionality between Instructions and ConstantExprs. class Operator : public User { private: // The Operator class is intended to be used as a utility, and is never itself @@ -46,17 +45,15 @@ protected: ~Operator(); public: - /// getOpcode - Return the opcode for this Instruction or ConstantExpr. - /// + /// Return the opcode for this Instruction or ConstantExpr. unsigned getOpcode() const { if (const Instruction *I = dyn_cast(this)) return I->getOpcode(); return cast(this)->getOpcode(); } - /// getOpcode - If V is an Instruction or ConstantExpr, return its - /// opcode. Otherwise return UserOp1. - /// + /// If V is an Instruction or ConstantExpr, return its opcode. + /// Otherwise return UserOp1. static unsigned getOpcode(const Value *V) { if (const Instruction *I = dyn_cast(V)) return I->getOpcode(); @@ -72,10 +69,9 @@ public: } }; -/// OverflowingBinaryOperator - Utility class for integer arithmetic operators -/// which may exhibit overflow - Add, Sub, and Mul. It does not include SDiv, -/// despite that operator having the potential for overflow. -/// +/// Utility class for integer arithmetic operators which may exhibit overflow - +/// Add, Sub, and Mul. It does not include SDiv, despite that operator having +/// the potential for overflow. class OverflowingBinaryOperator : public Operator { public: enum { @@ -96,13 +92,13 @@ private: } public: - /// hasNoUnsignedWrap - Test whether this operation is known to never + /// Test whether this operation is known to never /// undergo unsigned overflow, aka the nuw property. bool hasNoUnsignedWrap() const { return SubclassOptionalData & NoUnsignedWrap; } - /// hasNoSignedWrap - Test whether this operation is known to never + /// Test whether this operation is known to never /// undergo signed overflow, aka the nsw property. bool hasNoSignedWrap() const { return (SubclassOptionalData & NoSignedWrap) != 0; @@ -126,8 +122,8 @@ public: } }; -/// PossiblyExactOperator - A udiv or sdiv instruction, which can be marked as -/// "exact", indicating that no bits are destroyed. +/// A udiv or sdiv instruction, which can be marked as "exact", +/// indicating that no bits are destroyed. class PossiblyExactOperator : public Operator { public: enum { @@ -142,8 +138,7 @@ private: } public: - /// isExact - Test whether this division is known to be exact, with - /// zero remainder. + /// Test whether this division is known to be exact, with zero remainder. bool isExact() const { return SubclassOptionalData & IsExact; } @@ -217,7 +212,7 @@ public: }; -/// FPMathOperator - Utility class for floating point operations which can have +/// Utility class for floating point operations which can have /// information about relaxed accuracy requirements attached to them. class FPMathOperator : public Operator { private: @@ -257,11 +252,18 @@ private: (B * FastMathFlags::AllowReciprocal); } - /// Convenience function for setting all the fast-math flags + /// Convenience function for setting multiple fast-math flags. + /// FMF is a mask of the bits to set. void setFastMathFlags(FastMathFlags FMF) { SubclassOptionalData |= FMF.Flags; } + /// Convenience function for copying all fast-math flags. + /// All values in FMF are transferred to this operator. + void copyFastMathFlags(FastMathFlags FMF) { + SubclassOptionalData = FMF.Flags; + } + public: /// Test whether this operation is permitted to be /// algebraically transformed, aka the 'A' fast-math property. @@ -312,8 +314,7 @@ public: }; -/// ConcreteOperator - A helper template for defining operators for individual -/// opcodes. +/// A helper template for defining operators for individual opcodes. template class ConcreteOperator : public SuperClass { public: @@ -357,6 +358,8 @@ class LShrOperator }; +class ZExtOperator : public ConcreteOperator {}; + class GEPOperator : public ConcreteOperator { @@ -372,8 +375,7 @@ class GEPOperator } public: - /// isInBounds - Test whether this is an inbounds GEP, as defined - /// by LangRef.html. + /// Test whether this is an inbounds GEP, as defined by LangRef.html. bool isInBounds() const { return SubclassOptionalData & IsInBounds; } @@ -393,16 +395,14 @@ public: return 0U; // get index for modifying correct operand } - /// getPointerOperandType - Method to return the pointer operand as a - /// PointerType. + /// Method to return the pointer operand as a PointerType. Type *getPointerOperandType() const { return getPointerOperand()->getType(); } - /// getPointerAddressSpace - Method to return the address space of the - /// pointer operand. + /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { - return cast(getPointerOperandType())->getAddressSpace(); + return getPointerOperandType()->getPointerAddressSpace(); } unsigned getNumIndices() const { // Note: always non-negative @@ -413,8 +413,8 @@ public: return getNumOperands() > 1; } - /// hasAllZeroIndices - Return true if all of the indices of this GEP are - /// zeros. If so, the result pointer and the first operand have the same + /// Return true if all of the indices of this GEP are zeros. + /// If so, the result pointer and the first operand have the same /// value, just potentially different types. bool hasAllZeroIndices() const { for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { @@ -426,8 +426,8 @@ public: return true; } - /// hasAllConstantIndices - Return true if all of the indices of this GEP are - /// constant integers. If so, the result pointer and the first operand have + /// Return true if all of the indices of this GEP are constant integers. + /// If so, the result pointer and the first operand have /// a constant offset between them. bool hasAllConstantIndices() const { for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { @@ -493,14 +493,12 @@ public: return 0U; // get index for modifying correct operand } - /// getPointerOperandType - Method to return the pointer operand as a - /// PointerType. + /// Method to return the pointer operand as a PointerType. Type *getPointerOperandType() const { return getPointerOperand()->getType(); } - /// getPointerAddressSpace - Method to return the address space of the - /// pointer operand. + /// Method to return the address space of the pointer operand. unsigned getPointerAddressSpace() const { return cast(getPointerOperandType())->getAddressSpace(); } diff --git a/include/llvm/IR/PassManager.h b/include/llvm/IR/PassManager.h index cc2a80b..2625768 100644 --- a/include/llvm/IR/PassManager.h +++ b/include/llvm/IR/PassManager.h @@ -35,14 +35,17 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_PASS_MANAGER_H -#define LLVM_IR_PASS_MANAGER_H +#ifndef LLVM_IR_PASSMANAGER_H +#define LLVM_IR_PASSMANAGER_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Function.h" #include "llvm/IR/Module.h" +#include "llvm/IR/PassManagerInternal.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/type_traits.h" #include #include @@ -91,9 +94,12 @@ public: } /// \brief Mark a particular pass as preserved, adding it to the set. - template void preserve() { + template void preserve() { preserve(PassT::ID()); } + + /// \brief Mark an abstract PassID as preserved, adding it to the set. + void preserve(void *PassID) { if (!areAllPreserved()) - PreservedPassIDs.insert(PassT::ID()); + PreservedPassIDs.insert(PassID); } /// \brief Intersect this set with another in place. @@ -107,11 +113,9 @@ public: PreservedPassIDs = Arg.PreservedPassIDs; return; } - for (SmallPtrSet::const_iterator I = PreservedPassIDs.begin(), - E = PreservedPassIDs.end(); - I != E; ++I) - if (!Arg.PreservedPassIDs.count(*I)) - PreservedPassIDs.erase(*I); + for (void *P : PreservedPassIDs) + if (!Arg.PreservedPassIDs.count(P)) + PreservedPassIDs.erase(P); } /// \brief Intersect this set with a temporary other set in place. @@ -125,11 +129,9 @@ public: PreservedPassIDs = std::move(Arg.PreservedPassIDs); return; } - for (SmallPtrSet::const_iterator I = PreservedPassIDs.begin(), - E = PreservedPassIDs.end(); - I != E; ++I) - if (!Arg.PreservedPassIDs.count(*I)) - PreservedPassIDs.erase(*I); + for (void *P : PreservedPassIDs) + if (!Arg.PreservedPassIDs.count(P)) + PreservedPassIDs.erase(P); } /// \brief Query whether a pass is marked as preserved by this set. @@ -144,408 +146,115 @@ public: PreservedPassIDs.count(PassID); } + /// \brief Test whether all passes are preserved. + /// + /// This is used primarily to optimize for the case of no changes which will + /// common in many scenarios. + bool areAllPreserved() const { + return PreservedPassIDs.count((void *)AllPassesID); + } + private: // Note that this must not be -1 or -2 as those are already used by the // SmallPtrSet. static const uintptr_t AllPassesID = (intptr_t)(-3); - bool areAllPreserved() const { - return PreservedPassIDs.count((void *)AllPassesID); - } - SmallPtrSet PreservedPassIDs; }; -/// \brief Implementation details of the pass manager interfaces. -namespace detail { - -/// \brief Template for the abstract base class used to dispatch -/// polymorphically over pass objects. -template struct PassConcept { - // Boiler plate necessary for the container of derived classes. - virtual ~PassConcept() {} - - /// \brief The polymorphic API which runs the pass over a given IR entity. - /// - /// Note that actual pass object can omit the analysis manager argument if - /// desired. Also that the analysis manager may be null if there is no - /// analysis manager in the pass pipeline. - virtual PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) = 0; - - /// \brief Polymorphic method to access the name of a pass. - virtual StringRef name() = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c PassT has a run method -/// accepting an \c AnalysisManagerT. -template -class PassRunAcceptsAnalysisManager { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); +// Forward declare the analysis manager template. +template class AnalysisManager; -public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief A template wrapper used to implement the polymorphic API. +/// \brief Manages a sequence of passes over units of IR. /// -/// Can be instantiated for any object which provides a \c run method accepting -/// an \c IRUnitT. It requires the pass to be a copyable object. When the -/// \c run method also accepts an \c AnalysisManagerT*, we pass it along. -template ::Value> -struct PassModel; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR, AM); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Specialization of \c PassModel for passes that accept an analyis -/// manager. -template -struct PassModel - : PassConcept { - explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} - PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(PassModel &LHS, PassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - PassModel &operator=(PassModel RHS) { - swap(*this, RHS); - return *this; - } - - PreservedAnalyses run(IRUnitT IR, AnalysisManagerT *AM) override { - return Pass.run(IR); - } - StringRef name() override { return PassT::name(); } - PassT Pass; -}; - -/// \brief Abstract concept of an analysis result. +/// A pass manager contains a sequence of passes to run over units of IR. It is +/// itself a valid pass over that unit of IR, and when over some given IR will +/// run each pass in sequence. This is the primary and most basic building +/// block of a pass pipeline. /// -/// This concept is parameterized over the IR unit that this result pertains -/// to. -template struct AnalysisResultConcept { - virtual ~AnalysisResultConcept() {} - - /// \brief Method to try and mark a result as invalid. - /// - /// When the outer analysis manager detects a change in some underlying - /// unit of the IR, it will call this method on all of the results cached. - /// - /// This method also receives a set of preserved analyses which can be used - /// to avoid invalidation because the pass which changed the underlying IR - /// took care to update or preserve the analysis result in some way. - /// - /// \returns true if the result is indeed invalid (the default). - virtual bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) = 0; -}; - -/// \brief SFINAE metafunction for computing whether \c ResultT provides an -/// \c invalidate member function. -template class ResultHasInvalidateMethod { - typedef char SmallType; - struct BigType { - char a, b; - }; - - template - struct Checker; - - template static SmallType f(Checker *); - template static BigType f(...); - +/// If it is run with an \c AnalysisManager argument, it will propagate +/// that analysis manager to each pass it runs, as well as calling the analysis +/// manager's invalidation routine with the PreservedAnalyses of each pass it +/// runs. +template class PassManager { public: - enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; -}; - -/// \brief Wrapper to model the analysis result concept. -/// -/// By default, this will implement the invalidate method with a trivial -/// implementation so that the actual analysis result doesn't need to provide -/// an invalidation handler. It is only selected when the invalidation handler -/// is not part of the ResultT's interface. -template ::Value> -struct AnalysisResultModel; - -/// \brief Specialization of \c AnalysisResultModel which provides the default -/// invalidate functionality. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// \brief The model bases invalidation solely on being in the preserved set. - // - // FIXME: We should actually use two different concepts for analysis results - // rather than two different models, and avoid the indirect function call for - // ones that use the trivial behavior. - bool invalidate(IRUnitT, const PreservedAnalyses &PA) override { - return !PA.preserved(PassT::ID()); - } - - ResultT Result; -}; - -/// \brief Specialization of \c AnalysisResultModel which delegates invalidate -/// handling to \c ResultT. -template -struct AnalysisResultModel - : AnalysisResultConcept { - explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} - AnalysisResultModel(AnalysisResultModel &&Arg) - : Result(std::move(Arg.Result)) {} - friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { - using std::swap; - swap(LHS.Result, RHS.Result); - } - AnalysisResultModel &operator=(AnalysisResultModel RHS) { - swap(*this, RHS); - return *this; - } - - /// \brief The model delegates to the \c ResultT method. - bool invalidate(IRUnitT IR, const PreservedAnalyses &PA) override { - return Result.invalidate(IR, PA); - } - - ResultT Result; -}; - -/// \brief Abstract concept of an analysis pass. -/// -/// This concept is parameterized over the IR unit that it can run over and -/// produce an analysis result. -template -struct AnalysisPassConcept { - virtual ~AnalysisPassConcept() {} - - /// \brief Method to run this analysis over a unit of IR. - /// \returns A unique_ptr to the analysis result object to be queried by - /// users. - virtual std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) = 0; -}; - -/// \brief Wrapper to model the analysis pass concept. -/// -/// Can wrap any type which implements a suitable \c run method. The method -/// must accept the IRUnitT as an argument and produce an object which can be -/// wrapped in a \c AnalysisResultModel. -template ::Value> -struct AnalysisPassModel; - -/// \brief Specialization of \c AnalysisPassModel which passes an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + /// \brief Construct a pass manager. + /// + /// It can be passed a flag to get debug logging as the passes are run. + PassManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); + PassManager(PassManager &&Arg) + : Passes(std::move(Arg.Passes)), + DebugLogging(std::move(Arg.DebugLogging)) {} + PassManager &operator=(PassManager &&RHS) { + Passes = std::move(RHS.Passes); + DebugLogging = std::move(RHS.DebugLogging); return *this; } - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; - - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *AM) override { - return make_unique(Pass.run(IR, AM)); - } + /// \brief Run all of the passes in this manager over the IR. + PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM = nullptr) { + PreservedAnalyses PA = PreservedAnalyses::all(); - PassT Pass; -}; + if (DebugLogging) + dbgs() << "Starting pass manager run.\n"; -/// \brief Specialization of \c AnalysisPassModel which does not pass an -/// \c AnalysisManager to PassT's run method. -template -struct AnalysisPassModel - : AnalysisPassConcept { - explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} - AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { - using std::swap; - swap(LHS.Pass, RHS.Pass); - } - AnalysisPassModel &operator=(AnalysisPassModel RHS) { - swap(*this, RHS); - return *this; - } + for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { + if (DebugLogging) + dbgs() << "Running pass: " << Passes[Idx]->name() << "\n"; - // FIXME: Replace PassT::Result with type traits when we use C++11. - typedef AnalysisResultModel - ResultModelT; + PreservedAnalyses PassPA = Passes[Idx]->run(IR, AM); - /// \brief The model delegates to the \c PassT::run method. - /// - /// The return is wrapped in an \c AnalysisResultModel. - std::unique_ptr> - run(IRUnitT IR, AnalysisManagerT *) override { - return make_unique(Pass.run(IR)); - } + // If we have an active analysis manager at this level we want to ensure + // we update it as each pass runs and potentially invalidates analyses. + // We also update the preserved set of analyses based on what analyses we + // have already handled the invalidation for here and don't need to + // invalidate when finished. + if (AM) + PassPA = AM->invalidate(IR, std::move(PassPA)); - PassT Pass; -}; + // Finally, we intersect the final preserved analyses to compute the + // aggregate preserved set for this pass manager. + PA.intersect(std::move(PassPA)); -} // End namespace detail + // FIXME: Historically, the pass managers all called the LLVM context's + // yield function here. We don't have a generic way to acquire the + // context and it isn't yet clear what the right pattern is for yielding + // in the new pass manager so it is currently omitted. + //IR.getContext().yield(); + } -class ModuleAnalysisManager; + if (DebugLogging) + dbgs() << "Finished pass manager run.\n"; -class ModulePassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModulePassManager() {} - ModulePassManager(ModulePassManager &&Arg) : Passes(std::move(Arg.Passes)) {} - ModulePassManager &operator=(ModulePassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; + return PA; } - /// \brief Run all of the module passes in this module pass manager over - /// a module. - /// - /// This method should only be called for a single module as there is the - /// expectation that the lifetime of a pass is bounded to that of a module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM = nullptr); - - template void addPass(ModulePassT Pass) { - Passes.emplace_back(new ModulePassModel(std::move(Pass))); + template void addPass(PassT Pass) { + typedef detail::PassModel PassModelT; + Passes.emplace_back(new PassModelT(std::move(Pass))); } - static StringRef name() { return "ModulePassManager"; } + static StringRef name() { return "PassManager"; } private: - // Pull in the concept type and model template specialized for modules. - typedef detail::PassConcept - ModulePassConcept; - template - struct ModulePassModel - : detail::PassModel { - ModulePassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; + typedef detail::PassConcept PassConceptT; - ModulePassManager(const ModulePassManager &) LLVM_DELETED_FUNCTION; - ModulePassManager &operator=(const ModulePassManager &) LLVM_DELETED_FUNCTION; + PassManager(const PassManager &) LLVM_DELETED_FUNCTION; + PassManager &operator=(const PassManager &) LLVM_DELETED_FUNCTION; - std::vector> Passes; -}; - -class FunctionAnalysisManager; + std::vector> Passes; -class FunctionPassManager { -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - FunctionPassManager() {} - FunctionPassManager(FunctionPassManager &&Arg) - : Passes(std::move(Arg.Passes)) {} - FunctionPassManager &operator=(FunctionPassManager &&RHS) { - Passes = std::move(RHS.Passes); - return *this; - } - - template void addPass(FunctionPassT Pass) { - Passes.emplace_back(new FunctionPassModel(std::move(Pass))); - } - - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM = nullptr); - - static StringRef name() { return "FunctionPassManager"; } - -private: - // Pull in the concept type and model template specialized for functions. - typedef detail::PassConcept - FunctionPassConcept; - template - struct FunctionPassModel - : detail::PassModel { - FunctionPassModel(PassT Pass) - : detail::PassModel( - std::move(Pass)) {} - }; + /// \brief Flag indicating whether we should do debug logging. + bool DebugLogging; +}; - FunctionPassManager(const FunctionPassManager &) LLVM_DELETED_FUNCTION; - FunctionPassManager & - operator=(const FunctionPassManager &) LLVM_DELETED_FUNCTION; +/// \brief Convenience typedef for a pass manager over modules. +typedef PassManager ModulePassManager; - std::vector> Passes; -}; +/// \brief Convenience typedef for a pass manager over functions. +typedef PassManager FunctionPassManager; namespace detail { @@ -560,6 +269,12 @@ namespace detail { /// - invalidateImpl /// /// The details of the call pattern are within. +/// +/// Note that there is also a generic analysis manager template which implements +/// the above required functions along with common datastructures used for +/// managing analyses. This base class is factored so that if you need to +/// customize the handling of a specific IR unit, you can do so without +/// replicating *all* of the boilerplate. template class AnalysisManagerBase { DerivedT *derived_this() { return static_cast(this); } const DerivedT *derived_this() const { @@ -572,7 +287,7 @@ template class AnalysisManagerBase { protected: typedef detail::AnalysisResultConcept ResultConceptT; - typedef detail::AnalysisPassConcept PassConceptT; + typedef detail::AnalysisPassConcept PassConceptT; // FIXME: Provide template aliases for the models when we're using C++11 in // a mode supporting them. @@ -592,7 +307,7 @@ public: /// /// If there is not a valid cached result in the manager already, this will /// re-run the analysis to produce a valid result. - template typename PassT::Result &getResult(IRUnitT IR) { + template typename PassT::Result &getResult(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -609,7 +324,7 @@ public: /// /// \returns null if there is no cached result. template - typename PassT::Result *getCachedResult(IRUnitT IR) const { + typename PassT::Result *getCachedResult(IRUnitT &IR) const { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being queried"); @@ -631,25 +346,28 @@ public: template void registerPass(PassT Pass) { assert(!AnalysisPasses.count(PassT::ID()) && "Registered the same analysis pass twice!"); - typedef detail::AnalysisPassModel PassModelT; + typedef detail::AnalysisPassModel PassModelT; AnalysisPasses[PassT::ID()].reset(new PassModelT(std::move(Pass))); } /// \brief Invalidate a specific analysis pass for an IR module. /// /// Note that the analysis result can disregard invalidation. - template void invalidate(Module *M) { + template void invalidate(IRUnitT &IR) { assert(AnalysisPasses.count(PassT::ID()) && "This analysis pass was not registered prior to being invalidated"); - derived_this()->invalidateImpl(PassT::ID(), M); + derived_this()->invalidateImpl(PassT::ID(), IR); } /// \brief Invalidate analyses cached for an IR unit. /// /// Walk through all of the analyses pertaining to this unit of IR and /// invalidate them unless they are preserved by the PreservedAnalyses set. - void invalidate(IRUnitT IR, const PreservedAnalyses &PA) { - derived_this()->invalidateImpl(IR, PA); + /// We accept the PreservedAnalyses set by value and update it with each + /// analyis pass which has been successfully invalidated and thus can be + /// preserved going forward. The updated set is returned. + PreservedAnalyses invalidate(IRUnitT &IR, PreservedAnalyses PA) { + return derived_this()->invalidateImpl(IR, std::move(PA)); } protected: @@ -679,108 +397,153 @@ private: } // End namespace detail -/// \brief A module analysis pass manager with lazy running and caching of +/// \brief A generic analysis pass manager with lazy running and caching of /// results. -class ModuleAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; - -public: - // We have to explicitly define all the special member functions because MSVC - // refuses to generate them. - ModuleAnalysisManager() {} - ModuleAnalysisManager(ModuleAnalysisManager &&Arg) - : BaseT(std::move(static_cast(Arg))), - ModuleAnalysisResults(std::move(Arg.ModuleAnalysisResults)) {} - ModuleAnalysisManager &operator=(ModuleAnalysisManager &&RHS) { - BaseT::operator=(std::move(static_cast(RHS))); - ModuleAnalysisResults = std::move(RHS.ModuleAnalysisResults); - return *this; - } - -private: - ModuleAnalysisManager(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - ModuleAnalysisManager & - operator=(const ModuleAnalysisManager &) LLVM_DELETED_FUNCTION; - - /// \brief Get a module pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Module *M); - - /// \brief Get a cached module pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Module *M) const; - - /// \brief Invalidate a module pass result. - void invalidateImpl(void *PassID, Module *M); - - /// \brief Invalidate results across a module. - void invalidateImpl(Module *M, const PreservedAnalyses &PA); - - /// \brief Map type from module analysis pass ID to pass result concept - /// pointer. - typedef DenseMap>> - ModuleAnalysisResultMapT; - - /// \brief Cache of computed module analysis results for this module. - ModuleAnalysisResultMapT ModuleAnalysisResults; -}; - -/// \brief A function analysis manager to coordinate and cache analyses run over -/// a module. -class FunctionAnalysisManager - : public detail::AnalysisManagerBase { - friend class detail::AnalysisManagerBase; - typedef detail::AnalysisManagerBase - BaseT; - typedef BaseT::ResultConceptT ResultConceptT; - typedef BaseT::PassConceptT PassConceptT; +/// +/// This analysis manager can be used for any IR unit where the address of the +/// IR unit sufficies as its identity. It manages the cache for a unit of IR via +/// the address of each unit of IR cached. +template +class AnalysisManager + : public detail::AnalysisManagerBase, IRUnitT> { + friend class detail::AnalysisManagerBase, IRUnitT>; + typedef detail::AnalysisManagerBase, IRUnitT> BaseT; + typedef typename BaseT::ResultConceptT ResultConceptT; + typedef typename BaseT::PassConceptT PassConceptT; public: // Most public APIs are inherited from the CRTP base class. + /// \brief Construct an empty analysis manager. + /// + /// A flag can be passed to indicate that the manager should perform debug + /// logging. + AnalysisManager(bool DebugLogging = false) : DebugLogging(DebugLogging) {} + // We have to explicitly define all the special member functions because MSVC // refuses to generate them. - FunctionAnalysisManager() {} - FunctionAnalysisManager(FunctionAnalysisManager &&Arg) + AnalysisManager(AnalysisManager &&Arg) : BaseT(std::move(static_cast(Arg))), - FunctionAnalysisResults(std::move(Arg.FunctionAnalysisResults)) {} - FunctionAnalysisManager &operator=(FunctionAnalysisManager &&RHS) { + AnalysisResults(std::move(Arg.AnalysisResults)), + DebugLogging(std::move(Arg.DebugLogging)) {} + AnalysisManager &operator=(AnalysisManager &&RHS) { BaseT::operator=(std::move(static_cast(RHS))); - FunctionAnalysisResults = std::move(RHS.FunctionAnalysisResults); + AnalysisResults = std::move(RHS.AnalysisResults); + DebugLogging = std::move(RHS.DebugLogging); return *this; } /// \brief Returns true if the analysis manager has an empty results cache. - bool empty() const; + bool empty() const { + assert(AnalysisResults.empty() == AnalysisResultLists.empty() && + "The storage and index of analysis results disagree on how many " + "there are!"); + return AnalysisResults.empty(); + } - /// \brief Clear the function analysis result cache. + /// \brief Clear the analysis result cache. /// - /// This routine allows cleaning up when the set of functions itself has + /// This routine allows cleaning up when the set of IR units itself has /// potentially changed, and thus we can't even look up a a result and - /// invalidate it directly. Notably, this does *not* call invalidate - /// functions as there is nothing to be done for them. - void clear(); + /// invalidate it directly. Notably, this does *not* call invalidate functions + /// as there is nothing to be done for them. + void clear() { + AnalysisResults.clear(); + AnalysisResultLists.clear(); + } private: - FunctionAnalysisManager(const FunctionAnalysisManager &) - LLVM_DELETED_FUNCTION; - FunctionAnalysisManager & - operator=(const FunctionAnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager(const AnalysisManager &) LLVM_DELETED_FUNCTION; + AnalysisManager &operator=(const AnalysisManager &) LLVM_DELETED_FUNCTION; + + /// \brief Get an analysis result, running the pass if necessary. + ResultConceptT &getResultImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI; + bool Inserted; + std::tie(RI, Inserted) = AnalysisResults.insert(std::make_pair( + std::make_pair(PassID, &IR), typename AnalysisResultListT::iterator())); + + // If we don't have a cached result for this function, look up the pass and + // run it to produce a result, which we then add to the cache. + if (Inserted) { + auto &P = this->lookupPass(PassID); + if (DebugLogging) + dbgs() << "Running analysis: " << P.name() << "\n"; + AnalysisResultListT &ResultList = AnalysisResultLists[&IR]; + ResultList.emplace_back(PassID, P.run(IR, this)); + RI->second = std::prev(ResultList.end()); + } - /// \brief Get a function pass result, running the pass if necessary. - ResultConceptT &getResultImpl(void *PassID, Function *F); + return *RI->second->second; + } - /// \brief Get a cached function pass result or return null. - ResultConceptT *getCachedResultImpl(void *PassID, Function *F) const; + /// \brief Get a cached analysis result or return null. + ResultConceptT *getCachedResultImpl(void *PassID, IRUnitT &IR) const { + typename AnalysisResultMapT::const_iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + return RI == AnalysisResults.end() ? nullptr : &*RI->second->second; + } /// \brief Invalidate a function pass result. - void invalidateImpl(void *PassID, Function *F); + void invalidateImpl(void *PassID, IRUnitT &IR) { + typename AnalysisResultMapT::iterator RI = + AnalysisResults.find(std::make_pair(PassID, &IR)); + if (RI == AnalysisResults.end()) + return; + + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + AnalysisResultLists[&IR].erase(RI->second); + AnalysisResults.erase(RI); + } /// \brief Invalidate the results for a function.. - void invalidateImpl(Function *F, const PreservedAnalyses &PA); + PreservedAnalyses invalidateImpl(IRUnitT &IR, PreservedAnalyses PA) { + // Short circuit for a common case of all analyses being preserved. + if (PA.areAllPreserved()) + return std::move(PA); + + if (DebugLogging) + dbgs() << "Invalidating all non-preserved analyses for: " + << IR.getName() << "\n"; + + // Clear all the invalidated results associated specifically with this + // function. + SmallVector InvalidatedPassIDs; + AnalysisResultListT &ResultsList = AnalysisResultLists[&IR]; + for (typename AnalysisResultListT::iterator I = ResultsList.begin(), + E = ResultsList.end(); + I != E;) { + void *PassID = I->first; + + // Pass the invalidation down to the pass itself to see if it thinks it is + // necessary. The analysis pass can return false if no action on the part + // of the analysis manager is required for this invalidation event. + if (I->second->invalidate(IR, PA)) { + if (DebugLogging) + dbgs() << "Invalidating analysis: " << this->lookupPass(PassID).name() + << "\n"; + + InvalidatedPassIDs.push_back(I->first); + I = ResultsList.erase(I); + } else { + ++I; + } + + // After handling each pass, we mark it as preserved. Once we've + // invalidated any stale results, the rest of the system is allowed to + // start preserving this analysis again. + PA.preserve(PassID); + } + while (!InvalidatedPassIDs.empty()) + AnalysisResults.erase( + std::make_pair(InvalidatedPassIDs.pop_back_val(), &IR)); + if (ResultsList.empty()) + AnalysisResultLists.erase(&IR); + + return std::move(PA); + } /// \brief List of function analysis pass IDs and associated concept pointers. /// @@ -788,30 +551,37 @@ private: /// erases. Provides both the pass ID and concept pointer such that it is /// half of a bijection and provides storage for the actual result concept. typedef std::list>>> - FunctionAnalysisResultListT; + void *, std::unique_ptr>>> + AnalysisResultListT; /// \brief Map type from function pointer to our custom list type. - typedef DenseMap - FunctionAnalysisResultListMapT; + typedef DenseMap AnalysisResultListMapT; /// \brief Map from function to a list of function analysis results. /// /// Provides linear time removal of all analysis results for a function and /// the ultimate storage for a particular cached analysis result. - FunctionAnalysisResultListMapT FunctionAnalysisResultLists; + AnalysisResultListMapT AnalysisResultLists; /// \brief Map type from a pair of analysis ID and function pointer to an /// iterator into a particular result list. - typedef DenseMap, - FunctionAnalysisResultListT::iterator> - FunctionAnalysisResultMapT; + typedef DenseMap, + typename AnalysisResultListT::iterator> AnalysisResultMapT; /// \brief Map from an analysis ID and function to a particular cached /// analysis result. - FunctionAnalysisResultMapT FunctionAnalysisResults; + AnalysisResultMapT AnalysisResults; + + /// \brief A flag indicating whether debug logging is enabled. + bool DebugLogging; }; +/// \brief Convenience typedef for the Module analysis manager. +typedef AnalysisManager ModuleAnalysisManager; + +/// \brief Convenience typedef for the Function analysis manager. +typedef AnalysisManager FunctionAnalysisManager; + /// \brief A module analysis which acts as a proxy for a function analysis /// manager. /// @@ -826,6 +596,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "FunctionAnalysisManagerModuleProxy"; } + explicit FunctionAnalysisManagerModuleProxy(FunctionAnalysisManager &FAM) : FAM(&FAM) {} // We have to explicitly define all the special member functions because MSVC @@ -850,7 +622,7 @@ public: /// In debug builds, it will also assert that the analysis manager is empty /// as no queries should arrive at the function analysis manager prior to /// this analysis being requested. - Result run(Module *M); + Result run(Module &M); private: static char PassID; @@ -888,7 +660,7 @@ public: /// Regardless of whether this analysis is marked as preserved, all of the /// analyses in the \c FunctionAnalysisManager are potentially invalidated /// based on the set of preserved analyses. - bool invalidate(Module *M, const PreservedAnalyses &PA); + bool invalidate(Module &M, const PreservedAnalyses &PA); private: FunctionAnalysisManager *FAM; @@ -924,7 +696,7 @@ public: const ModuleAnalysisManager &getManager() const { return *MAM; } /// \brief Handle invalidation by ignoring it, this pass is immutable. - bool invalidate(Function *) { return false; } + bool invalidate(Function &) { return false; } private: const ModuleAnalysisManager *MAM; @@ -932,6 +704,8 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "ModuleAnalysisManagerFunctionProxy"; } + ModuleAnalysisManagerFunctionProxy(const ModuleAnalysisManager &MAM) : MAM(&MAM) {} // We have to explicitly define all the special member functions because MSVC @@ -950,7 +724,7 @@ public: /// \brief Run the analysis pass and create our proxy result object. /// Nothing to see here, it just forwards the \c MAM reference into the /// result. - Result run(Function *) { return Result(*MAM); } + Result run(Function &) { return Result(*MAM); } private: static char PassID; @@ -966,6 +740,20 @@ private: /// \c FunctionAnalysisManagerModuleProxy analysis prior to running the function /// pass over the module to enable a \c FunctionAnalysisManager to be used /// within this run safely. +/// +/// Function passes run within this adaptor can rely on having exclusive access +/// to the function they are run over. They should not read or modify any other +/// functions! Other threads or systems may be manipulating other functions in +/// the module, and so their state should never be relied on. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. +/// +/// Function passes can also read the module containing the function, but they +/// should not modify that module outside of the use lists of various globals. +/// For example, a function pass is not permitted to add functions to the +/// module. +/// FIXME: Make the above true for all of LLVM's actual passes, some still +/// violate this principle. template class ModuleToFunctionPassAdaptor { public: explicit ModuleToFunctionPassAdaptor(FunctionPassT Pass) @@ -976,7 +764,8 @@ public: : Pass(Arg.Pass) {} ModuleToFunctionPassAdaptor(ModuleToFunctionPassAdaptor &&Arg) : Pass(std::move(Arg.Pass)) {} - friend void swap(ModuleToFunctionPassAdaptor &LHS, ModuleToFunctionPassAdaptor &RHS) { + friend void swap(ModuleToFunctionPassAdaptor &LHS, + ModuleToFunctionPassAdaptor &RHS) { using std::swap; swap(LHS.Pass, RHS.Pass); } @@ -986,21 +775,23 @@ public: } /// \brief Runs the function pass across every function in the module. - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { FunctionAnalysisManager *FAM = nullptr; if (AM) // Setup the function analysis manager from its proxy. FAM = &AM->getResult(M).getManager(); PreservedAnalyses PA = PreservedAnalyses::all(); - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { - PreservedAnalyses PassPA = Pass.run(I, FAM); + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + PreservedAnalyses PassPA = Pass.run(*I, FAM); // We know that the function pass couldn't have invalidated any other // function's analyses (that's the contract of a function pass), so - // directly handle the function analysis manager's invalidation here. + // directly handle the function analysis manager's invalidation here and + // update our preserved set to reflect that these have already been + // handled. if (FAM) - FAM->invalidate(I, PassPA); + PassPA = FAM->invalidate(*I, std::move(PassPA)); // Then intersect the preserved set so that invalidation of module // analyses will eventually occur when the module pass completes. @@ -1029,6 +820,66 @@ createModuleToFunctionPassAdaptor(FunctionPassT Pass) { return std::move(ModuleToFunctionPassAdaptor(std::move(Pass))); } +/// \brief A template utility pass to force an analysis result to be available. +/// +/// This is a no-op pass which simply forces a specific analysis pass's result +/// to be available when it is run. +template struct RequireAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + (void)AM->template getResult(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "RequireAnalysisPass"; } +}; + +/// \brief A template utility pass to force an analysis result to be +/// invalidated. +/// +/// This is a no-op pass which simply forces a specific analysis result to be +/// invalidated when it is run. +template struct InvalidateAnalysisPass { + /// \brief Run this pass over some unit of IR. + /// + /// This pass can be run over any unit of IR and use any analysis manager + /// provided they satisfy the basic API requirements. When this pass is + /// created, these methods can be instantiated to satisfy whatever the + /// context requires. + template + PreservedAnalyses run(IRUnitT &Arg, AnalysisManager *AM) { + if (AM) + // We have to directly invalidate the analysis result as we can't + // enumerate all other analyses and use the preserved set to control it. + (void)AM->template invalidate(Arg); + + return PreservedAnalyses::all(); + } + + static StringRef name() { return "InvalidateAnalysisPass"; } +}; + +/// \brief A utility pass that does nothing but preserves no analyses. +/// +/// As a consequence fo not preserving any analyses, this pass will force all +/// analysis passes to be re-run to produce fresh results if any are needed. +struct InvalidateAllAnalysesPass { + /// \brief Run this pass over some unit of IR. + template PreservedAnalyses run(IRUnitT &Arg) { + return PreservedAnalyses::none(); + } + + static StringRef name() { return "InvalidateAllAnalysesPass"; } +}; + } #endif diff --git a/include/llvm/IR/PassManagerInternal.h b/include/llvm/IR/PassManagerInternal.h new file mode 100644 index 0000000..297f5f4 --- /dev/null +++ b/include/llvm/IR/PassManagerInternal.h @@ -0,0 +1,349 @@ +//===- PassManager internal APIs and implementation details -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This header provides internal APIs and implementation details used by the +/// pass management interfaces exposed in PassManager.h. To understand more +/// context of why these particular interfaces are needed, see that header +/// file. None of these APIs should be used elsewhere. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_PASSMANAGERINTERNAL_H +#define LLVM_IR_PASSMANAGERINTERNAL_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { + +template class AnalysisManager; +class PreservedAnalyses; + +/// \brief Implementation details of the pass manager interfaces. +namespace detail { + +/// \brief Template for the abstract base class used to dispatch +/// polymorphically over pass objects. +template struct PassConcept { + // Boiler plate necessary for the container of derived classes. + virtual ~PassConcept() {} + + /// \brief The polymorphic API which runs the pass over a given IR entity. + /// + /// Note that actual pass object can omit the analysis manager argument if + /// desired. Also that the analysis manager may be null if there is no + /// analysis manager in the pass pipeline. + virtual PreservedAnalyses run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c PassT has a run method +/// accepting an \c AnalysisManager. +template +class PassRunAcceptsAnalysisManager { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template *)> + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief A template wrapper used to implement the polymorphic API. +/// +/// Can be instantiated for any object which provides a \c run method accepting +/// an \c IRUnitT. It requires the pass to be a copyable object. When the +/// \c run method also accepts an \c AnalysisManager*, we pass it +/// along. +template ::Value> +struct PassModel; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR, AM); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Specialization of \c PassModel for passes that accept an analyis +/// manager. +template +struct PassModel + : PassConcept { + explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + PassModel(const PassModel &Arg) : Pass(Arg.Pass) {} + PassModel(PassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(PassModel &LHS, PassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + PassModel &operator=(PassModel RHS) { + swap(*this, RHS); + return *this; + } + + PreservedAnalysesT run(IRUnitT &IR, AnalysisManager *AM) override { + return Pass.run(IR); + } + StringRef name() override { return PassT::name(); } + PassT Pass; +}; + +/// \brief Abstract concept of an analysis result. +/// +/// This concept is parameterized over the IR unit that this result pertains +/// to. +template struct AnalysisResultConcept { + virtual ~AnalysisResultConcept() {} + + /// \brief Method to try and mark a result as invalid. + /// + /// When the outer analysis manager detects a change in some underlying + /// unit of the IR, it will call this method on all of the results cached. + /// + /// This method also receives a set of preserved analyses which can be used + /// to avoid invalidation because the pass which changed the underlying IR + /// took care to update or preserve the analysis result in some way. + /// + /// \returns true if the result is indeed invalid (the default). + virtual bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA) = 0; +}; + +/// \brief SFINAE metafunction for computing whether \c ResultT provides an +/// \c invalidate member function. +template class ResultHasInvalidateMethod { + typedef char SmallType; + struct BigType { + char a, b; + }; + + template + struct Checker; + + template static SmallType f(Checker *); + template static BigType f(...); + +public: + enum { Value = sizeof(f(nullptr)) == sizeof(SmallType) }; +}; + +/// \brief Wrapper to model the analysis result concept. +/// +/// By default, this will implement the invalidate method with a trivial +/// implementation so that the actual analysis result doesn't need to provide +/// an invalidation handler. It is only selected when the invalidation handler +/// is not part of the ResultT's interface. +template ::Value> +struct AnalysisResultModel; + +/// \brief Specialization of \c AnalysisResultModel which provides the default +/// invalidate functionality. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model bases invalidation solely on being in the preserved set. + // + // FIXME: We should actually use two different concepts for analysis results + // rather than two different models, and avoid the indirect function call for + // ones that use the trivial behavior. + bool invalidate(IRUnitT &, const PreservedAnalysesT &PA) override { + return !PA.preserved(PassT::ID()); + } + + ResultT Result; +}; + +/// \brief Specialization of \c AnalysisResultModel which delegates invalidate +/// handling to \c ResultT. +template +struct AnalysisResultModel + : AnalysisResultConcept { + explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {} + AnalysisResultModel(AnalysisResultModel &&Arg) + : Result(std::move(Arg.Result)) {} + friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) { + using std::swap; + swap(LHS.Result, RHS.Result); + } + AnalysisResultModel &operator=(AnalysisResultModel RHS) { + swap(*this, RHS); + return *this; + } + + /// \brief The model delegates to the \c ResultT method. + bool invalidate(IRUnitT &IR, const PreservedAnalysesT &PA) override { + return Result.invalidate(IR, PA); + } + + ResultT Result; +}; + +/// \brief Abstract concept of an analysis pass. +/// +/// This concept is parameterized over the IR unit that it can run over and +/// produce an analysis result. +template struct AnalysisPassConcept { + virtual ~AnalysisPassConcept() {} + + /// \brief Method to run this analysis over a unit of IR. + /// \returns A unique_ptr to the analysis result object to be queried by + /// users. + virtual std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) = 0; + + /// \brief Polymorphic method to access the name of a pass. + virtual StringRef name() = 0; +}; + +/// \brief Wrapper to model the analysis pass concept. +/// +/// Can wrap any type which implements a suitable \c run method. The method +/// must accept the IRUnitT as an argument and produce an object which can be +/// wrapped in a \c AnalysisResultModel. +template ::Value> +struct AnalysisPassModel; + +/// \brief Specialization of \c AnalysisPassModel which passes an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *AM) override { + return make_unique(Pass.run(IR, AM)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +/// \brief Specialization of \c AnalysisPassModel which does not pass an +/// \c AnalysisManager to PassT's run method. +template +struct AnalysisPassModel : AnalysisPassConcept { + explicit AnalysisPassModel(PassT Pass) : Pass(std::move(Pass)) {} + // We have to explicitly define all the special member functions because MSVC + // refuses to generate them. + AnalysisPassModel(const AnalysisPassModel &Arg) : Pass(Arg.Pass) {} + AnalysisPassModel(AnalysisPassModel &&Arg) : Pass(std::move(Arg.Pass)) {} + friend void swap(AnalysisPassModel &LHS, AnalysisPassModel &RHS) { + using std::swap; + swap(LHS.Pass, RHS.Pass); + } + AnalysisPassModel &operator=(AnalysisPassModel RHS) { + swap(*this, RHS); + return *this; + } + + // FIXME: Replace PassT::Result with type traits when we use C++11. + typedef AnalysisResultModel + ResultModelT; + + /// \brief The model delegates to the \c PassT::run method. + /// + /// The return is wrapped in an \c AnalysisResultModel. + std::unique_ptr> + run(IRUnitT &IR, AnalysisManager *) override { + return make_unique(Pass.run(IR)); + } + + /// \brief The model delegates to a static \c PassT::name method. + /// + /// The returned string ref must point to constant immutable data! + StringRef name() override { return PassT::name(); } + + PassT Pass; +}; + +} // End namespace detail +} + +#endif diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index 2efb294..f94e105 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -32,61 +32,64 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" +#include "llvm/IR/Intrinsics.h" #include "llvm/IR/Operator.h" namespace llvm { namespace PatternMatch { -template -bool match(Val *V, const Pattern &P) { - return const_cast(P).match(V); +template bool match(Val *V, const Pattern &P) { + return const_cast(P).match(V); } - -template -struct OneUse_match { +template struct OneUse_match { SubPattern_t SubPattern; OneUse_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { return V->hasOneUse() && SubPattern.match(V); } }; -template -inline OneUse_match m_OneUse(const T &SubPattern) { return SubPattern; } - +template inline OneUse_match m_OneUse(const T &SubPattern) { + return SubPattern; +} -template -struct class_match { - template - bool match(ITy *V) { return isa(V); } +template struct class_match { + template bool match(ITy *V) { return isa(V); } }; -/// m_Value() - Match an arbitrary value and ignore it. +/// \brief Match an arbitrary value and ignore it. inline class_match m_Value() { return class_match(); } -/// m_ConstantInt() - Match an arbitrary ConstantInt and ignore it. + +/// \brief Match an arbitrary binary operation and ignore it. +inline class_match m_BinOp() { + return class_match(); +} + +/// \brief Matches any compare instruction and ignore it. +inline class_match m_Cmp() { return class_match(); } + +/// \brief Match an arbitrary ConstantInt and ignore it. inline class_match m_ConstantInt() { return class_match(); } -/// m_Undef() - Match an arbitrary undef constant. + +/// \brief Match an arbitrary undef constant. inline class_match m_Undef() { return class_match(); } +/// \brief Match an arbitrary Constant and ignore it. inline class_match m_Constant() { return class_match(); } /// Matching combinators -template -struct match_combine_or { +template struct match_combine_or { LTy L; RTy R; - match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_or(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) return true; if (R.match(V)) @@ -95,15 +98,13 @@ struct match_combine_or { } }; -template -struct match_combine_and { +template struct match_combine_and { LTy L; RTy R; - match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) { } + match_combine_and(const LTy &Left, const RTy &Right) : L(Left), R(Right) {} - template - bool match(ITy *V) { + template bool match(ITy *V) { if (L.match(V)) if (R.match(V)) return true; @@ -112,46 +113,44 @@ struct match_combine_and { }; /// Combine two pattern matchers matching L || R -template +template inline match_combine_or m_CombineOr(const LTy &L, const RTy &R) { return match_combine_or(L, R); } /// Combine two pattern matchers matching L && R -template +template inline match_combine_and m_CombineAnd(const LTy &L, const RTy &R) { return match_combine_and(L, R); } struct match_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNullValue(); return false; } }; -/// m_Zero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. inline match_zero m_Zero() { return match_zero(); } struct match_neg_zero { - template - bool match(ITy *V) { - if (const Constant *C = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *C = dyn_cast(V)) return C->isNegativeZeroValue(); return false; } }; -/// m_NegZero() - Match an arbitrary zero/null constant. This includes +/// \brief Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero but not positive /// zero inline match_neg_zero m_NegZero() { return match_neg_zero(); } -/// m_AnyZero() - Match an arbitrary zero/null constant. This includes +/// \brief - Match an arbitrary zero/null constant. This includes /// zero_initializer for vectors and ConstantPointerNull for pointers. For /// floating point constants, this will match negative zero and positive zero inline match_combine_or m_AnyZero() { @@ -161,16 +160,14 @@ inline match_combine_or m_AnyZero() { struct apint_match { const APInt *&Res; apint_match(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (ConstantInt *CI = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CI = dyn_cast(V)) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) { + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) { Res = &CI->getValue(); return true; } @@ -178,16 +175,13 @@ struct apint_match { } }; -/// m_APInt - Match a ConstantInt or splatted ConstantVector, binding the +/// \brief Match a ConstantInt or splatted ConstantVector, binding the /// specified pointer to the contained APInt. inline apint_match m_APInt(const APInt *&Res) { return Res; } - -template -struct constantint_match { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) { +template struct constantint_match { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) { const APInt &CIV = CI->getValue(); if (Val >= 0) return CIV == static_cast(Val); @@ -200,45 +194,39 @@ struct constantint_match { } }; -/// m_ConstantInt - Match a ConstantInt with a specific value. -template -inline constantint_match m_ConstantInt() { +/// \brief Match a ConstantInt with a specific value. +template inline constantint_match m_ConstantInt() { return constantint_match(); } -/// cst_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate. -template -struct cst_pred_ty : public Predicate { - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate. +template struct cst_pred_ty : public Predicate { + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) return this->isValue(CI->getValue()); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (const ConstantInt *CI = - dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (const auto *CI = dyn_cast_or_null(C->getSplatValue())) return this->isValue(CI->getValue()); return false; } }; -/// api_pred_ty - This helper class is used to match scalar and vector constants -/// that satisfy a specified predicate, and bind them to an APInt. -template -struct api_pred_ty : public Predicate { +/// \brief This helper class is used to match scalar and vector constants that +/// satisfy a specified predicate, and bind them to an APInt. +template struct api_pred_ty : public Predicate { const APInt *&Res; api_pred_ty(const APInt *&R) : Res(R) {} - template - bool match(ITy *V) { - if (const ConstantInt *CI = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CI = dyn_cast(V)) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; } if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantInt *CI = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CI = dyn_cast_or_null(C->getSplatValue())) if (this->isValue(CI->getValue())) { Res = &CI->getValue(); return true; @@ -248,12 +236,11 @@ struct api_pred_ty : public Predicate { } }; - struct is_one { bool isValue(const APInt &C) { return C == 1; } }; -/// m_One() - Match an integer 1 or a vector with all elements equal to 1. +/// \brief Match an integer 1 or a vector with all elements equal to 1. inline cst_pred_ty m_One() { return cst_pred_ty(); } inline api_pred_ty m_One(const APInt *&V) { return V; } @@ -261,34 +248,43 @@ struct is_all_ones { bool isValue(const APInt &C) { return C.isAllOnesValue(); } }; -/// m_AllOnes() - Match an integer or vector with all bits set to true. -inline cst_pred_ty m_AllOnes() {return cst_pred_ty();} +/// \brief Match an integer or vector with all bits set to true. +inline cst_pred_ty m_AllOnes() { + return cst_pred_ty(); +} inline api_pred_ty m_AllOnes(const APInt *&V) { return V; } struct is_sign_bit { bool isValue(const APInt &C) { return C.isSignBit(); } }; -/// m_SignBit() - Match an integer or vector with only the sign bit(s) set. -inline cst_pred_ty m_SignBit() {return cst_pred_ty();} +/// \brief Match an integer or vector with only the sign bit(s) set. +inline cst_pred_ty m_SignBit() { + return cst_pred_ty(); +} inline api_pred_ty m_SignBit(const APInt *&V) { return V; } struct is_power2 { bool isValue(const APInt &C) { return C.isPowerOf2(); } }; -/// m_Power2() - Match an integer or vector power of 2. +/// \brief Match an integer or vector power of 2. inline cst_pred_ty m_Power2() { return cst_pred_ty(); } inline api_pred_ty m_Power2(const APInt *&V) { return V; } -template -struct bind_ty { +struct is_maxsignedvalue { + bool isValue(const APInt &C) { return C.isMaxSignedValue(); } +}; + +inline cst_pred_ty m_MaxSignedValue() { return cst_pred_ty(); } +inline api_pred_ty m_MaxSignedValue(const APInt *&V) { return V; } + +template struct bind_ty { Class *&VR; bind_ty(Class *&V) : VR(V) {} - template - bool match(ITy *V) { - if (Class *CV = dyn_cast(V)) { + template bool match(ITy *V) { + if (auto *CV = dyn_cast(V)) { VR = CV; return true; } @@ -296,64 +292,62 @@ struct bind_ty { } }; -/// m_Value - Match a value, capturing it if we match. +/// \brief Match a value, capturing it if we match. inline bind_ty m_Value(Value *&V) { return V; } -/// m_ConstantInt - Match a ConstantInt, capturing the value if we match. +/// \brief Match a binary operator, capturing it if we match. +inline bind_ty m_BinOp(BinaryOperator *&I) { return I; } + +/// \brief Match a ConstantInt, capturing the value if we match. inline bind_ty m_ConstantInt(ConstantInt *&CI) { return CI; } -/// m_Constant - Match a Constant, capturing the value if we match. +/// \brief Match a Constant, capturing the value if we match. inline bind_ty m_Constant(Constant *&C) { return C; } -/// m_ConstantFP - Match a ConstantFP, capturing the value if we match. +/// \brief Match a ConstantFP, capturing the value if we match. inline bind_ty m_ConstantFP(ConstantFP *&C) { return C; } -/// specificval_ty - Match a specified Value*. +/// \brief Match a specified Value*. struct specificval_ty { const Value *Val; specificval_ty(const Value *V) : Val(V) {} - template - bool match(ITy *V) { - return V == Val; - } + template bool match(ITy *V) { return V == Val; } }; -/// m_Specific - Match if we have a specific specified value. +/// \brief Match if we have a specific specified value. inline specificval_ty m_Specific(const Value *V) { return V; } -/// Match a specified floating point value or vector of all elements of that -/// value. +/// \brief Match a specified floating point value or vector of all elements of +/// that value. struct specific_fpval { double Val; specific_fpval(double V) : Val(V) {} - template - bool match(ITy *V) { - if (const ConstantFP *CFP = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CFP = dyn_cast(V)) return CFP->isExactlyValue(Val); if (V->getType()->isVectorTy()) - if (const Constant *C = dyn_cast(V)) - if (ConstantFP *CFP = dyn_cast_or_null(C->getSplatValue())) + if (const auto *C = dyn_cast(V)) + if (auto *CFP = dyn_cast_or_null(C->getSplatValue())) return CFP->isExactlyValue(Val); return false; } }; -/// Match a specific floating point value or vector with all elements equal to -/// the value. +/// \brief Match a specific floating point value or vector with all elements +/// equal to the value. inline specific_fpval m_SpecificFP(double V) { return specific_fpval(V); } -/// Match a float 1.0 or vector with all elements equal to 1.0. +/// \brief Match a float 1.0 or vector with all elements equal to 1.0. inline specific_fpval m_FPOne() { return m_SpecificFP(1.0); } struct bind_const_intval_ty { uint64_t &VR; bind_const_intval_ty(uint64_t &V) : VR(V) {} - template - bool match(ITy *V) { - if (ConstantInt *CV = dyn_cast(V)) + template bool match(ITy *V) { + if (const auto *CV = dyn_cast(V)) if (CV->getBitWidth() <= 64) { VR = CV->getZExtValue(); return true; @@ -362,152 +356,196 @@ struct bind_const_intval_ty { } }; -/// m_ConstantInt - Match a ConstantInt and bind to its value. This does not -/// match ConstantInts wider than 64-bits. +/// \brief Match a specified integer value or vector of all elements of that +// value. +struct specific_intval { + uint64_t Val; + specific_intval(uint64_t V) : Val(V) {} + + template bool match(ITy *V) { + const auto *CI = dyn_cast(V); + if (!CI && V->getType()->isVectorTy()) + if (const auto *C = dyn_cast(V)) + CI = dyn_cast_or_null(C->getSplatValue()); + + if (CI && CI->getBitWidth() <= 64) + return CI->getZExtValue() == Val; + + return false; + } +}; + +/// \brief Match a specific integer value or vector with all elements equal to +/// the value. +inline specific_intval m_SpecificInt(uint64_t V) { return specific_intval(V); } + +/// \brief Match a ConstantInt and bind to its value. This does not match +/// ConstantInts wider than 64-bits. inline bind_const_intval_ty m_ConstantInt(uint64_t &V) { return V; } //===----------------------------------------------------------------------===// +// Matcher for any binary operator. +// +template struct AnyBinaryOp_match { + LHS_t L; + RHS_t R; + + AnyBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); + return false; + } +}; + +template +inline AnyBinaryOp_match m_BinOp(const LHS &L, const RHS &R) { + return AnyBinaryOp_match(L, R); +} + +//===----------------------------------------------------------------------===// // Matchers for specific binary operators. // -template +template struct BinaryOp_match { LHS_t L; RHS_t R; BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opcode) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -template -inline BinaryOp_match -m_Add(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Add(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FAdd(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FAdd(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Sub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Sub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FSub(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FSub(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Mul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Mul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FMul(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FMul(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_UDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_UDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FDiv(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FDiv(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_URem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_URem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_SRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_SRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_FRem(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_FRem(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_And(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_And(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Or(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Or(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Xor(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Xor(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_Shl(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_Shl(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_LShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_LShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template -inline BinaryOp_match -m_AShr(const LHS &L, const RHS &R) { +template +inline BinaryOp_match m_AShr(const LHS &L, + const RHS &R) { return BinaryOp_match(L, R); } -template +template struct OverflowingBinaryOp_match { LHS_t L; RHS_t R; - OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + OverflowingBinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) + : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (OverflowingBinaryOperator *Op = dyn_cast(V)) { + template bool match(OpTy *V) { + if (auto *Op = dyn_cast(V)) { if (Op->getOpcode() != Opcode) return false; if (WrapFlags & OverflowingBinaryOperator::NoUnsignedWrap && @@ -591,43 +629,42 @@ m_NUWShl(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches two different binary ops. // -template +template struct BinOp2_match { LHS_t L; RHS_t R; BinOp2_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (V->getValueID() == Value::InstructionVal + Opc1 || V->getValueID() == Value::InstructionVal + Opc2) { - BinaryOperator *I = cast(V); + auto *I = cast(V); return L.match(I->getOperand(0)) && R.match(I->getOperand(1)); } - if (ConstantExpr *CE = dyn_cast(V)) + if (auto *CE = dyn_cast(V)) return (CE->getOpcode() == Opc1 || CE->getOpcode() == Opc2) && L.match(CE->getOperand(0)) && R.match(CE->getOperand(1)); return false; } }; -/// m_Shr - Matches LShr or AShr. -template +/// \brief Matches LShr or AShr. +template inline BinOp2_match m_Shr(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_LogicalShift - Matches LShr or Shl. -template +/// \brief Matches LShr or Shl. +template inline BinOp2_match m_LogicalShift(const LHS &L, const RHS &R) { return BinOp2_match(L, R); } -/// m_IDiv - Matches UDiv and SDiv. -template +/// \brief Matches UDiv and SDiv. +template inline BinOp2_match m_IDiv(const LHS &L, const RHS &R) { return BinOp2_match(L, R); @@ -636,38 +673,36 @@ m_IDiv(const LHS &L, const RHS &R) { //===----------------------------------------------------------------------===// // Class that matches exact binary ops. // -template -struct Exact_match { +template struct Exact_match { SubPattern_t SubPattern; Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (PossiblyExactOperator *PEO = dyn_cast(V)) return PEO->isExact() && SubPattern.match(V); return false; } }; -template -inline Exact_match m_Exact(const T &SubPattern) { return SubPattern; } +template inline Exact_match m_Exact(const T &SubPattern) { + return SubPattern; +} //===----------------------------------------------------------------------===// // Matchers for CmpInst classes // -template +template struct CmpClass_match { PredicateTy &Predicate; LHS_t L; RHS_t R; CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, const RHS_t &RHS) - : Predicate(Pred), L(LHS), R(RHS) {} + : Predicate(Pred), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { if (Class *I = dyn_cast(V)) if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { Predicate = I->getPredicate(); @@ -677,123 +712,114 @@ struct CmpClass_match { } }; -template +template +inline CmpClass_match +m_Cmp(CmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match(Pred, L, R); +} + +template inline CmpClass_match m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } -template +template inline CmpClass_match m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { - return CmpClass_match(Pred, L, R); + return CmpClass_match(Pred, L, R); } //===----------------------------------------------------------------------===// // Matchers for SelectInst classes // -template +template struct SelectClass_match { Cond_t C; LHS_t L; RHS_t R; - SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, - const RHS_t &RHS) - : C(Cond), L(LHS), R(RHS) {} + SelectClass_match(const Cond_t &Cond, const LHS_t &LHS, const RHS_t &RHS) + : C(Cond), L(LHS), R(RHS) {} - template - bool match(OpTy *V) { - if (SelectInst *I = dyn_cast(V)) - return C.match(I->getOperand(0)) && - L.match(I->getOperand(1)) && + template bool match(OpTy *V) { + if (auto *I = dyn_cast(V)) + return C.match(I->getOperand(0)) && L.match(I->getOperand(1)) && R.match(I->getOperand(2)); return false; } }; -template -inline SelectClass_match -m_Select(const Cond &C, const LHS &L, const RHS &R) { +template +inline SelectClass_match m_Select(const Cond &C, const LHS &L, + const RHS &R) { return SelectClass_match(C, L, R); } -/// m_SelectCst - This matches a select of two constants, e.g.: -/// m_SelectCst<-1, 0>(m_Value(V)) -template -inline SelectClass_match, constantint_match > +/// \brief This matches a select of two constants, e.g.: +/// m_SelectCst<-1, 0>(m_Value(V)) +template +inline SelectClass_match, constantint_match> m_SelectCst(const Cond &C) { return m_Select(C, m_ConstantInt(), m_ConstantInt()); } - //===----------------------------------------------------------------------===// // Matchers for CastInst classes // -template -struct CastClass_match { +template struct CastClass_match { Op_t Op; CastClass_match(const Op_t &OpMatch) : Op(OpMatch) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) return O->getOpcode() == Opcode && Op.match(O->getOperand(0)); return false; } }; -/// m_BitCast -template -inline CastClass_match -m_BitCast(const OpTy &Op) { +/// \brief Matches BitCast. +template +inline CastClass_match m_BitCast(const OpTy &Op) { return CastClass_match(Op); } -/// m_PtrToInt -template -inline CastClass_match -m_PtrToInt(const OpTy &Op) { +/// \brief Matches PtrToInt. +template +inline CastClass_match m_PtrToInt(const OpTy &Op) { return CastClass_match(Op); } -/// m_Trunc -template -inline CastClass_match -m_Trunc(const OpTy &Op) { +/// \brief Matches Trunc. +template +inline CastClass_match m_Trunc(const OpTy &Op) { return CastClass_match(Op); } -/// m_SExt -template -inline CastClass_match -m_SExt(const OpTy &Op) { +/// \brief Matches SExt. +template +inline CastClass_match m_SExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_ZExt -template -inline CastClass_match -m_ZExt(const OpTy &Op) { +/// \brief Matches ZExt. +template +inline CastClass_match m_ZExt(const OpTy &Op) { return CastClass_match(Op); } -/// m_UIToFP -template -inline CastClass_match -m_UIToFP(const OpTy &Op) { +/// \brief Matches UIToFP. +template +inline CastClass_match m_UIToFP(const OpTy &Op) { return CastClass_match(Op); } -/// m_SIToFP -template -inline CastClass_match -m_SIToFP(const OpTy &Op) { +/// \brief Matches SIToFP. +template +inline CastClass_match m_SIToFP(const OpTy &Op) { return CastClass_match(Op); } @@ -801,46 +827,41 @@ m_SIToFP(const OpTy &Op) { // Matchers for unary operators // -template -struct not_match { +template struct not_match { LHS_t L; not_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Xor) return matchIfNot(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNot(Value *LHS, Value *RHS) { return (isa(RHS) || isa(RHS) || // FIXME: Remove CV. isa(RHS)) && - cast(RHS)->isAllOnesValue() && - L.match(LHS); + cast(RHS)->isAllOnesValue() && L.match(LHS); } }; -template -inline not_match m_Not(const LHS &L) { return L; } +template inline not_match m_Not(const LHS &L) { return L; } - -template -struct neg_match { +template struct neg_match { LHS_t L; neg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::Sub) return matchIfNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfNeg(Value *LHS, Value *RHS) { return ((isa(LHS) && cast(LHS)->isZero()) || @@ -849,36 +870,33 @@ private: } }; -/// m_Neg - Match an integer negate. -template -inline neg_match m_Neg(const LHS &L) { return L; } - +/// \brief Match an integer negate. +template inline neg_match m_Neg(const LHS &L) { return L; } -template -struct fneg_match { +template struct fneg_match { LHS_t L; fneg_match(const LHS_t &LHS) : L(LHS) {} - template - bool match(OpTy *V) { - if (Operator *O = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *O = dyn_cast(V)) if (O->getOpcode() == Instruction::FSub) return matchIfFNeg(O->getOperand(0), O->getOperand(1)); return false; } + private: bool matchIfFNeg(Value *LHS, Value *RHS) { - if (ConstantFP *C = dyn_cast(LHS)) + if (const auto *C = dyn_cast(LHS)) return C->isNegativeZeroValue() && L.match(RHS); return false; } }; -/// m_FNeg - Match a floating point negate. -template -inline fneg_match m_FNeg(const LHS &L) { return L; } - +/// \brief Match a floating point negate. +template inline fneg_match m_FNeg(const LHS &L) { + return L; +} //===----------------------------------------------------------------------===// // Matchers for control flow. @@ -886,13 +904,10 @@ inline fneg_match m_FNeg(const LHS &L) { return L; } struct br_match { BasicBlock *&Succ; - br_match(BasicBlock *&Succ) - : Succ(Succ) { - } + br_match(BasicBlock *&Succ) : Succ(Succ) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isUnconditional()) { Succ = BI->getSuccessor(0); return true; @@ -903,17 +918,14 @@ struct br_match { inline br_match m_UnconditionalBr(BasicBlock *&Succ) { return br_match(Succ); } -template -struct brc_match { +template struct brc_match { Cond_t Cond; BasicBlock *&T, *&F; brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) - : Cond(C), T(t), F(f) { - } + : Cond(C), T(t), F(f) {} - template - bool match(OpTy *V) { - if (BranchInst *BI = dyn_cast(V)) + template bool match(OpTy *V) { + if (auto *BI = dyn_cast(V)) if (BI->isConditional() && Cond.match(BI->getCondition())) { T = BI->getSuccessor(0); F = BI->getSuccessor(1); @@ -923,31 +935,28 @@ struct brc_match { } }; -template +template inline brc_match m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F) { return brc_match(C, T, F); } - //===----------------------------------------------------------------------===// // Matchers for max/min idioms, eg: "select (sgt x, y), x, y" -> smax(x,y). // -template +template struct MaxMin_match { LHS_t L; RHS_t R; - MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) - : L(LHS), R(RHS) {} + MaxMin_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { // Look for "(x pred y) ? x : y" or "(x pred y) ? y : x". - SelectInst *SI = dyn_cast(V); + auto *SI = dyn_cast(V); if (!SI) return false; - CmpInst_t *Cmp = dyn_cast(SI->getCondition()); + auto *Cmp = dyn_cast(SI->getCondition()); if (!Cmp) return false; // At this point we have a select conditioned on a comparison. Check that @@ -959,8 +968,8 @@ struct MaxMin_match { if ((TrueVal != LHS || FalseVal != RHS) && (TrueVal != RHS || FalseVal != LHS)) return false; - typename CmpInst_t::Predicate Pred = LHS == TrueVal ? - Cmp->getPredicate() : Cmp->getSwappedPredicate(); + typename CmpInst_t::Predicate Pred = + LHS == TrueVal ? Cmp->getPredicate() : Cmp->getSwappedPredicate(); // Does "(x pred y) ? x : y" represent the desired max/min operation? if (!Pred_t::match(Pred)) return false; @@ -969,83 +978,83 @@ struct MaxMin_match { } }; -/// smax_pred_ty - Helper class for identifying signed max predicates. +/// \brief Helper class for identifying signed max predicates. struct smax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SGT || Pred == CmpInst::ICMP_SGE; } }; -/// smin_pred_ty - Helper class for identifying signed min predicates. +/// \brief Helper class for identifying signed min predicates. struct smin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_SLT || Pred == CmpInst::ICMP_SLE; } }; -/// umax_pred_ty - Helper class for identifying unsigned max predicates. +/// \brief Helper class for identifying unsigned max predicates. struct umax_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_UGT || Pred == CmpInst::ICMP_UGE; } }; -/// umin_pred_ty - Helper class for identifying unsigned min predicates. +/// \brief Helper class for identifying unsigned min predicates. struct umin_pred_ty { static bool match(ICmpInst::Predicate Pred) { return Pred == CmpInst::ICMP_ULT || Pred == CmpInst::ICMP_ULE; } }; -/// ofmax_pred_ty - Helper class for identifying ordered max predicates. +/// \brief Helper class for identifying ordered max predicates. struct ofmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OGT || Pred == CmpInst::FCMP_OGE; } }; -/// ofmin_pred_ty - Helper class for identifying ordered min predicates. +/// \brief Helper class for identifying ordered min predicates. struct ofmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_OLT || Pred == CmpInst::FCMP_OLE; } }; -/// ufmax_pred_ty - Helper class for identifying unordered max predicates. +/// \brief Helper class for identifying unordered max predicates. struct ufmax_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_UGT || Pred == CmpInst::FCMP_UGE; } }; -/// ufmin_pred_ty - Helper class for identifying unordered min predicates. +/// \brief Helper class for identifying unordered min predicates. struct ufmin_pred_ty { static bool match(FCmpInst::Predicate Pred) { return Pred == CmpInst::FCMP_ULT || Pred == CmpInst::FCMP_ULE; } }; -template -inline MaxMin_match -m_SMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_SMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_SMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } -template -inline MaxMin_match -m_UMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_UMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1058,9 +1067,9 @@ m_UMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMax(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMax(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMax(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1073,9 +1082,9 @@ m_OrdFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_OrdFMin(L, R) = R iff L or R are NaN -template -inline MaxMin_match -m_OrdFMin(const LHS &L, const RHS &R) { +template +inline MaxMin_match m_OrdFMin(const LHS &L, + const RHS &R) { return MaxMin_match(L, R); } @@ -1088,7 +1097,7 @@ m_OrdFMin(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match(L, R); @@ -1103,40 +1112,39 @@ m_UnordFMax(const LHS &L, const RHS &R) { /// /// max(L, R) iff L and R are not NaN /// m_UnordFMin(L, R) = L iff L or R are NaN -template +template inline MaxMin_match m_UnordFMin(const LHS &L, const RHS &R) { return MaxMin_match(L, R); } -template -struct Argument_match { +template struct Argument_match { unsigned OpI; Opnd_t Val; - Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) { } + Argument_match(unsigned OpIdx, const Opnd_t &V) : OpI(OpIdx), Val(V) {} - template - bool match(OpTy *V) { + template bool match(OpTy *V) { CallSite CS(V); return CS.isCall() && Val.match(CS.getArgument(OpI)); } }; -/// Match an argument -template +/// \brief Match an argument. +template inline Argument_match m_Argument(const Opnd_t &Op) { return Argument_match(OpI, Op); } -/// Intrinsic matchers. +/// \brief Intrinsic matchers. struct IntrinsicID_match { unsigned ID; - IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) { } + IntrinsicID_match(Intrinsic::ID IntrID) : ID(IntrID) {} - template - bool match(OpTy *V) { - IntrinsicInst *II = dyn_cast(V); - return II && II->getIntrinsicID() == ID; + template bool match(OpTy *V) { + if (const auto *CI = dyn_cast(V)) + if (const auto *F = CI->getCalledFunction()) + return F->getIntrinsicID() == ID; + return false; } }; @@ -1147,64 +1155,74 @@ struct IntrinsicID_match { template struct m_Intrinsic_Ty; -template -struct m_Intrinsic_Ty { - typedef match_combine_and > Ty; + typename T9 = void, typename T10 = void> +struct m_Intrinsic_Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and> Ty; }; -template -struct m_Intrinsic_Ty { - typedef match_combine_and::Ty, - Argument_match > Ty; +template struct m_Intrinsic_Ty { + typedef match_combine_and::Ty, Argument_match> + Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; template struct m_Intrinsic_Ty { typedef match_combine_and::Ty, - Argument_match > Ty; + Argument_match> Ty; }; -/// Match intrinsic calls like this: -/// m_Intrinsic(m_Value(X)) -template -inline IntrinsicID_match -m_Intrinsic() { return IntrinsicID_match(IntrID); } +/// \brief Match intrinsic calls like this: +/// m_Intrinsic(m_Value(X)) +template inline IntrinsicID_match m_Intrinsic() { + return IntrinsicID_match(IntrID); +} -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0) { return m_CombineAnd(m_Intrinsic(), m_Argument<0>(Op0)); } -template -inline typename m_Intrinsic_Ty::Ty -m_Intrinsic(const T0 &Op0, const T1 &Op1) { +template +inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, + const T1 &Op1) { return m_CombineAnd(m_Intrinsic(Op0), m_Argument<1>(Op1)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2) { return m_CombineAnd(m_Intrinsic(Op0, Op1), m_Argument<2>(Op2)); } -template +template inline typename m_Intrinsic_Ty::Ty m_Intrinsic(const T0 &Op0, const T1 &Op1, const T2 &Op2, const T3 &Op3) { return m_CombineAnd(m_Intrinsic(Op0, Op1, Op2), m_Argument<3>(Op3)); } -// Helper intrinsic matching specializations -template -inline typename m_Intrinsic_Ty::Ty -m_BSwap(const Opnd0 &Op0) { +// Helper intrinsic matching specializations. +template +inline typename m_Intrinsic_Ty::Ty m_BSwap(const Opnd0 &Op0) { return m_Intrinsic(Op0); } +template +inline typename m_Intrinsic_Ty::Ty m_FMin(const Opnd0 &Op0, + const Opnd1 &Op1) { + return m_Intrinsic(Op0, Op1); +} + +template +inline typename m_Intrinsic_Ty::Ty m_FMax(const Opnd0 &Op0, + const Opnd1 &Op1) { + return m_Intrinsic(Op0, Op1); +} + } // end namespace PatternMatch } // end namespace llvm diff --git a/include/llvm/IR/PredIteratorCache.h b/include/llvm/IR/PredIteratorCache.h index 02bc583..5e1be37 100644 --- a/include/llvm/IR/PredIteratorCache.h +++ b/include/llvm/IR/PredIteratorCache.h @@ -11,14 +11,14 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_IR_PREDITERATORCACHE_H +#define LLVM_IR_PREDITERATORCACHE_H + #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" #include "llvm/Support/Allocator.h" -#ifndef LLVM_IR_PREDITERATORCACHE_H -#define LLVM_IR_PREDITERATORCACHE_H - namespace llvm { /// PredIteratorCache - This class is an extremely trivial cache for diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h new file mode 100644 index 0000000..e3c4243e --- /dev/null +++ b/include/llvm/IR/Statepoint.h @@ -0,0 +1,215 @@ +//===-- llvm/IR/Statepoint.h - gc.statepoint utilities ------ --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains utility functions and a wrapper class analogous to +// CallSite for accessing the fields of gc.statepoint, gc.relocate, and +// gc.result intrinsics +// +//===----------------------------------------------------------------------===// + +#ifndef __LLVM_IR_STATEPOINT_H +#define __LLVM_IR_STATEPOINT_H + +#include "llvm/ADT/iterator_range.h" +#include "llvm/IR/CallSite.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +bool isStatepoint(const ImmutableCallSite &CS); +bool isStatepoint(const Instruction *inst); +bool isStatepoint(const Instruction &inst); + +bool isGCRelocate(const Instruction *inst); +bool isGCRelocate(const ImmutableCallSite &CS); + +bool isGCResult(const Instruction *inst); +bool isGCResult(const ImmutableCallSite &CS); + +/// Analogous to CallSiteBase, this provides most of the actual +/// functionality for Statepoint and ImmutableStatepoint. It is +/// templatized to allow easily specializing of const and non-const +/// concrete subtypes. This is structured analogous to CallSite +/// rather than the IntrinsicInst.h helpers since we want to support +/// invokable statepoints in the near future. +/// TODO: This does not currently allow the if(Statepoint S = ...) +/// idiom used with CallSites. Consider refactoring to support. +template +class StatepointBase { + CallSiteTy StatepointCS; + void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION; + void *operator new(size_t s) LLVM_DELETED_FUNCTION; + + protected: + explicit StatepointBase(InstructionTy *I) : StatepointCS(I) { + assert(isStatepoint(I)); + } + explicit StatepointBase(CallSiteTy CS) : StatepointCS(CS) { + assert(isStatepoint(CS)); + } + + public: + typedef typename CallSiteTy::arg_iterator arg_iterator; + + /// Return the underlying CallSite. + CallSiteTy getCallSite() { + return StatepointCS; + } + + /// Return the value actually being called or invoked. + ValueTy *actualCallee() { + return StatepointCS.getArgument(0); + } + /// Number of arguments to be passed to the actual callee. + int numCallArgs() { + return cast(StatepointCS.getArgument(1))->getZExtValue(); + } + /// Number of additional arguments excluding those intended + /// for garbage collection. + int numTotalVMSArgs() { + return cast(StatepointCS.getArgument(3 + numCallArgs()))->getZExtValue(); + } + + typename CallSiteTy::arg_iterator call_args_begin() { + // 3 = callTarget, #callArgs, flag + int Offset = 3; + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + typename CallSiteTy::arg_iterator call_args_end() { + int Offset = 3 + numCallArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for call arguments + iterator_range call_args() { + return iterator_range(call_args_begin(), call_args_end()); + } + + typename CallSiteTy::arg_iterator vm_state_begin() { + return call_args_end(); + } + typename CallSiteTy::arg_iterator vm_state_end() { + int Offset = 3 + numCallArgs() + 1 + numTotalVMSArgs(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for vm state arguments + iterator_range vm_state_args() { + return iterator_range(vm_state_begin(), vm_state_end()); + } + + typename CallSiteTy::arg_iterator first_vm_state_stack_begin() { + // 6 = numTotalVMSArgs, 1st_objectID, 1st_bci, + // 1st_#stack, 1st_#local, 1st_#monitor + return vm_state_begin() + 6; + } + + typename CallSiteTy::arg_iterator gc_args_begin() { + return vm_state_end(); + } + typename CallSiteTy::arg_iterator gc_args_end() { + return StatepointCS.arg_end(); + } + + /// range adapter for gc arguments + iterator_range gc_args() { + return iterator_range(gc_args_begin(), gc_args_end()); + } + + +#ifndef NDEBUG + /// Asserts if this statepoint is malformed. Common cases for failure + /// include incorrect length prefixes for variable length sections or + /// illegal values for parameters. + void verify() { + assert(numCallArgs() >= 0 && + "number of arguments to actually callee can't be negative"); + + // The internal asserts in the iterator accessors do the rest. + (void)call_args_begin(); + (void)call_args_end(); + (void)vm_state_begin(); + (void)vm_state_end(); + (void)gc_args_begin(); + (void)gc_args_end(); + } +#endif +}; + +/// A specialization of it's base class for read only access +/// to a gc.statepoint. +class ImmutableStatepoint + : public StatepointBase { + typedef StatepointBase + Base; + +public: + explicit ImmutableStatepoint(const Instruction *I) : Base(I) {} + explicit ImmutableStatepoint(ImmutableCallSite CS) : Base(CS) {} +}; + +/// A specialization of it's base class for read-write access +/// to a gc.statepoint. +class Statepoint : public StatepointBase { + typedef StatepointBase Base; + +public: + explicit Statepoint(Instruction *I) : Base(I) {} + explicit Statepoint(CallSite CS) : Base(CS) {} +}; + +/// Wraps a call to a gc.relocate and provides access to it's operands. +/// TODO: This should likely be refactored to resememble the wrappers in +/// InstrinsicInst.h. +class GCRelocateOperands { + ImmutableCallSite RelocateCS; + + public: + GCRelocateOperands(const User* U) : RelocateCS(U) { + assert(isGCRelocate(U)); + } + GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { + assert(isGCRelocate(inst)); + } + GCRelocateOperands(CallSite CS) : RelocateCS(CS) { + assert(isGCRelocate(CS)); + } + + /// The statepoint with which this gc.relocate is associated. + const Instruction *statepoint() { + return cast(RelocateCS.getArgument(0)); + } + /// The index into the associate statepoint's argument list + /// which contains the base pointer of the pointer whose + /// relocation this gc.relocate describes. + int basePtrIndex() { + return cast(RelocateCS.getArgument(1))->getZExtValue(); + } + /// The index into the associate statepoint's argument list which + /// contains the pointer whose relocation this gc.relocate describes. + int derivedPtrIndex() { + return cast(RelocateCS.getArgument(2))->getZExtValue(); + } + Value *basePtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + basePtrIndex()); + } + Value *derivedPtr() { + ImmutableCallSite CS(statepoint()); + return *(CS.arg_begin() + derivedPtrIndex()); + } +}; +} +#endif diff --git a/include/llvm/IR/TrackingMDRef.h b/include/llvm/IR/TrackingMDRef.h new file mode 100644 index 0000000..e241121 --- /dev/null +++ b/include/llvm/IR/TrackingMDRef.h @@ -0,0 +1,170 @@ +//===- llvm/IR/TrackingMDRef.h - Tracking Metadata references ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// References to metadata that track RAUW. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_TRACKINGMDREF_H +#define LLVM_IR_TRACKINGMDREF_H + +#include "llvm/IR/MetadataTracking.h" +#include "llvm/Support/Casting.h" + +namespace llvm { + +class Metadata; +class MDNode; +class ValueAsMetadata; + +/// \brief Tracking metadata reference. +/// +/// This class behaves like \a TrackingVH, but for metadata. +class TrackingMDRef { + Metadata *MD; + +public: + TrackingMDRef() : MD(nullptr) {} + explicit TrackingMDRef(Metadata *MD) : MD(MD) { track(); } + + TrackingMDRef(TrackingMDRef &&X) : MD(X.MD) { retrack(X); } + TrackingMDRef(const TrackingMDRef &X) : MD(X.MD) { track(); } + TrackingMDRef &operator=(TrackingMDRef &&X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + retrack(X); + return *this; + } + TrackingMDRef &operator=(const TrackingMDRef &X) { + if (&X == this) + return *this; + + untrack(); + MD = X.MD; + track(); + return *this; + } + ~TrackingMDRef() { untrack(); } + + Metadata *get() const { return MD; } + operator Metadata *() const { return get(); } + Metadata *operator->() const { return get(); } + Metadata &operator*() const { return *get(); } + + void reset() { + untrack(); + MD = nullptr; + } + void reset(Metadata *MD) { + untrack(); + this->MD = MD; + track(); + } + + /// \brief Check whether this has a trivial destructor. + /// + /// If \c MD isn't replaceable, the destructor will be a no-op. + bool hasTrivialDestructor() const { + return !MD || !MetadataTracking::isReplaceable(*MD); + } + + bool operator==(const TrackingMDRef &X) const { return MD == X.MD; } + bool operator!=(const TrackingMDRef &X) const { return MD != X.MD; } + +private: + void track() { + if (MD) + MetadataTracking::track(MD); + } + void untrack() { + if (MD) + MetadataTracking::untrack(MD); + } + void retrack(TrackingMDRef &X) { + assert(MD == X.MD && "Expected values to match"); + if (X.MD) { + MetadataTracking::retrack(X.MD, MD); + X.MD = nullptr; + } + } +}; + +/// \brief Typed tracking ref. +/// +/// Track refererences of a particular type. It's useful to use this for \a +/// MDNode and \a ValueAsMetadata. +template class TypedTrackingMDRef { + TrackingMDRef Ref; + +public: + TypedTrackingMDRef() {} + explicit TypedTrackingMDRef(T *MD) : Ref(static_cast(MD)) {} + + TypedTrackingMDRef(TypedTrackingMDRef &&X) : Ref(std::move(X.Ref)) {} + TypedTrackingMDRef(const TypedTrackingMDRef &X) : Ref(X.Ref) {} + TypedTrackingMDRef &operator=(TypedTrackingMDRef &&X) { + Ref = std::move(X.Ref); + return *this; + } + TypedTrackingMDRef &operator=(const TypedTrackingMDRef &X) { + Ref = X.Ref; + return *this; + } + + T *get() const { return (T *)Ref.get(); } + operator T *() const { return get(); } + T *operator->() const { return get(); } + T &operator*() const { return *get(); } + + bool operator==(const TypedTrackingMDRef &X) const { return Ref == X.Ref; } + bool operator!=(const TypedTrackingMDRef &X) const { return Ref != X.Ref; } + + void reset() { Ref.reset(); } + void reset(T *MD) { Ref.reset(static_cast(MD)); } + + /// \brief Check whether this has a trivial destructor. + bool hasTrivialDestructor() const { return Ref.hasTrivialDestructor(); } +}; + +typedef TypedTrackingMDRef TrackingMDNodeRef; +typedef TypedTrackingMDRef TrackingValueAsMetadataRef; + +// Expose the underlying metadata to casting. +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(TrackingMDRef &MD) { return MD.get(); } +}; + +template <> struct simplify_type { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +template struct simplify_type> { + typedef T *SimpleType; + static SimpleType getSimplifiedValue(const TypedTrackingMDRef &MD) { + return MD.get(); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index 7955587..c2073c7 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -265,7 +265,7 @@ public: /// get the actual size for a particular target, it is reasonable to use the /// DataLayout subsystem to do this. /// - bool isSized(SmallPtrSet *Visited = nullptr) const { + bool isSized(SmallPtrSetImpl *Visited = nullptr) const { // If it's a primitive, it is always sized. if (getTypeID() == IntegerTyID || isFloatingPointTy() || getTypeID() == PointerTyID || @@ -313,6 +313,9 @@ public: typedef Type * const *subtype_iterator; subtype_iterator subtype_begin() const { return ContainedTys; } subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + ArrayRef subtypes() const { + return makeArrayRef(subtype_begin(), subtype_end()); + } typedef std::reverse_iterator subtype_reverse_iterator; subtype_reverse_iterator subtype_rbegin() const { @@ -323,7 +326,7 @@ public: } /// getContainedType - This method is used to implement the type iterator - /// (defined a the end of the file). For derived types, this returns the + /// (defined at the end of the file). For derived types, this returns the /// types 'contained' in the derived type. /// Type *getContainedType(unsigned i) const { @@ -419,7 +422,7 @@ private: /// isSizedDerivedType - Derived types like structures and arrays are sized /// iff all of the members of the type are sized as well. Since asking for /// their size is relatively uncommon, move this operation out of line. - bool isSizedDerivedType(SmallPtrSet *Visited = nullptr) const; + bool isSizedDerivedType(SmallPtrSetImpl *Visited = nullptr) const; }; // Printing of types. diff --git a/include/llvm/IR/TypeFinder.h b/include/llvm/IR/TypeFinder.h index cea66a4..73a63ad 100644 --- a/include/llvm/IR/TypeFinder.h +++ b/include/llvm/IR/TypeFinder.h @@ -31,6 +31,7 @@ class TypeFinder { // To avoid walking constant expressions multiple times and other IR // objects, we keep several helper maps. DenseSet VisitedConstants; + DenseSet VisitedMetadata; DenseSet VisitedTypes; std::vector StructTypes; diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h new file mode 100644 index 0000000..5df459b --- /dev/null +++ b/include/llvm/IR/UseListOrder.h @@ -0,0 +1,62 @@ +//===- llvm/IR/UseListOrder.h - LLVM Use List Order -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file has structures and command-line options for preserving use-list +// order. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_IR_USELISTORDER_H +#define LLVM_IR_USELISTORDER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace llvm { + +class Module; +class Function; +class Value; + +/// \brief Structure to hold a use-list order. +struct UseListOrder { + const Value *V; + const Function *F; + std::vector Shuffle; + + UseListOrder(const Value *V, const Function *F, size_t ShuffleSize) + : V(V), F(F), Shuffle(ShuffleSize) {} + + UseListOrder() : V(0), F(0) {} + UseListOrder(UseListOrder &&X) + : V(X.V), F(X.F), Shuffle(std::move(X.Shuffle)) {} + UseListOrder &operator=(UseListOrder &&X) { + V = X.V; + F = X.F; + Shuffle = std::move(X.Shuffle); + return *this; + } + +private: + UseListOrder(const UseListOrder &X) LLVM_DELETED_FUNCTION; + UseListOrder &operator=(const UseListOrder &X) LLVM_DELETED_FUNCTION; +}; + +typedef std::vector UseListOrderStack; + +/// \brief Whether to preserve use-list ordering. +bool shouldPreserveBitcodeUseListOrder(); +bool shouldPreserveAssemblyUseListOrder(); +void setPreserveBitcodeUseListOrder(bool ShouldPreserve); +void setPreserveAssemblyUseListOrder(bool ShouldPreserve); + +} // end namespace llvm + +#endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 848adae..f578227 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -26,9 +26,9 @@ namespace llvm { -/// OperandTraits - Compile-time customization of -/// operand-related allocators and accessors -/// for use of the User class +/// \brief Compile-time customization of User operands. +/// +/// Customizes operand-related allocators and accessors. template struct OperandTraits; @@ -39,11 +39,8 @@ class User : public Value { friend struct HungoffOperandTraits; virtual void anchor(); protected: - /// NumOperands - The number of values used by this User. + /// \brief This is a pointer to the array of Uses for this User. /// - unsigned NumOperands; - - /// OperandList - This is a pointer to the array of Uses for this User. /// For nodes of fixed arity (e.g. a binary operator) this array will live /// prefixed to some derived class instance. For nodes of resizable variable /// arity (e.g. PHINodes, SwitchInst etc.), this memory will be dynamically @@ -52,7 +49,9 @@ protected: void *operator new(size_t s, unsigned Us); User(Type *ty, unsigned vty, Use *OpList, unsigned NumOps) - : Value(ty, vty), NumOperands(NumOps), OperandList(OpList) {} + : Value(ty, vty), OperandList(OpList) { + NumOperands = NumOps; + } Use *allocHungoffUses(unsigned) const; void dropHungoffUses() { Use::zap(OperandList, OperandList + NumOperands, true); @@ -64,13 +63,13 @@ public: ~User() { Use::zap(OperandList, OperandList + NumOperands); } - /// operator delete - free memory allocated for User and Use objects + /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); - /// placement delete - required by std, but never called. + /// \brief Placement delete - required by std, but never called. void operator delete(void*, unsigned) { llvm_unreachable("Constructor throws?"); } - /// placement delete - required by std, but never called. + /// \brief Placement delete - required by std, but never called. void operator delete(void*, unsigned, bool) { llvm_unreachable("Constructor throws?"); } @@ -128,8 +127,7 @@ public: return const_op_range(op_begin(), op_end()); } - /// Convenience iterator for directly iterating over the Values in the - /// OperandList + /// \brief Iterator for directly iterating over the operand Values. struct value_op_iterator : iterator_adaptor_base(value_op_begin(), value_op_end()); } - // dropAllReferences() - This function is in charge of "letting go" of all - // objects that this User refers to. This allows one to - // 'delete' a whole class at a time, even though there may be circular - // references... First all references are dropped, and all use counts go to - // zero. Then everything is deleted for real. Note that no operations are - // valid on an object that has "dropped all references", except operator - // delete. - // + /// \brief Drop all references to operands. + /// + /// This function is in charge of "letting go" of all objects that this User + /// refers to. This allows one to 'delete' a whole class at a time, even + /// though there may be circular references... First all references are + /// dropped, and all use counts go to zero. Then everything is deleted for + /// real. Note that no operations are valid on an object that has "dropped + /// all references", except operator delete. void dropAllReferences() { for (Use &U : operands()) U.set(nullptr); } - /// replaceUsesOfWith - Replaces all references to the "From" definition with - /// references to the "To" definition. + /// \brief Replace uses of one Value with another. /// + /// Replaces all references to the "From" definition with references to the + /// "To" definition. void replaceUsesOfWith(Value *From, Value *To); // Methods for support type inquiry through isa, cast, and dyn_cast: diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index b5bbc96..705fc0f 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -37,7 +37,6 @@ class GlobalVariable; class InlineAsm; class Instruction; class LLVMContext; -class MDNode; class Module; class StringRef; class Twine; @@ -53,6 +52,8 @@ typedef StringMapEntry ValueName; // Value Class //===----------------------------------------------------------------------===// +/// \brief LLVM Value Representation +/// /// This is a very important LLVM class. It is the base class of all values /// computed by a program that may be used as operands to other values. Value is /// the super class of other important classes such as Instruction and Function. @@ -64,31 +65,45 @@ typedef StringMapEntry ValueName; /// using this Value. A Value can also have an arbitrary number of ValueHandle /// objects that watch it and listen to RAUW and Destroy events. See /// llvm/IR/ValueHandle.h for details. -/// -/// @brief LLVM Value Representation class Value { Type *VTy; Use *UseList; - friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class ValueAsMetadata; // Allow access to NameAndIsUsedByMD. friend class ValueHandleBase; - ValueName *Name; + PointerIntPair NameAndIsUsedByMD; const unsigned char SubclassID; // Subclass identifier (for isa/dyn_cast) unsigned char HasValueHandle : 1; // Has a ValueHandle pointing to this? protected: - /// SubclassOptionalData - This member is similar to SubclassData, however it - /// is for holding information which may be used to aid optimization, but - /// which may be cleared to zero without affecting conservative - /// interpretation. + /// \brief Hold subclass data that can be dropped. + /// + /// This member is similar to SubclassData, however it is for holding + /// information which may be used to aid optimization, but which may be + /// cleared to zero without affecting conservative interpretation. unsigned char SubclassOptionalData : 7; private: - /// SubclassData - This member is defined by this class, but is not used for - /// anything. Subclasses can use it to hold whatever state they find useful. - /// This field is initialized to zero by the ctor. + /// \brief Hold arbitrary subclass data. + /// + /// This member is defined by this class, but is not used for anything. + /// Subclasses can use it to hold whatever state they find useful. This + /// field is initialized to zero by the ctor. unsigned short SubclassData; +protected: + /// \brief The number of operands in the subclass. + /// + /// This member is defined by this class, but not used for anything. + /// Subclasses can use it to store their number of operands, if they have + /// any. + /// + /// This is stored here to save space in User on 64-bit hosts. Since most + /// instances of Value have operands, 32-bit hosts aren't significantly + /// affected. + unsigned NumOperands; + +private: template // UseT == 'Use' or 'const Use' class use_iterator_impl : public std::iterator { @@ -175,6 +190,7 @@ private: Use &getUse() const { return *UI; } /// \brief Return the operand # of this use in its User. + /// /// FIXME: Replace all callers with a direct call to Use::getOperandNo. unsigned getOperandNo() const { return UI->getOperandNo(); } }; @@ -187,15 +203,14 @@ protected: public: virtual ~Value(); - /// dump - Support for debugging, callable in GDB: V->dump() - // + /// \brief Support for debugging, callable in GDB: V->dump() void dump() const; - /// print - Implement operator<< on Value. - /// + /// \brief Implement operator<< on Value. void print(raw_ostream &O) const; /// \brief Print the name of this Value out to the specified raw_ostream. + /// /// This is useful when you just want to print 'int %reg126', not the /// instruction that generated it. If you specify a Module for context, then /// even constanst get pretty-printed; for example, the type of a null @@ -203,40 +218,56 @@ public: void printAsOperand(raw_ostream &O, bool PrintType = true, const Module *M = nullptr) const; - /// All values are typed, get the type of this value. - /// + /// \brief All values are typed, get the type of this value. Type *getType() const { return VTy; } - /// All values hold a context through their type. + /// \brief All values hold a context through their type. LLVMContext &getContext() const; - // All values can potentially be named. - bool hasName() const { return Name != nullptr && SubclassID != MDStringVal; } - ValueName *getValueName() const { return Name; } - void setValueName(ValueName *VN) { Name = VN; } + // \brief All values can potentially be named. + bool hasName() const { return getValueName() != nullptr; } + ValueName *getValueName() const { return NameAndIsUsedByMD.getPointer(); } + void setValueName(ValueName *VN) { NameAndIsUsedByMD.setPointer(VN); } - /// getName() - Return a constant reference to the value's name. This is cheap - /// and guaranteed to return the same reference as long as the value is not - /// modified. +private: + void destroyValueName(); + +public: + /// \brief Return a constant reference to the value's name. + /// + /// This is cheap and guaranteed to return the same reference as long as the + /// value is not modified. StringRef getName() const; - /// setName() - Change the name of the value, choosing a new unique name if - /// the provided name is taken. + /// \brief Change the name of the value. + /// + /// Choose a new unique name if the provided name is taken. /// /// \param Name The new name; or "" if the value's name should be removed. void setName(const Twine &Name); - /// takeName - transfer the name from V to this value, setting V's name to - /// empty. It is an error to call V->takeName(V). + /// \brief Transfer the name from V to this value. + /// + /// After taking V's name, sets V's name to empty. + /// + /// \note It is an error to call V->takeName(V). void takeName(Value *V); - /// replaceAllUsesWith - Go through the uses list for this definition and make - /// each use point to "V" instead of "this". After this completes, 'this's - /// use list is guaranteed to be empty. + /// \brief Change all uses of this to point to a new Value. /// + /// Go through the uses list for this definition and make each use point to + /// "V" instead of "this". After this completes, 'this's use list is + /// guaranteed to be empty. void replaceAllUsesWith(Value *V); + /// replaceUsesOutsideBlock - Go through the uses list for this definition and + /// make each use point to "V" instead of "this" when the use is outside the + /// block. 'This's use list is expected to have at least one element. + /// Unlike replaceAllUsesWith this function does not support basic block + /// values or constant users. + void replaceUsesOutsideBlock(Value *V, BasicBlock *BB); + //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // @@ -255,6 +286,8 @@ public: return iterator_range(use_begin(), use_end()); } + bool user_empty() const { return UseList == nullptr; } + typedef user_iterator_impl user_iterator; typedef user_iterator_impl const_user_iterator; user_iterator user_begin() { return user_iterator(UseList); } @@ -270,36 +303,38 @@ public: return iterator_range(user_begin(), user_end()); } - /// hasOneUse - Return true if there is exactly one user of this value. This - /// is specialized because it is a common request and does not require - /// traversing the whole use list. + /// \brief Return true if there is exactly one user of this value. /// + /// This is specialized because it is a common request and does not require + /// traversing the whole use list. bool hasOneUse() const { const_use_iterator I = use_begin(), E = use_end(); if (I == E) return false; return ++I == E; } - /// hasNUses - Return true if this Value has exactly N users. - /// + /// \brief Return true if this Value has exactly N users. bool hasNUses(unsigned N) const; - /// hasNUsesOrMore - Return true if this value has N users or more. This is - /// logically equivalent to getNumUses() >= N. + /// \brief Return true if this value has N users or more. /// + /// This is logically equivalent to getNumUses() >= N. bool hasNUsesOrMore(unsigned N) const; + /// \brief Check if this value is used in the specified basic block. bool isUsedInBasicBlock(const BasicBlock *BB) const; - /// getNumUses - This method computes the number of uses of this Value. This - /// is a linear time operation. Use hasOneUse, hasNUses, or hasNUsesOrMore - /// to check for specific values. + /// \brief This method computes the number of uses of this Value. + /// + /// This is a linear time operation. Use hasOneUse, hasNUses, or + /// hasNUsesOrMore to check for specific values. unsigned getNumUses() const; - /// addUse - This method should only be used by the Use class. - /// + /// \brief This method should only be used by the Use class. void addUse(Use &U) { U.addToList(&UseList); } + /// \brief Concrete subclass of this. + /// /// An enumeration for keeping track of the concrete subclass of Value that /// is actually instantiated. Values of this enumeration are kept in the /// Value classes SubclassID field. They are used for concrete type @@ -322,8 +357,7 @@ public: ConstantStructVal, // This is an instance of ConstantStruct ConstantVectorVal, // This is an instance of ConstantVector ConstantPointerNullVal, // This is an instance of ConstantPointerNull - MDNodeVal, // This is an instance of MDNode - MDStringVal, // This is an instance of MDString + MetadataAsValueVal, // This is an instance of MetadataAsValue InlineAsmVal, // This is an instance of InlineAsm InstructionVal, // This is an instance of Instruction // Enum values starting at InstructionVal are used for Instructions; @@ -334,11 +368,12 @@ public: ConstantLastVal = ConstantPointerNullVal }; - /// getValueID - Return an ID for the concrete type of this object. This is - /// used to implement the classof checks. This should not be used for any - /// other purpose, as the values may change as LLVM evolves. Also, note that - /// for instructions, the Instruction's opcode is added to InstructionVal. So - /// this means three things: + /// \brief Return an ID for the concrete type of this object. + /// + /// This is used to implement the classof checks. This should not be used + /// for any other purpose, as the values may change as LLVM evolves. Also, + /// note that for instructions, the Instruction's opcode is added to + /// InstructionVal. So this means three things: /// # there is no value with code InstructionVal (no opcode==0). /// # there are more possible values for the value type than in ValueTy enum. /// # the InstructionVal enumerator must be the highest valued enumerator in @@ -347,64 +382,62 @@ public: return SubclassID; } - /// getRawSubclassOptionalData - Return the raw optional flags value - /// contained in this value. This should only be used when testing two - /// Values for equivalence. + /// \brief Return the raw optional flags value contained in this value. + /// + /// This should only be used when testing two Values for equivalence. unsigned getRawSubclassOptionalData() const { return SubclassOptionalData; } - /// clearSubclassOptionalData - Clear the optional flags contained in - /// this value. + /// \brief Clear the optional flags contained in this value. void clearSubclassOptionalData() { SubclassOptionalData = 0; } - /// hasSameSubclassOptionalData - Test whether the optional flags contained - /// in this value are equal to the optional flags in the given value. + /// \brief Check the optional flags for equality. bool hasSameSubclassOptionalData(const Value *V) const { return SubclassOptionalData == V->SubclassOptionalData; } - /// intersectOptionalDataWith - Clear any optional flags in this value - /// that are not also set in the given value. + /// \brief Clear any optional flags not set in the given Value. void intersectOptionalDataWith(const Value *V) { SubclassOptionalData &= V->SubclassOptionalData; } - /// hasValueHandle - Return true if there is a value handle associated with - /// this value. + /// \brief Return true if there is a value handle associated with this value. bool hasValueHandle() const { return HasValueHandle; } - /// \brief Strips off any unneeded pointer casts, all-zero GEPs and aliases - /// from the specified value, returning the original uncasted value. + /// \brief Return true if there is metadata referencing this value. + bool isUsedByMetadata() const { return NameAndIsUsedByMD.getInt(); } + + /// \brief Strip off pointer casts, all-zero GEPs, and aliases. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original uncasted value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripPointerCasts(); const Value *stripPointerCasts() const { return const_cast(this)->stripPointerCasts(); } - /// \brief Strips off any unneeded pointer casts and all-zero GEPs from the - /// specified value, returning the original uncasted value. + /// \brief Strip off pointer casts and all-zero GEPs. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original uncasted value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripPointerCastsNoFollowAliases(); const Value *stripPointerCastsNoFollowAliases() const { return const_cast(this)->stripPointerCastsNoFollowAliases(); } - /// \brief Strips off unneeded pointer casts and all-constant GEPs from the - /// specified value, returning the original pointer value. + /// \brief Strip off pointer casts and all-constant inbounds GEPs. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original pointer value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripInBoundsConstantOffsets(); const Value *stripInBoundsConstantOffsets() const { return const_cast(this)->stripInBoundsConstantOffsets(); } - /// \brief Strips like \c stripInBoundsConstantOffsets but also accumulates - /// the constant offset stripped. + /// \brief Accumulate offsets from \a stripInBoundsConstantOffsets(). /// /// Stores the resulting constant offset stripped into the APInt provided. /// The provided APInt will be extended or truncated as needed to be the @@ -419,23 +452,27 @@ public: ->stripAndAccumulateInBoundsConstantOffsets(DL, Offset); } - /// \brief Strips off unneeded pointer casts and any in-bounds offsets from - /// the specified value, returning the original pointer value. + /// \brief Strip off pointer casts and inbounds GEPs. /// - /// If this is called on a non-pointer value, it returns 'this'. + /// Returns the original pointer value. If this is called on a non-pointer + /// value, it returns 'this'. Value *stripInBoundsOffsets(); const Value *stripInBoundsOffsets() const { return const_cast(this)->stripInBoundsOffsets(); } - /// isDereferenceablePointer - Test if this value is always a pointer to - /// allocated and suitably aligned memory for a simple load or store. + /// \brief Check if this is always a dereferenceable pointer. + /// + /// Test if this value is always a pointer to allocated and suitably aligned + /// memory for a simple load or store. bool isDereferenceablePointer(const DataLayout *DL = nullptr) const; - /// DoPHITranslation - If this value is a PHI node with CurBB as its parent, - /// return the value in the PHI node corresponding to PredBB. If not, return - /// ourself. This is useful if you want to know the value something has in a - /// predecessor block. + /// \brief Translate PHI node to its predecessor from the given basic block. + /// + /// If this value is a PHI node with CurBB as its parent, return the value in + /// the PHI node corresponding to PredBB. If not, return ourself. This is + /// useful if you want to know the value something has in a predecessor + /// block. Value *DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB); const Value *DoPHITranslation(const BasicBlock *CurBB, @@ -443,11 +480,14 @@ public: return const_cast(this)->DoPHITranslation(CurBB, PredBB); } - /// MaximumAlignment - This is the greatest alignment value supported by - /// load, store, and alloca instructions, and global values. + /// \brief The maximum alignment for instructions. + /// + /// This is the greatest alignment value supported by load, store, and alloca + /// instructions, and global values. static const unsigned MaximumAlignment = 1u << 29; - /// mutateType - Mutate the type of this Value to be of the specified type. + /// \brief Mutate the type of this Value to be of the specified type. + /// /// Note that this is an extremely dangerous operation which can create /// completely invalid IR very easily. It is strongly recommended that you /// recreate IR objects with the right types instead of mutating them in @@ -456,6 +496,37 @@ public: VTy = Ty; } + /// \brief Sort the use-list. + /// + /// Sorts the Value's use-list by Cmp using a stable mergesort. Cmp is + /// expected to compare two \a Use references. + template void sortUseList(Compare Cmp); + + /// \brief Reverse the use-list. + void reverseUseList(); + +private: + /// \brief Merge two lists together. + /// + /// Merges \c L and \c R using \c Cmp. To enable stable sorts, always pushes + /// "equal" items from L before items from R. + /// + /// \return the first element in the list. + /// + /// \note Completely ignores \a Use::Prev (doesn't read, doesn't update). + template + static Use *mergeUseLists(Use *L, Use *R, Compare Cmp) { + Use *Merged; + mergeUseListsImpl(L, R, &Merged, Cmp); + return Merged; + } + + /// \brief Tail-recursive helper for \a mergeUseLists(). + /// + /// \param[out] Next the first element in the list. + template + static void mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp); + protected: unsigned short getSubclassDataFromValue() const { return SubclassData; } void setValueSubclassData(unsigned short D) { SubclassData = D; } @@ -472,6 +543,91 @@ void Use::set(Value *V) { if (V) V->addUse(*this); } +template void Value::sortUseList(Compare Cmp) { + if (!UseList || !UseList->Next) + // No need to sort 0 or 1 uses. + return; + + // Note: this function completely ignores Prev pointers until the end when + // they're fixed en masse. + + // Create a binomial vector of sorted lists, visiting uses one at a time and + // merging lists as necessary. + const unsigned MaxSlots = 32; + Use *Slots[MaxSlots]; + + // Collect the first use, turning it into a single-item list. + Use *Next = UseList->Next; + UseList->Next = nullptr; + unsigned NumSlots = 1; + Slots[0] = UseList; + + // Collect all but the last use. + while (Next->Next) { + Use *Current = Next; + Next = Current->Next; + + // Turn Current into a single-item list. + Current->Next = nullptr; + + // Save Current in the first available slot, merging on collisions. + unsigned I; + for (I = 0; I < NumSlots; ++I) { + if (!Slots[I]) + break; + + // Merge two lists, doubling the size of Current and emptying slot I. + // + // Since the uses in Slots[I] originally preceded those in Current, send + // Slots[I] in as the left parameter to maintain a stable sort. + Current = mergeUseLists(Slots[I], Current, Cmp); + Slots[I] = nullptr; + } + // Check if this is a new slot. + if (I == NumSlots) { + ++NumSlots; + assert(NumSlots <= MaxSlots && "Use list bigger than 2^32"); + } + + // Found an open slot. + Slots[I] = Current; + } + + // Merge all the lists together. + assert(Next && "Expected one more Use"); + assert(!Next->Next && "Expected only one Use"); + UseList = Next; + for (unsigned I = 0; I < NumSlots; ++I) + if (Slots[I]) + // Since the uses in Slots[I] originally preceded those in UseList, send + // Slots[I] in as the left parameter to maintain a stable sort. + UseList = mergeUseLists(Slots[I], UseList, Cmp); + + // Fix the Prev pointers. + for (Use *I = UseList, **Prev = &UseList; I; I = I->Next) { + I->setPrev(Prev); + Prev = &I->Next; + } +} + +template +void Value::mergeUseListsImpl(Use *L, Use *R, Use **Next, Compare Cmp) { + if (!L) { + *Next = R; + return; + } + if (!R) { + *Next = L; + return; + } + if (Cmp(*R, *L)) { + *Next = R; + mergeUseListsImpl(L, R->Next, &R->Next, Cmp); + return; + } + *Next = L; + mergeUseListsImpl(L->Next, R, &L->Next, Cmp); +} // isa - Provide some specializations of isa so that we don't have to include // the subtype header files to test to see if the value is a subclass... @@ -537,12 +693,6 @@ template <> struct isa_impl { } }; -template <> struct isa_impl { - static inline bool doit(const Value &Val) { - return Val.getValueID() == Value::MDNodeVal; - } -}; - // Value* is only 4-byte aligned. template<> class PointerLikeTypeTraits { diff --git a/include/llvm/IR/ValueHandle.h b/include/llvm/IR/ValueHandle.h index aa29b2e..8fc7fdb 100644 --- a/include/llvm/IR/ValueHandle.h +++ b/include/llvm/IR/ValueHandle.h @@ -33,15 +33,16 @@ public: enum { NumLowBitsAvailable = 2 }; }; -/// ValueHandleBase - This is the common base class of value handles. +/// \brief This is the common base class of value handles. +/// /// ValueHandle's are smart pointers to Value's that have special behavior when /// the value is deleted or ReplaceAllUsesWith'd. See the specific handles /// below for details. -/// class ValueHandleBase { friend class Value; protected: - /// HandleBaseKind - This indicates what sub class the handle actually is. + /// \brief This indicates what sub class the handle actually is. + /// /// This is to avoid having a vtable for the light-weight handle pointers. The /// fully general Callback version does have a vtable. enum HandleBaseKind { @@ -55,55 +56,48 @@ private: PointerIntPair PrevPair; ValueHandleBase *Next; - // A subclass may want to store some information along with the value - // pointer. Allow them to do this by making the value pointer a pointer-int - // pair. The 'setValPtrInt' and 'getValPtrInt' methods below give them this - // access. - PointerIntPair VP; + Value* V; ValueHandleBase(const ValueHandleBase&) LLVM_DELETED_FUNCTION; public: explicit ValueHandleBase(HandleBaseKind Kind) - : PrevPair(nullptr, Kind), Next(nullptr), VP(nullptr, 0) {} + : PrevPair(nullptr, Kind), Next(nullptr), V(nullptr) {} ValueHandleBase(HandleBaseKind Kind, Value *V) - : PrevPair(nullptr, Kind), Next(nullptr), VP(V, 0) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(V) { + if (isValid(V)) AddToUseList(); } ValueHandleBase(HandleBaseKind Kind, const ValueHandleBase &RHS) - : PrevPair(nullptr, Kind), Next(nullptr), VP(RHS.VP) { - if (isValid(VP.getPointer())) + : PrevPair(nullptr, Kind), Next(nullptr), V(RHS.V) { + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); } ~ValueHandleBase() { - if (isValid(VP.getPointer())) + if (isValid(V)) RemoveFromUseList(); } Value *operator=(Value *RHS) { - if (VP.getPointer() == RHS) return RHS; - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS); - if (isValid(VP.getPointer())) AddToUseList(); + if (V == RHS) return RHS; + if (isValid(V)) RemoveFromUseList(); + V = RHS; + if (isValid(V)) AddToUseList(); return RHS; } Value *operator=(const ValueHandleBase &RHS) { - if (VP.getPointer() == RHS.VP.getPointer()) return RHS.VP.getPointer(); - if (isValid(VP.getPointer())) RemoveFromUseList(); - VP.setPointer(RHS.VP.getPointer()); - if (isValid(VP.getPointer())) AddToExistingUseList(RHS.getPrevPtr()); - return VP.getPointer(); + if (V == RHS.V) return RHS.V; + if (isValid(V)) RemoveFromUseList(); + V = RHS.V; + if (isValid(V)) AddToExistingUseList(RHS.getPrevPtr()); + return V; } - Value *operator->() const { return getValPtr(); } - Value &operator*() const { return *getValPtr(); } + Value *operator->() const { return V; } + Value &operator*() const { return *V; } protected: - Value *getValPtr() const { return VP.getPointer(); } - - void setValPtrInt(unsigned K) { VP.setInt(K); } - unsigned getValPtrInt() const { return VP.getInt(); } + Value *getValPtr() const { return V; } static bool isValid(Value *V) { return V && @@ -122,26 +116,28 @@ private: HandleBaseKind getKind() const { return PrevPair.getInt(); } void setPrevPtr(ValueHandleBase **Ptr) { PrevPair.setPointer(Ptr); } - /// AddToExistingUseList - Add this ValueHandle to the use list for VP, where + /// \brief Add this ValueHandle to the use list for V. + /// /// List is the address of either the head of the list or a Next node within /// the existing use list. void AddToExistingUseList(ValueHandleBase **List); - /// AddToExistingUseListAfter - Add this ValueHandle to the use list after - /// Node. + /// \brief Add this ValueHandle to the use list after Node. void AddToExistingUseListAfter(ValueHandleBase *Node); - /// AddToUseList - Add this ValueHandle to the use list for VP. + /// \brief Add this ValueHandle to the use list for V. void AddToUseList(); - /// RemoveFromUseList - Remove this ValueHandle from its current use list. + /// \brief Remove this ValueHandle from its current use list. void RemoveFromUseList(); }; -/// WeakVH - This is a value handle that tries hard to point to a Value, even -/// across RAUW operations, but will null itself out if the value is destroyed. -/// this is useful for advisory sorts of information, but should not be used as -/// the key of a map (since the map would have to rearrange itself when the -/// pointer changes). +/// \brief Value handle that is nullable, but tries to track the Value. +/// +/// This is a value handle that tries hard to point to a Value, even across +/// RAUW operations, but will null itself out if the value is destroyed. this +/// is useful for advisory sorts of information, but should not be used as the +/// key of a map (since the map would have to rearrange itself when the pointer +/// changes). class WeakVH : public ValueHandleBase { public: WeakVH() : ValueHandleBase(Weak) {} @@ -170,14 +166,16 @@ template<> struct simplify_type { } }; -/// AssertingVH - This is a Value Handle that points to a value and asserts out -/// if the value is destroyed while the handle is still live. This is very -/// useful for catching dangling pointer bugs and other things which can be -/// non-obvious. One particularly useful place to use this is as the Key of a -/// map. Dangling pointer bugs often lead to really subtle bugs that only occur -/// if another object happens to get allocated to the same address as the old -/// one. Using an AssertingVH ensures that an assert is triggered as soon as -/// the bad delete occurs. +/// \brief Value handle that asserts if the Value is deleted. +/// +/// This is a Value Handle that points to a value and asserts out if the value +/// is destroyed while the handle is still live. This is very useful for +/// catching dangling pointer bugs and other things which can be non-obvious. +/// One particularly useful place to use this is as the Key of a map. Dangling +/// pointer bugs often lead to really subtle bugs that only occur if another +/// object happens to get allocated to the same address as the old one. Using +/// an AssertingVH ensures that an assert is triggered as soon as the bad +/// delete occurs. /// /// Note that an AssertingVH handle does *not* follow values across RAUW /// operations. This means that RAUW's need to explicitly update the @@ -189,25 +187,23 @@ class AssertingVH : public ValueHandleBase #endif { + friend struct DenseMapInfo >; #ifndef NDEBUG - ValueTy *getValPtr() const { - return static_cast(ValueHandleBase::getValPtr()); - } - void setValPtr(ValueTy *P) { - ValueHandleBase::operator=(GetAsValue(P)); - } + Value *getRawValPtr() const { return ValueHandleBase::getValPtr(); } + void setRawValPtr(Value *P) { ValueHandleBase::operator=(P); } #else - ValueTy *ThePtr; - ValueTy *getValPtr() const { return ThePtr; } - void setValPtr(ValueTy *P) { ThePtr = P; } + Value *ThePtr; + Value *getRawValPtr() const { return ThePtr; } + void setRawValPtr(Value *P) { ThePtr = P; } #endif - - // Convert a ValueTy*, which may be const, to the type the base - // class expects. + // Convert a ValueTy*, which may be const, to the raw Value*. static Value *GetAsValue(Value *V) { return V; } static Value *GetAsValue(const Value *V) { return const_cast(V); } + ValueTy *getValPtr() const { return static_cast(getRawValPtr()); } + void setValPtr(ValueTy *P) { setRawValPtr(GetAsValue(P)); } + public: #ifndef NDEBUG AssertingVH() : ValueHandleBase(Assert) {} @@ -215,7 +211,7 @@ public: AssertingVH(const AssertingVH &RHS) : ValueHandleBase(Assert, RHS) {} #else AssertingVH() : ThePtr(nullptr) {} - AssertingVH(ValueTy *P) : ThePtr(P) {} + AssertingVH(ValueTy *P) : ThePtr(GetAsValue(P)) {} #endif operator ValueTy*() const { @@ -238,21 +234,25 @@ public: // Specialize DenseMapInfo to allow AssertingVH to participate in DenseMap. template struct DenseMapInfo > { - typedef DenseMapInfo PointerInfo; static inline AssertingVH getEmptyKey() { - return AssertingVH(PointerInfo::getEmptyKey()); + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getEmptyKey()); + return Res; } - static inline T* getTombstoneKey() { - return AssertingVH(PointerInfo::getTombstoneKey()); + static inline AssertingVH getTombstoneKey() { + AssertingVH Res; + Res.setRawValPtr(DenseMapInfo::getTombstoneKey()); + return Res; } static unsigned getHashValue(const AssertingVH &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val.getRawValPtr()); } static bool isEqual(const AssertingVH &LHS, const AssertingVH &RHS) { - return LHS == RHS; + return DenseMapInfo::isEqual(LHS.getRawValPtr(), + RHS.getRawValPtr()); } }; - + template struct isPodLike > { #ifdef NDEBUG @@ -263,8 +263,7 @@ struct isPodLike > { }; -/// TrackingVH - This is a value handle that tracks a Value (or Value subclass), -/// even across RAUW operations. +/// \brief Value handle that tracks a Value across RAUW. /// /// TrackingVH is designed for situations where a client needs to hold a handle /// to a Value (or subclass) across some operations which may move that value, @@ -332,12 +331,14 @@ public: ValueTy &operator*() const { return *getValPtr(); } }; -/// CallbackVH - This is a value handle that allows subclasses to define -/// callbacks that run when the underlying Value has RAUW called on it or is -/// destroyed. This class can be used as the key of a map, as long as the user -/// takes it out of the map before calling setValPtr() (since the map has to -/// rearrange itself when the pointer changes). Unlike ValueHandleBase, this -/// class has a vtable and a virtual destructor. +/// \brief Value handle with callbacks on RAUW and destruction. +/// +/// This is a value handle that allows subclasses to define callbacks that run +/// when the underlying Value has RAUW called on it or is destroyed. This +/// class can be used as the key of a map, as long as the user takes it out of +/// the map before calling setValPtr() (since the map has to rearrange itself +/// when the pointer changes). Unlike ValueHandleBase, this class has a vtable +/// and a virtual destructor. class CallbackVH : public ValueHandleBase { virtual void anchor(); protected: @@ -358,16 +359,20 @@ public: return getValPtr(); } - /// Called when this->getValPtr() is destroyed, inside ~Value(), so you may - /// call any non-virtual Value method on getValPtr(), but no subclass methods. - /// If WeakVH were implemented as a CallbackVH, it would use this method to - /// call setValPtr(NULL). AssertingVH would use this method to cause an - /// assertion failure. + /// \brief Callback for Value destruction. + /// + /// Called when this->getValPtr() is destroyed, inside ~Value(), so you + /// may call any non-virtual Value method on getValPtr(), but no subclass + /// methods. If WeakVH were implemented as a CallbackVH, it would use this + /// method to call setValPtr(NULL). AssertingVH would use this method to + /// cause an assertion failure. /// /// All implementations must remove the reference from this object to the /// Value that's being destroyed. virtual void deleted() { setValPtr(nullptr); } + /// \brief Callback for Value RAUW. + /// /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, /// _before_ any of the uses have actually been replaced. If WeakVH were /// implemented as a CallbackVH, it would use this method to call diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index 43a79c7..f2ea405 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -27,10 +27,13 @@ #define LLVM_IR_VALUEMAP_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/TrackingMDRef.h" #include "llvm/IR/ValueHandle.h" #include "llvm/Support/Mutex.h" +#include "llvm/Support/UniqueLock.h" #include "llvm/Support/type_traits.h" #include +#include namespace llvm { @@ -78,8 +81,10 @@ class ValueMap { friend class ValueMapCallbackVH; typedef ValueMapCallbackVH ValueMapCVH; typedef DenseMap > MapT; + typedef DenseMap MDMapT; typedef typename Config::ExtraData ExtraData; MapT Map; + std::unique_ptr MDMap; ExtraData Data; ValueMap(const ValueMap&) LLVM_DELETED_FUNCTION; ValueMap& operator=(const ValueMap&) LLVM_DELETED_FUNCTION; @@ -90,12 +95,19 @@ public: typedef unsigned size_type; explicit ValueMap(unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data() {} + : Map(NumInitBuckets), Data() {} explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) - : Map(NumInitBuckets), Data(Data) {} + : Map(NumInitBuckets), Data(Data) {} ~ValueMap() {} + bool hasMD() const { return MDMap; } + MDMapT &MD() { + if (!MDMap) + MDMap.reset(new MDMapT); + return *MDMap; + } + typedef ValueMapIterator iterator; typedef ValueMapConstIterator const_iterator; inline iterator begin() { return iterator(Map.begin()); } @@ -109,9 +121,12 @@ public: /// Grow the map so that it has at least Size buckets. Does not shrink void resize(size_t Size) { Map.resize(Size); } - void clear() { Map.clear(); } + void clear() { + Map.clear(); + MDMap.reset(); + } - /// Return 1 if the specified key is in the map, 0 otherwise. + /// Return 1 if the specified key is in the map, 0 otherwise. size_type count(const KeyT &Val) const { return Map.find_as(Val) == Map.end() ? 0 : 1; } @@ -209,6 +224,9 @@ class ValueMapCallbackVH : public CallbackVH { : CallbackVH(const_cast(static_cast(Key))), Map(Map) {} + // Private constructor used to create empty/tombstone DenseMap keys. + ValueMapCallbackVH(Value *V) : CallbackVH(V), Map(nullptr) {} + public: KeyT Unwrap() const { return cast_or_null(getValPtr()); } @@ -216,12 +234,11 @@ public: // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); + unique_lock Guard; if (M) - M->acquire(); + Guard = unique_lock(*M); Config::onDelete(Copy.Map->Data, Copy.Unwrap()); // May destroy *this. Copy.Map->Map.erase(Copy); // Definitely destroys *this. - if (M) - M->release(); } void allUsesReplacedWith(Value *new_key) override { assert(isa(new_key) && @@ -229,8 +246,9 @@ public: // Make a copy that won't get changed even when *this is destroyed. ValueMapCallbackVH Copy(*this); typename Config::mutex_type *M = Config::getMutex(Copy.Map->Data); + unique_lock Guard; if (M) - M->acquire(); + Guard = unique_lock(*M); KeyT typed_new_key = cast(new_key); // Can destroy *this: @@ -245,27 +263,24 @@ public: Copy.Map->insert(std::make_pair(typed_new_key, Target)); } } - if (M) - M->release(); } }; template struct DenseMapInfo > { typedef ValueMapCallbackVH VH; - typedef DenseMapInfo PointerInfo; static inline VH getEmptyKey() { - return VH(PointerInfo::getEmptyKey(), nullptr); + return VH(DenseMapInfo::getEmptyKey()); } static inline VH getTombstoneKey() { - return VH(PointerInfo::getTombstoneKey(), nullptr); + return VH(DenseMapInfo::getTombstoneKey()); } static unsigned getHashValue(const VH &Val) { - return PointerInfo::getHashValue(Val.Unwrap()); + return DenseMapInfo::getHashValue(Val.Unwrap()); } static unsigned getHashValue(const KeyT &Val) { - return PointerInfo::getHashValue(Val); + return DenseMapInfo::getHashValue(Val); } static bool isEqual(const VH &LHS, const VH &RHS) { return LHS == RHS; diff --git a/include/llvm/IR/Verifier.h b/include/llvm/IR/Verifier.h index 0272e20..43bd123 100644 --- a/include/llvm/IR/Verifier.h +++ b/include/llvm/IR/Verifier.h @@ -77,8 +77,8 @@ class VerifierPass { public: explicit VerifierPass(bool FatalErrors = true) : FatalErrors(FatalErrors) {} - PreservedAnalyses run(Module *M); - PreservedAnalyses run(Function *F); + PreservedAnalyses run(Module &M); + PreservedAnalyses run(Function &F); static StringRef name() { return "VerifierPass"; } }; diff --git a/include/llvm/IRReader/IRReader.h b/include/llvm/IRReader/IRReader.h index 59ffc09..2d9ace0 100644 --- a/include/llvm/IRReader/IRReader.h +++ b/include/llvm/IRReader/IRReader.h @@ -15,12 +15,12 @@ #ifndef LLVM_IRREADER_IRREADER_H #define LLVM_IRREADER_IRREADER_H +#include "llvm/Support/MemoryBuffer.h" #include namespace llvm { class Module; -class MemoryBuffer; class SMDiagnostic; class LLVMContext; @@ -28,20 +28,21 @@ class LLVMContext; /// for it which does lazy deserialization of function bodies. Otherwise, /// attempt to parse it as LLVM Assembly and return a fully populated /// Module. -Module *getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, - LLVMContext &Context); +std::unique_ptr getLazyIRFileModule(StringRef Filename, + SMDiagnostic &Err, + LLVMContext &Context); /// If the given MemoryBuffer holds a bitcode image, return a Module /// for it. Otherwise, attempt to parse it as LLVM Assembly and return -/// a Module for it. This function *never* takes ownership of Buffer. -Module *ParseIR(MemoryBuffer *Buffer, SMDiagnostic &Err, LLVMContext &Context); +/// a Module for it. +std::unique_ptr parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, + LLVMContext &Context); /// If the given file holds a bitcode image, return a Module for it. /// Otherwise, attempt to parse it as LLVM Assembly and return a Module /// for it. -Module *ParseIRFile(const std::string &Filename, SMDiagnostic &Err, - LLVMContext &Context); - +std::unique_ptr parseIRFile(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context); } #endif diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 02f4259..3028003 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -71,8 +71,9 @@ void initializeAliasDebuggerPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); -void initializeAtomicExpandLoadLinkedPass(PassRegistry&); +void initializeAtomicExpandPass(PassRegistry&); void initializeSampleProfileLoaderPass(PassRegistry&); +void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry &); @@ -89,6 +90,8 @@ void initializeCFGOnlyPrinterPass(PassRegistry&); void initializeCFGOnlyViewerPass(PassRegistry&); void initializeCFGPrinterPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeCFLAliasAnalysisPass(PassRegistry&); +void initializeForwardControlFlowIntegrityPass(PassRegistry&); void initializeFlattenCFGPassPass(PassRegistry&); void initializeStructurizeCFGPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&); @@ -103,7 +106,6 @@ void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); void initializeDCEPass(PassRegistry&); void initializeDSEPass(PassRegistry&); -void initializeDebugIRPass(PassRegistry&); void initializeDebugInfoVerifierLegacyPassPass(PassRegistry &); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); @@ -119,15 +121,16 @@ void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); void initializeGCOVProfilerPass(PassRegistry&); +void initializeInstrProfilingPass(PassRegistry&); void initializeAddressSanitizerPass(PassRegistry&); void initializeAddressSanitizerModulePass(PassRegistry&); void initializeMemorySanitizerPass(PassRegistry&); void initializeThreadSanitizerPass(PassRegistry&); +void initializeSanitizerCoverageModulePass(PassRegistry&); void initializeDataFlowSanitizerPass(PassRegistry&); void initializeScalarizerPass(PassRegistry&); void initializeEarlyCSEPass(PassRegistry&); void initializeExpandISelPseudosPass(PassRegistry&); -void initializeFindUsedTypesPass(PassRegistry&); void initializeFunctionAttrsPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); @@ -207,6 +210,7 @@ void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&); +void initializePAEvalPass(PassRegistry &); void initializeOptimizePHIsPass(PassRegistry&); void initializePartiallyInlineLibCallsPass(PassRegistry&); void initializePEIPass(PassRegistry&); @@ -259,10 +263,13 @@ void initializeTailDuplicatePassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); void initializeDataLayoutPassPass(PassRegistry &); void initializeTargetTransformInfoAnalysisGroup(PassRegistry&); +void initializeFunctionTargetTransformInfoPass(PassRegistry &); void initializeNoTTIPass(PassRegistry&); void initializeTargetLibraryInfoPass(PassRegistry&); +void initializeAssumptionCacheTrackerPass(PassRegistry &); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAliasAnalysisPass(PassRegistry&); +void initializeScopedNoAliasAAPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); @@ -277,7 +284,9 @@ void initializeSLPVectorizerPass(PassRegistry&); void initializeBBVectorizePass(PassRegistry&); void initializeMachineFunctionPrinterPassPass(PassRegistry&); void initializeStackMapLivenessPass(PassRegistry&); +void initializeMachineCombinerPass(PassRegistry &); void initializeLoadCombinePass(PassRegistry&); +void initializeRewriteSymbolsPass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index b19b232..0c9ce4a 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -32,8 +32,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LTO_CODE_GENERATOR_H -#define LTO_CODE_GENERATOR_H +#ifndef LLVM_LTO_LTOCODEGENERATOR_H +#define LLVM_LTO_LTOCODEGENERATOR_H #include "llvm-c/lto.h" #include "llvm/ADT/ArrayRef.h" @@ -61,10 +61,11 @@ struct LTOCodeGenerator { static const char *getVersionString(); LTOCodeGenerator(); + LTOCodeGenerator(std::unique_ptr Context); ~LTOCodeGenerator(); // Merge given module, return true on success. - bool addModule(struct LTOModule*, std::string &errMsg); + bool addModule(struct LTOModule *); void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); @@ -101,6 +102,7 @@ struct LTOCodeGenerator { bool disableOpt, bool disableInline, bool disableGVNLoadPRE, + bool disableVectorization, std::string &errMsg); // As with compile_to_file(), this function compiles the merged module into @@ -112,19 +114,23 @@ struct LTOCodeGenerator { bool disableOpt, bool disableInline, bool disableGVNLoadPRE, + bool disableVectorization, std::string &errMsg); void setDiagnosticHandler(lto_diagnostic_handler_t, void *); + LLVMContext &getContext() { return Context; } + private: void initializeLTOPasses(); bool generateObjectFile(raw_ostream &out, bool disableOpt, bool disableInline, - bool disableGVNLoadPRE, std::string &errMsg); + bool disableGVNLoadPRE, bool disableVectorization, + std::string &errMsg); void applyScopeRestrictions(); - void applyRestriction(GlobalValue &GV, const ArrayRef &Libcalls, + void applyRestriction(GlobalValue &GV, ArrayRef Libcalls, std::vector &MustPreserveList, - SmallPtrSet &AsmUsed, + SmallPtrSetImpl &AsmUsed, Mangler &Mangler); bool determineTarget(std::string &errMsg); @@ -134,6 +140,8 @@ private: typedef StringMap StringSet; + void initialize(); + std::unique_ptr OwnedContext; LLVMContext &Context; Linker IRLinker; TargetMachine *TargetMach; @@ -142,7 +150,7 @@ private: lto_codegen_model CodeModel; StringSet MustPreserveSymbols; StringSet AsmUndefinedRefs; - MemoryBuffer *NativeObjectFile; + std::unique_ptr NativeObjectFile; std::vector CodegenOptions; std::string MCpu; std::string MAttr; @@ -152,4 +160,4 @@ private: void *DiagContext; }; } -#endif // LTO_CODE_GENERATOR_H +#endif diff --git a/include/llvm/LTO/LTOModule.h b/include/llvm/LTO/LTOModule.h index c43846a..53c2b8e 100644 --- a/include/llvm/LTO/LTOModule.h +++ b/include/llvm/LTO/LTOModule.h @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LTO_MODULE_H -#define LTO_MODULE_H +#ifndef LLVM_LTO_LTOMODULE_H +#define LLVM_LTO_LTOMODULE_H #include "llvm-c/lto.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringSet.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" @@ -37,8 +38,6 @@ namespace llvm { /// struct LTOModule { private: - typedef StringMap StringSet; - struct NameAndAttributes { const char *name; uint32_t attributes; @@ -46,21 +45,27 @@ private: const GlobalValue *symbol; }; + std::unique_ptr OwnedContext; + std::unique_ptr IRFile; std::unique_ptr _target; - StringSet _linkeropt_strings; + StringSet<> _linkeropt_strings; std::vector _deplibs; std::vector _linkeropts; std::vector _symbols; // _defines and _undefines only needed to disambiguate tentative definitions - StringSet _defines; + StringSet<> _defines; StringMap _undefines; std::vector _asm_undefines; LTOModule(std::unique_ptr Obj, TargetMachine *TM); + LTOModule(std::unique_ptr Obj, TargetMachine *TM, + std::unique_ptr Context); public: + ~LTOModule(); + /// Returns 'true' if the file or memory contents is LLVM bitcode. static bool isBitcodeFile(const void *mem, size_t length); static bool isBitcodeFile(const char *path); @@ -71,8 +76,8 @@ public: StringRef triplePrefix); /// Create a MemoryBuffer from a memory range with an optional name. - static MemoryBuffer *makeBuffer(const void *mem, size_t length, - StringRef name = ""); + static std::unique_ptr + makeBuffer(const void *mem, size_t length, StringRef name = ""); /// Create an LTOModule. N.B. These methods take ownership of the buffer. The /// caller must have initialized the Targets, the TargetMCs, the AsmPrinters, @@ -95,6 +100,13 @@ public: TargetOptions options, std::string &errMsg, StringRef path = ""); + static LTOModule *createInLocalContext(const void *mem, size_t length, + TargetOptions options, + std::string &errMsg, StringRef path); + static LTOModule *createInContext(const void *mem, size_t length, + TargetOptions options, std::string &errMsg, + StringRef path, LLVMContext *Context); + const Module &getModule() const { return const_cast(this)->getModule(); } @@ -202,10 +214,9 @@ private: /// Get string that the data pointer points to. bool objcClassNameFromExpression(const Constant *c, std::string &name); - /// Create an LTOModule (private version). N.B. This method takes ownership of - /// the buffer. - static LTOModule *makeLTOModule(std::unique_ptr Buffer, - TargetOptions options, std::string &errMsg); + /// Create an LTOModule (private version). + static LTOModule *makeLTOModule(MemoryBufferRef Buffer, TargetOptions options, + std::string &errMsg, LLVMContext *Context); }; } -#endif // LTO_MODULE_H +#endif diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index e06560c..2e8feab 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -18,7 +18,6 @@ #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/CallPrinter.h" #include "llvm/Analysis/DomPrinter.h" -#include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/IntervalPartition.h" #include "llvm/Analysis/Lint.h" #include "llvm/Analysis/Passes.h" @@ -33,6 +32,7 @@ #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/SymbolRewriter.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" #include @@ -52,15 +52,18 @@ namespace { (void) llvm::createAliasAnalysisCounterPass(); (void) llvm::createAliasDebugger(); (void) llvm::createArgumentPromotionPass(); + (void) llvm::createAlignmentFromAssumptionsPass(); (void) llvm::createBasicAliasAnalysisPass(); (void) llvm::createLibCallAliasAnalysisPass(nullptr); (void) llvm::createScalarEvolutionAliasAnalysisPass(); (void) llvm::createTypeBasedAliasAnalysisPass(); + (void) llvm::createScopedNoAliasAAPass(); (void) llvm::createBoundsCheckingPass(); (void) llvm::createBreakCriticalEdgesPass(); (void) llvm::createCallGraphPrinterPass(); (void) llvm::createCallGraphViewerPass(); (void) llvm::createCFGSimplificationPass(); + (void) llvm::createCFLAliasAnalysisPass(); (void) llvm::createStructurizeCFGPass(); (void) llvm::createConstantMergePass(); (void) llvm::createConstantPropagationPass(); @@ -75,6 +78,7 @@ namespace { (void) llvm::createDomOnlyViewerPass(); (void) llvm::createDomViewerPass(); (void) llvm::createGCOVProfilerPass(); + (void) llvm::createInstrProfilingPass(); (void) llvm::createFunctionInliningPass(); (void) llvm::createAlwaysInlinerPass(); (void) llvm::createGlobalDCEPass(); @@ -107,6 +111,7 @@ namespace { (void) llvm::createObjCARCExpandPass(); (void) llvm::createObjCARCContractPass(); (void) llvm::createObjCARCOptPass(); + (void) llvm::createPAEvalPass(); (void) llvm::createPromoteMemoryToRegisterPass(); (void) llvm::createDemoteRegisterToMemoryPass(); (void) llvm::createPruneEHPass(); @@ -134,7 +139,7 @@ namespace { (void) llvm::createConstantHoistingPass(); (void) llvm::createCodeGenPreparePass(); (void) llvm::createEarlyCSEPass(); - (void)llvm::createMergedLoadStoreMotionPass(); + (void) llvm::createMergedLoadStoreMotionPass(); (void) llvm::createGVNPass(); (void) llvm::createMemCpyOptPass(); (void) llvm::createLoopDeletionPass(); @@ -160,15 +165,15 @@ namespace { (void) llvm::createPartiallyInlineLibCallsPass(); (void) llvm::createScalarizerPass(); (void) llvm::createSeparateConstOffsetFromGEPPass(); + (void) llvm::createRewriteSymbolsPass(); (void)new llvm::IntervalPartition(); - (void)new llvm::FindUsedTypes(); (void)new llvm::ScalarEvolution(); ((llvm::Function*)nullptr)->viewCFGOnly(); llvm::RGPassManager RGM; ((llvm::RegionPass*)nullptr)->runOnRegion((llvm::Region*)nullptr, RGM); llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)nullptr); - X.add((llvm::Value*)nullptr, 0, nullptr); // for -print-alias-sets + X.add(nullptr, 0, llvm::AAMDNodes()); // for -print-alias-sets } } ForcePassLinking; // Force link by creating a global definition. } diff --git a/include/llvm/Linker/Linker.h b/include/llvm/Linker/Linker.h index 6254bbb..9c3ecea5 100644 --- a/include/llvm/Linker/Linker.h +++ b/include/llvm/Linker/Linker.h @@ -10,52 +10,78 @@ #ifndef LLVM_LINKER_LINKER_H #define LLVM_LINKER_LINKER_H -#include "llvm/ADT/SmallPtrSet.h" -#include +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/IR/DiagnosticInfo.h" namespace llvm { - -class Comdat; -class GlobalValue; class Module; -class StringRef; class StructType; +class Type; /// This class provides the core functionality of linking in LLVM. It keeps a /// pointer to the merged module so far. It doesn't take ownership of the /// module since it is assumed that the user of this class will want to do /// something with it after the linking. class Linker { - public: - enum LinkerMode { - DestroySource = 0, // Allow source module to be destroyed. - PreserveSource = 1 // Preserve the source module. +public: + struct StructTypeKeyInfo { + struct KeyTy { + ArrayRef ETypes; + bool IsPacked; + KeyTy(ArrayRef E, bool P); + KeyTy(const StructType *ST); + bool operator==(const KeyTy &that) const; + bool operator!=(const KeyTy &that) const; }; + static StructType *getEmptyKey(); + static StructType *getTombstoneKey(); + static unsigned getHashValue(const KeyTy &Key); + static unsigned getHashValue(const StructType *ST); + static bool isEqual(const KeyTy &LHS, const StructType *RHS); + static bool isEqual(const StructType *LHS, const StructType *RHS); + }; + + typedef DenseSet NonOpaqueStructTypeSet; + typedef DenseSet OpaqueStructTypeSet; + + struct IdentifiedStructTypeSet { + // The set of opaque types is the composite module. + OpaqueStructTypeSet OpaqueStructTypes; + + // The set of identified but non opaque structures in the composite module. + NonOpaqueStructTypeSet NonOpaqueStructTypes; + + void addNonOpaque(StructType *Ty); + void addOpaque(StructType *Ty); + StructType *findNonOpaque(ArrayRef ETypes, bool IsPacked); + bool hasType(StructType *Ty); + }; + + Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Linker(Module *M); + ~Linker(); + + Module *getModule() const { return Composite; } + void deleteModule(); - Linker(Module *M, bool SuppressWarnings=false); - ~Linker(); + /// \brief Link \p Src into the composite. The source is destroyed. + /// Returns true on error. + bool linkInModule(Module *Src); - Module *getModule() const { return Composite; } - void deleteModule(); + static bool LinkModules(Module *Dest, Module *Src, + DiagnosticHandlerFunction DiagnosticHandler); - /// \brief Link \p Src into the composite. The source is destroyed if - /// \p Mode is DestroySource and preserved if it is PreserveSource. - /// If \p ErrorMsg is not null, information about any error is written - /// to it. - /// Returns true on error. - bool linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg); - bool linkInModule(Module *Src, std::string *ErrorMsg) { - return linkInModule(Src, Linker::DestroySource, ErrorMsg); - } + static bool LinkModules(Module *Dest, Module *Src); - static bool LinkModules(Module *Dest, Module *Src, unsigned Mode, - std::string *ErrorMsg); +private: + void init(Module *M, DiagnosticHandlerFunction DiagnosticHandler); + Module *Composite; - private: - Module *Composite; - SmallPtrSet IdentifiedStructTypes; + IdentifiedStructTypeSet IdentifiedStructTypes; - bool SuppressWarnings; + DiagnosticHandlerFunction DiagnosticHandler; }; } // End llvm namespace diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h index 2e76074..1fc0332 100644 --- a/include/llvm/MC/ConstantPools.h +++ b/include/llvm/MC/ConstantPools.h @@ -12,10 +12,12 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_CONSTANTPOOL_H -#define LLVM_MC_CONSTANTPOOL_H +#ifndef LLVM_MC_CONSTANTPOOLS_H +#define LLVM_MC_CONSTANTPOOLS_H +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" + namespace llvm { class MCContext; class MCExpr; diff --git a/include/llvm/MC/MCAnalysis/MCAtom.h b/include/llvm/MC/MCAnalysis/MCAtom.h deleted file mode 100644 index 33f3431..0000000 --- a/include/llvm/MC/MCAnalysis/MCAtom.h +++ /dev/null @@ -1,199 +0,0 @@ -//===-- MCAtom.h ------------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCAtom class, which is used to -// represent a contiguous region in a decoded object that is uniformly data or -// instructions. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCATOM_H -#define LLVM_MC_MCANALYSIS_MCATOM_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/DataTypes.h" -#include - -namespace llvm { - -class MCModule; - -class MCAtom; -class MCTextAtom; -class MCDataAtom; - -/// \brief Represents a contiguous range of either instructions (a TextAtom) -/// or data (a DataAtom). Address ranges are expressed as _closed_ intervals. -class MCAtom { - virtual void anchor(); -public: - virtual ~MCAtom() {} - - enum AtomKind { TextAtom, DataAtom }; - AtomKind getKind() const { return Kind; } - - /// \brief Get the start address of the atom. - uint64_t getBeginAddr() const { return Begin; } - /// \brief Get the end address, i.e. the last one inside the atom. - uint64_t getEndAddr() const { return End; } - - /// \name Atom modification methods: - /// When modifying a TextAtom, keep instruction boundaries in mind. - /// For instance, split must me given the start address of an instruction. - /// @{ - - /// \brief Splits the atom in two at a given address. - /// \param SplitPt Address at which to start a new atom, splitting this one. - /// \returns The newly created atom starting at \p SplitPt. - virtual MCAtom *split(uint64_t SplitPt) = 0; - - /// \brief Truncates an atom, discarding everything after \p TruncPt. - /// \param TruncPt Last byte address to be contained in this atom. - virtual void truncate(uint64_t TruncPt) = 0; - /// @} - - /// \name Naming: - /// - /// This is mostly for display purposes, and may contain anything that hints - /// at what the atom contains: section or symbol name, BB start address, .. - /// @{ - StringRef getName() const { return Name; } - void setName(StringRef NewName) { Name = NewName.str(); } - /// @} - -protected: - const AtomKind Kind; - std::string Name; - MCModule *Parent; - uint64_t Begin, End; - - friend class MCModule; - MCAtom(AtomKind K, MCModule *P, uint64_t B, uint64_t E) - : Kind(K), Name("(unknown)"), Parent(P), Begin(B), End(E) { } - - /// \name Atom remapping helpers - /// @{ - - /// \brief Remap the atom, using the given range, updating Begin/End. - /// One or both of the bounds can remain the same, but overlapping with other - /// atoms in the module is still forbidden. - void remap(uint64_t NewBegin, uint64_t NewEnd); - - /// \brief Remap the atom to prepare for a truncation at TruncPt. - /// Equivalent to: - /// \code - /// // Bound checks - /// remap(Begin, TruncPt); - /// \endcode - void remapForTruncate(uint64_t TruncPt); - - /// \brief Remap the atom to prepare for a split at SplitPt. - /// The bounds for the resulting atoms are returned in {L,R}{Begin,End}. - /// The current atom is truncated to \p LEnd. - void remapForSplit(uint64_t SplitPt, - uint64_t &LBegin, uint64_t &LEnd, - uint64_t &RBegin, uint64_t &REnd); - /// @} -}; - -/// \name Text atom -/// @{ - -/// \brief An entry in an MCTextAtom: a disassembled instruction. -/// NOTE: Both the Address and Size field are actually redundant when taken in -/// the context of the text atom, and may better be exposed in an iterator -/// instead of stored in the atom, which would replace this class. -class MCDecodedInst { -public: - MCInst Inst; - uint64_t Address; - uint64_t Size; - MCDecodedInst(const MCInst &Inst, uint64_t Address, uint64_t Size) - : Inst(Inst), Address(Address), Size(Size) {} -}; - -/// \brief An atom consisting of disassembled instructions. -class MCTextAtom : public MCAtom { -private: - typedef std::vector InstListTy; - InstListTy Insts; - - /// \brief The address of the next appended instruction, i.e., the - /// address immediately after the last instruction in the atom. - uint64_t NextInstAddress; -public: - /// Append an instruction, expanding the atom if necessary. - void addInst(const MCInst &Inst, uint64_t Size); - - /// \name Instruction list access - /// @{ - typedef InstListTy::const_iterator const_iterator; - const_iterator begin() const { return Insts.begin(); } - const_iterator end() const { return Insts.end(); } - - const MCDecodedInst &back() const { return Insts.back(); } - const MCDecodedInst &at(size_t n) const { return Insts.at(n); } - size_t size() const { return Insts.size(); } - /// @} - - /// \name Atom type specific split/truncate logic. - /// @{ - MCTextAtom *split(uint64_t SplitPt) override; - void truncate(uint64_t TruncPt) override; - /// @} - - // Class hierarchy. - static bool classof(const MCAtom *A) { return A->getKind() == TextAtom; } -private: - friend class MCModule; - // Private constructor - only callable by MCModule - MCTextAtom(MCModule *P, uint64_t Begin, uint64_t End) - : MCAtom(TextAtom, P, Begin, End), NextInstAddress(Begin) {} -}; -/// @} - -/// \name Data atom -/// @{ - -/// \brief An entry in an MCDataAtom. -// NOTE: This may change to a more complex type in the future. -typedef uint8_t MCData; - -/// \brief An atom consising of a sequence of bytes. -class MCDataAtom : public MCAtom { - std::vector Data; - -public: - /// Append a data entry, expanding the atom if necessary. - void addData(const MCData &D); - - /// Get a reference to the data in this atom. - ArrayRef getData() const { return Data; } - - /// \name Atom type specific split/truncate logic. - /// @{ - MCDataAtom *split(uint64_t SplitPt) override; - void truncate(uint64_t TruncPt) override; - /// @} - - // Class hierarchy. - static bool classof(const MCAtom *A) { return A->getKind() == DataAtom; } -private: - friend class MCModule; - // Private constructor - only callable by MCModule - MCDataAtom(MCModule *P, uint64_t Begin, uint64_t End) - : MCAtom(DataAtom, P, Begin, End) { - Data.reserve(End + 1 - Begin); - } -}; - -} - -#endif diff --git a/include/llvm/MC/MCAnalysis/MCFunction.h b/include/llvm/MC/MCAnalysis/MCFunction.h deleted file mode 100644 index 44fa450..0000000 --- a/include/llvm/MC/MCAnalysis/MCFunction.h +++ /dev/null @@ -1,142 +0,0 @@ -//===-- MCFunction.h --------------------------------------------*- C++ -*-===// -// -// 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 data structures to hold a CFG reconstructed from -// machine code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCFUNCTION_H -#define LLVM_MC_MCANALYSIS_MCFUNCTION_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCInst.h" -#include -#include -#include - -namespace llvm { - -class MCFunction; -class MCModule; -class MCTextAtom; - -/// \brief Basic block containing a sequence of disassembled instructions. -/// The basic block is backed by an MCTextAtom, which holds the instructions, -/// and the address range it covers. -/// Create a basic block using MCFunction::createBlock. -class MCBasicBlock { - const MCTextAtom *Insts; - - // MCFunction owns the basic block. - MCFunction *Parent; - friend class MCFunction; - MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent); - - /// \name Predecessors/Successors, to represent the CFG. - /// @{ - typedef std::vector BasicBlockListTy; - BasicBlockListTy Successors; - BasicBlockListTy Predecessors; - /// @} -public: - - /// \brief Get the backing MCTextAtom, containing the instruction sequence. - const MCTextAtom *getInsts() const { return Insts; } - - /// \name Get the owning MCFunction. - /// @{ - const MCFunction *getParent() const { return Parent; } - MCFunction *getParent() { return Parent; } - /// @} - - /// MC CFG access: Predecessors/Successors. - /// @{ - typedef BasicBlockListTy::const_iterator succ_const_iterator; - succ_const_iterator succ_begin() const { return Successors.begin(); } - succ_const_iterator succ_end() const { return Successors.end(); } - - typedef BasicBlockListTy::const_iterator pred_const_iterator; - pred_const_iterator pred_begin() const { return Predecessors.begin(); } - pred_const_iterator pred_end() const { return Predecessors.end(); } - - void addSuccessor(const MCBasicBlock *MCBB); - bool isSuccessor(const MCBasicBlock *MCBB) const; - - void addPredecessor(const MCBasicBlock *MCBB); - bool isPredecessor(const MCBasicBlock *MCBB) const; - - /// \brief Split block, mirrorring NewAtom = Insts->split(..). - /// This moves all successors to \p SplitBB, and - /// adds a fallthrough to it. - /// \p SplitBB The result of splitting Insts, a basic block directly following - /// this basic block. - void splitBasicBlock(MCBasicBlock *SplitBB); - /// @} -}; - -/// \brief Represents a function in machine code, containing MCBasicBlocks. -/// MCFunctions are created by MCModule. -class MCFunction { - MCFunction (const MCFunction&) LLVM_DELETED_FUNCTION; - MCFunction& operator=(const MCFunction&) LLVM_DELETED_FUNCTION; - - std::string Name; - MCModule *ParentModule; - typedef std::vector> BasicBlockListTy; - BasicBlockListTy Blocks; - - // MCModule owns the function. - friend class MCModule; - MCFunction(StringRef Name, MCModule *Parent); - -public: - /// \brief Create an MCBasicBlock backed by Insts and add it to this function. - /// \param Insts Sequence of straight-line code backing the basic block. - /// \returns The newly created basic block. - MCBasicBlock &createBlock(const MCTextAtom &Insts); - - StringRef getName() const { return Name; } - - /// \name Get the owning MC Module. - /// @{ - const MCModule *getParent() const { return ParentModule; } - MCModule *getParent() { return ParentModule; } - /// @} - - /// \name Access to the function's basic blocks. No ordering is enforced, - /// except that the first block is the entry block. - /// @{ - /// \brief Get the entry point basic block. - const MCBasicBlock *getEntryBlock() const { return front(); } - MCBasicBlock *getEntryBlock() { return front(); } - - bool empty() const { return Blocks.empty(); } - - typedef BasicBlockListTy::const_iterator const_iterator; - typedef BasicBlockListTy:: iterator iterator; - const_iterator begin() const { return Blocks.begin(); } - iterator begin() { return Blocks.begin(); } - const_iterator end() const { return Blocks.end(); } - iterator end() { return Blocks.end(); } - - const MCBasicBlock* front() const { return Blocks.front().get(); } - MCBasicBlock* front() { return Blocks.front().get(); } - const MCBasicBlock* back() const { return Blocks.back().get(); } - MCBasicBlock* back() { return Blocks.back().get(); } - - /// \brief Find the basic block, if any, that starts at \p StartAddr. - const MCBasicBlock *find(uint64_t StartAddr) const; - MCBasicBlock *find(uint64_t StartAddr); - /// @} -}; - -} - -#endif diff --git a/include/llvm/MC/MCAnalysis/MCModule.h b/include/llvm/MC/MCAnalysis/MCModule.h deleted file mode 100644 index cf7e2c0..0000000 --- a/include/llvm/MC/MCAnalysis/MCModule.h +++ /dev/null @@ -1,134 +0,0 @@ -//===-- MCModule.h - MCModule class -----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCModule class, which is used to -// represent a complete, disassembled object file or executable. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCMODULE_H -#define LLVM_MC_MCANALYSIS_MCMODULE_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" -#include -#include - -namespace llvm { - -class MCAtom; -class MCBasicBlock; -class MCDataAtom; -class MCFunction; -class MCObjectDisassembler; -class MCTextAtom; - -/// \brief A completely disassembled object file or executable. -/// It comprises a list of MCAtom's, each representing a contiguous range of -/// either instructions or data. -/// An MCModule is created using MCObjectDisassembler::buildModule. -class MCModule { - /// \name Atom tracking - /// @{ - - /// \brief Atoms in this module, sorted by begin address. - /// FIXME: This doesn't handle overlapping atoms (which happen when a basic - /// block starts in the middle of an instruction of another basic block.) - typedef std::vector AtomListTy; - AtomListTy Atoms; - - // For access to map/remap. - friend class MCAtom; - - /// \brief Remap \p Atom to the given range, and update its Begin/End fields. - /// \param Atom An atom belonging to this module. - /// An atom should always use this method to update its bounds, because this - /// enables the owning MCModule to keep track of its atoms. - void remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd); - - /// \brief Insert an atom in the module, using its Begin and End addresses. - void map(MCAtom *NewAtom); - /// @} - - /// \name Basic block tracking - /// @{ - typedef std::vector BBsByAtomTy; - BBsByAtomTy BBsByAtom; - - // For access to basic block > atom tracking. - friend class MCBasicBlock; - friend class MCTextAtom; - - /// \brief Keep track of \p BBBackedByAtom as being backed by \p Atom. - /// This is used to update succs/preds when \p Atom is split. - void trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BBBackedByAtom); - void splitBasicBlocksForAtom(const MCTextAtom *TA, const MCTextAtom *NewTA); - /// @} - - /// \name Function tracking - /// @{ - typedef std::vector> FunctionListTy; - FunctionListTy Functions; - /// @} - - /// The address of the entrypoint function. - uint64_t Entrypoint; - - MCModule (const MCModule &) LLVM_DELETED_FUNCTION; - MCModule& operator=(const MCModule &) LLVM_DELETED_FUNCTION; - - // MCObjectDisassembler creates MCModules. - friend class MCObjectDisassembler; - -public: - MCModule(); - ~MCModule(); - - /// \name Create a new MCAtom covering the specified offset range. - /// @{ - MCTextAtom *createTextAtom(uint64_t Begin, uint64_t End); - MCDataAtom *createDataAtom(uint64_t Begin, uint64_t End); - /// @} - - /// \name Access to the owned atom list, ordered by begin address. - /// @{ - const MCAtom *findAtomContaining(uint64_t Addr) const; - MCAtom *findAtomContaining(uint64_t Addr); - const MCAtom *findFirstAtomAfter(uint64_t Addr) const; - MCAtom *findFirstAtomAfter(uint64_t Addr); - - typedef AtomListTy::const_iterator const_atom_iterator; - typedef AtomListTy:: iterator atom_iterator; - const_atom_iterator atom_begin() const { return Atoms.begin(); } - atom_iterator atom_begin() { return Atoms.begin(); } - const_atom_iterator atom_end() const { return Atoms.end(); } - atom_iterator atom_end() { return Atoms.end(); } - /// @} - - /// \brief Create a new MCFunction. - MCFunction *createFunction(StringRef Name); - - /// \name Access to the owned function list. - /// @{ - typedef FunctionListTy::const_iterator const_func_iterator; - typedef FunctionListTy:: iterator func_iterator; - const_func_iterator func_begin() const { return Functions.begin(); } - func_iterator func_begin() { return Functions.begin(); } - const_func_iterator func_end() const { return Functions.end(); } - func_iterator func_end() { return Functions.end(); } - /// @} - - /// \brief Get the address of the entrypoint function, or 0 if there is none. - uint64_t getEntrypoint() const { return Entrypoint; } -}; - -} - -#endif diff --git a/include/llvm/MC/MCAnalysis/MCModuleYAML.h b/include/llvm/MC/MCAnalysis/MCModuleYAML.h deleted file mode 100644 index 4856277..0000000 --- a/include/llvm/MC/MCAnalysis/MCModuleYAML.h +++ /dev/null @@ -1,40 +0,0 @@ -//===- MCModuleYAML.h - MCModule YAMLIO implementation ----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// \brief This file declares classes for handling the YAML representation -/// of MCModule. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCANALYSIS_MCMODULEYAML_H -#define LLVM_MC_MCANALYSIS_MCMODULEYAML_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { - -class MCInstrInfo; -class MCRegisterInfo; - -/// \brief Dump a YAML representation of the MCModule \p MCM to \p OS. -/// \returns The empty string on success, an error message on failure. -StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, - const MCInstrInfo &MII, const MCRegisterInfo &MRI); - -/// \brief Creates a new module and returns it in \p MCM. -/// \returns The empty string on success, an error message on failure. -StringRef yaml2mcmodule(std::unique_ptr &MCM, StringRef YamlContent, - const MCInstrInfo &MII, const MCRegisterInfo &MRI); - -} // end namespace llvm - -#endif diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 82b65fd..2162710 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -1,4 +1,4 @@ -//===-- llvm/MC/MCAsmBack.h - MC Asm Backend --------------------*- C++ -*-===// +//===-- llvm/MC/MCAsmBackend.h - MC Asm Backend -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -61,20 +61,6 @@ public: /// markers. If not, data region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } - /// doesSectionRequireSymbols - Check whether the given section requires that - /// all symbols (even temporaries) have symbol table entries. - virtual bool doesSectionRequireSymbols(const MCSection &Section) const { - return false; - } - - /// isSectionAtomizable - Check whether the given section can be split into - /// atoms. - /// - /// \see MCAssembler::isSymbolLinkerVisible(). - virtual bool isSectionAtomizable(const MCSection &Section) const { - return true; - } - /// @name Target Fixup Interfaces /// @{ @@ -146,7 +132,7 @@ public: /// \brief Generate the compact unwind encoding for the CFI instructions. virtual uint32_t - generateCompactUnwindEncoding(ArrayRef) const { + generateCompactUnwindEncoding(ArrayRef) const { return 0; } }; diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 06e473d..a750a0f 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -31,22 +31,23 @@ class MCContext; namespace WinEH { enum class EncodingType { - ET_Invalid, /// Invalid - ET_Alpha, /// Windows Alpha - ET_Alpha64, /// Windows AXP64 - ET_ARM, /// Windows NT (Windows on ARM) - ET_CE, /// Windows CE ARM, PowerPC, SH3, SH4 - ET_Itanium, /// Windows x64, Windows Itanium (IA-64) - ET_MIPS = ET_Alpha, + Invalid, /// Invalid + Alpha, /// Windows Alpha + Alpha64, /// Windows AXP64 + ARM, /// Windows NT (Windows on ARM) + CE, /// Windows CE ARM, PowerPC, SH3, SH4 + Itanium, /// Windows x64, Windows Itanium (IA-64) + MIPS = Alpha, }; } enum class ExceptionHandling { - None, /// No exception support - DwarfCFI, /// DWARF-like instruction based exceptions - SjLj, /// setjmp/longjmp based exceptions - ARM, /// ARM EHABI - WinEH, /// Windows Exception Handling + None, /// No exception support + DwarfCFI, /// DWARF-like instruction based exceptions + SjLj, /// setjmp/longjmp based exceptions + ARM, /// ARM EHABI + ItaniumWinEH, /// Itanium EH built on Windows unwind info (.pdata and .xdata) + MSVC, /// MSVC compatible exception handling }; namespace LCOMM { @@ -87,16 +88,11 @@ protected: bool HasMachoTBSSDirective; /// True if the compiler should emit a ".reference .constructors_used" or - /// ".reference .destructors_used" directive after the a static ctor/dtor + /// ".reference .destructors_used" directive after the static ctor/dtor /// list. This directive is only emitted in Static relocation model. Default /// is false. bool HasStaticCtorDtorReferenceInStaticMode; - /// True if the linker has a bug and requires that the debug_line section be - /// of a minimum size. In practice such a linker requires a non-empty line - /// sequence if a file is present. Default to false. - bool LinkerRequiresNonEmptyDwarfLines; - /// This is the maximum possible length of an instruction, which is needed to /// compute the size of an inline asm. Defaults to 4. unsigned MaxInstLength; @@ -128,6 +124,10 @@ protected: /// file. Defaults to "L" const char *PrivateGlobalPrefix; + /// This prefix is used for labels for basic blocks. Defaults to the same as + /// PrivateGlobalPrefix. + const char *PrivateLabelPrefix; + /// This prefix is used for symbols that should be passed through the /// assembler but be removed by the linker. This is 'l' on Darwin, currently /// used for some ObjC metadata. The default of "" meast that for this system @@ -220,11 +220,16 @@ protected: //===--- Global Variable Emission Directives --------------------------===// - /// This is the directive used to declare a global entity. Defaults to NULL. + /// This is the directive used to declare a global entity. Defaults to + /// ".globl". const char *GlobalDirective; - /// True if the assembler supports the .set directive. Defaults to true. - bool HasSetDirective; + /// True if the expression + /// .long f - g + /// uses an relocation but it can be supressed by writting + /// a = f - g + /// .long a + bool SetDirectiveSuppressesReloc; /// False if the assembler requires that we use /// \code @@ -265,6 +270,9 @@ protected: /// to false. bool HasNoDeadStrip; + /// Used to declare a global as being a weak symbol. Defaults to ".weak". + const char *WeakDirective; + /// This directive, if non-null, is used to declare a global as being a weak /// undefined symbol. Defaults to NULL. const char *WeakRefDirective; @@ -295,9 +303,6 @@ protected: //===--- Dwarf Emission Directives -----------------------------------===// - /// True if target asm supports leb128 directives. Defaults to false. - bool HasLEB128; - /// True if target supports emission of debugging information. Defaults to /// false. bool SupportsDebugInformation; @@ -377,6 +382,12 @@ public: return nullptr; } + /// \brief True if the section is atomized using the symbols in it. + /// This is false if the section is not atomized at all (most ELF sections) or + /// if it is atomized based on its contents (MachO' __TEXT,__cstring for + /// example). + virtual bool isSectionAtomizableBySymbols(const MCSection &Section) const; + virtual const MCExpr *getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, MCStreamer &Streamer) const; @@ -404,9 +415,6 @@ public: bool hasStaticCtorDtorReferenceInStaticMode() const { return HasStaticCtorDtorReferenceInStaticMode; } - bool getLinkerRequiresNonEmptyDwarfLines() const { - return LinkerRequiresNonEmptyDwarfLines; - } unsigned getMaxInstLength() const { return MaxInstLength; } unsigned getMinInstAlignment() const { return MinInstAlignment; } bool getDollarIsPC() const { return DollarIsPC; } @@ -421,6 +429,7 @@ public: bool useAssignmentForEHBegin() const { return UseAssignmentForEHBegin; } const char *getPrivateGlobalPrefix() const { return PrivateGlobalPrefix; } + const char *getPrivateLabelPrefix() const { return PrivateLabelPrefix; } bool hasLinkerPrivateGlobalPrefix() const { return LinkerPrivateGlobalPrefix[0] != '\0'; } @@ -445,7 +454,9 @@ public: bool getAlignmentIsInBytes() const { return AlignmentIsInBytes; } unsigned getTextAlignFillValue() const { return TextAlignFillValue; } const char *getGlobalDirective() const { return GlobalDirective; } - bool hasSetDirective() const { return HasSetDirective; } + bool doesSetDirectiveSuppressesReloc() const { + return SetDirectiveSuppressesReloc; + } bool hasAggressiveSymbolFolding() const { return HasAggressiveSymbolFolding; } bool getCOMMDirectiveAlignmentIsInBytes() const { return COMMDirectiveAlignmentIsInBytes; @@ -457,6 +468,7 @@ public: bool hasSingleParameterDotFile() const { return HasSingleParameterDotFile; } bool hasIdentDirective() const { return HasIdentDirective; } bool hasNoDeadStrip() const { return HasNoDeadStrip; } + const char *getWeakDirective() const { return WeakDirective; } const char *getWeakRefDirective() const { return WeakRefDirective; } bool hasWeakDefDirective() const { return HasWeakDefDirective; } bool hasWeakDefCanBeHiddenDirective() const { @@ -471,19 +483,27 @@ public: MCSymbolAttr getProtectedVisibilityAttr() const { return ProtectedVisibilityAttr; } - bool hasLEB128() const { return HasLEB128; } bool doesSupportDebugInformation() const { return SupportsDebugInformation; } bool doesSupportExceptionHandling() const { return ExceptionsType != ExceptionHandling::None; } ExceptionHandling getExceptionHandlingType() const { return ExceptionsType; } WinEH::EncodingType getWinEHEncodingType() const { return WinEHEncodingType; } - bool isExceptionHandlingDwarf() const { + + /// Return true if the exception handling type uses the language-specific data + /// area (LSDA) format specified by the Itanium C++ ABI. + bool usesItaniumLSDAForExceptions() const { return (ExceptionsType == ExceptionHandling::DwarfCFI || ExceptionsType == ExceptionHandling::ARM || - // Windows handler data still uses DWARF LSDA encoding. - ExceptionsType == ExceptionHandling::WinEH); + // This Windows EH type uses the Itanium LSDA encoding. + ExceptionsType == ExceptionHandling::ItaniumWinEH); } + + bool usesWindowsCFI() const { + return ExceptionsType == ExceptionHandling::ItaniumWinEH || + ExceptionsType == ExceptionHandling::MSVC; + } + bool doesDwarfUseRelocationsAcrossSections() const { return DwarfUsesRelocationsAcrossSections; } diff --git a/include/llvm/MC/MCAsmInfoDarwin.h b/include/llvm/MC/MCAsmInfoDarwin.h index 3d249f9..d587c3c 100644 --- a/include/llvm/MC/MCAsmInfoDarwin.h +++ b/include/llvm/MC/MCAsmInfoDarwin.h @@ -19,9 +19,9 @@ namespace llvm { class MCAsmInfoDarwin : public MCAsmInfo { - virtual void anchor(); public: explicit MCAsmInfoDarwin(); + bool isSectionAtomizableBySymbols(const MCSection &Section) const override; }; } diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h index 27fea84..7bd2460 100644 --- a/include/llvm/MC/MCAsmInfoELF.h +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -15,6 +15,9 @@ namespace llvm { class MCAsmInfoELF : public MCAsmInfo { virtual void anchor(); + const MCSection * + getNonexecutableStackSection(MCContext &Ctx) const override final; + protected: MCAsmInfoELF(); }; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 1cb34c2..31f29eb 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -11,6 +11,8 @@ #define LLVM_MC_MCASSEMBLER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/ilist.h" @@ -593,7 +595,10 @@ private: unsigned Alignment; /// \brief Keeping track of bundle-locked state. - BundleLockStateType BundleLockState; + BundleLockStateType BundleLockState; + + /// \brief Current nesting depth of bundle_lock directives. + unsigned BundleLockNestingDepth; /// \brief We've seen a bundle_lock directive but not its first instruction /// yet. @@ -665,9 +670,7 @@ public: return BundleLockState; } - void setBundleLockState(BundleLockStateType NewState) { - BundleLockState = NewState; - } + void setBundleLockState(BundleLockStateType NewState); bool isBundleGroupBeforeFirstInst() const { return BundleGroupBeforeFirstInst; @@ -684,34 +687,27 @@ public: // FIXME: Same concerns as with SectionData. class MCSymbolData : public ilist_node { -public: const MCSymbol *Symbol; - /// Fragment - The fragment this symbol's value is relative to, if any. - MCFragment *Fragment; - - /// Offset - The offset to apply to the fragment address to form this symbol's - /// value. - uint64_t Offset; - - /// IsExternal - True if this symbol is visible outside this translation - /// unit. - unsigned IsExternal : 1; + /// Fragment - The fragment this symbol's value is relative to, if any. Also + /// stores if this symbol is visible outside this translation unit (bit 0) or + /// if it is private extern (bit 1). + PointerIntPair Fragment; - /// IsPrivateExtern - True if this symbol is private extern. - unsigned IsPrivateExtern : 1; + union { + /// Offset - The offset to apply to the fragment address to form this + /// symbol's value. + uint64_t Offset; - /// CommonSize - The size of the symbol, if it is 'common', or 0. - // - // FIXME: Pack this in with other fields? We could put it in offset, since a - // common symbol can never get a definition. - uint64_t CommonSize; + /// CommonSize - The size of the symbol, if it is 'common'. + uint64_t CommonSize; + }; /// SymbolSize - An expression describing how to calculate the size of /// a symbol. If a symbol has no size this field will be NULL. const MCExpr *SymbolSize; - /// CommonAlign - The alignment of the symbol, if it is 'common'. + /// CommonAlign - The alignment of the symbol, if it is 'common', or -1. // // FIXME: Pack this in with other fields? unsigned CommonAlign; @@ -734,30 +730,41 @@ public: const MCSymbol &getSymbol() const { return *Symbol; } - MCFragment *getFragment() const { return Fragment; } - void setFragment(MCFragment *Value) { Fragment = Value; } + MCFragment *getFragment() const { return Fragment.getPointer(); } + void setFragment(MCFragment *Value) { Fragment.setPointer(Value); } - uint64_t getOffset() const { return Offset; } - void setOffset(uint64_t Value) { Offset = Value; } + uint64_t getOffset() const { + assert(!isCommon()); + return Offset; + } + void setOffset(uint64_t Value) { + assert(!isCommon()); + Offset = Value; + } /// @} /// @name Symbol Attributes /// @{ - bool isExternal() const { return IsExternal; } - void setExternal(bool Value) { IsExternal = Value; } + bool isExternal() const { return Fragment.getInt() & 1; } + void setExternal(bool Value) { + Fragment.setInt((Fragment.getInt() & ~1) | unsigned(Value)); + } - bool isPrivateExtern() const { return IsPrivateExtern; } - void setPrivateExtern(bool Value) { IsPrivateExtern = Value; } + bool isPrivateExtern() const { return Fragment.getInt() & 2; } + void setPrivateExtern(bool Value) { + Fragment.setInt((Fragment.getInt() & ~2) | (unsigned(Value) << 1)); + } /// isCommon - Is this a 'common' symbol. - bool isCommon() const { return CommonSize != 0; } + bool isCommon() const { return CommonAlign != -1U; } /// setCommon - Mark this symbol as being 'common'. /// /// \param Size - The size of the symbol. /// \param Align - The alignment of the symbol. void setCommon(uint64_t Size, unsigned Align) { + assert(getOffset() == 0); CommonSize = Size; CommonAlign = Align; } @@ -875,6 +882,8 @@ private: iplist Symbols; + DenseSet LocalsUsedInReloc; + /// The map of sections to their associated assembler backend data. // // FIXME: Avoid this indirection? @@ -910,7 +919,6 @@ private: unsigned BundleAlignSize; unsigned RelaxAll : 1; - unsigned NoExecStack : 1; unsigned SubsectionsViaSymbols : 1; /// ELF specific e_header flags @@ -975,6 +983,9 @@ private: MCFragment &F, const MCFixup &Fixup); public: + void addLocalUsedInReloc(const MCSymbol &Sym); + bool isLocalUsedInReloc(const MCSymbol &Sym) const; + /// Compute the effective fragment size assuming it is laid out at the given /// \p SectionAddress and \p FragmentOffset. uint64_t computeFragmentSize(const MCAsmLayout &Layout, @@ -1056,9 +1067,6 @@ public: bool getRelaxAll() const { return RelaxAll; } void setRelaxAll(bool Value) { RelaxAll = Value; } - bool getNoExecStack() const { return NoExecStack; } - void setNoExecStack(bool Value) { NoExecStack = Value; } - bool isBundlingEnabled() const { return BundleAlignSize != 0; } diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index eb0340f..e3163a7 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -73,6 +73,10 @@ namespace llvm { /// Symbols - Bindings of names to symbols. SymbolTable Symbols; + /// ELF sections can have a corresponding symbol. This maps one to the + /// other. + DenseMap SectionSymbols; + /// A maping from a local label number and an instance count to a symbol. /// For example, in the assembly /// 1: @@ -231,6 +235,10 @@ namespace llvm { MCSymbol *GetOrCreateSymbol(StringRef Name); MCSymbol *GetOrCreateSymbol(const Twine &Name); + MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); + + MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName); + /// LookupSymbol - Get the symbol for \p Name, or null. MCSymbol *LookupSymbol(StringRef Name) const; MCSymbol *LookupSymbol(const Twine &Name) const; @@ -284,6 +292,13 @@ namespace llvm { const MCSectionCOFF *getCOFFSection(StringRef Section); + /// Gets or creates a section equivalent to Sec that is associated with the + /// section containing KeySym. For example, to create a debug info section + /// associated with an inline function, pass the normal debug info section + /// as Sec and the function symbol as KeySym. + const MCSectionCOFF *getAssociativeCOFFSection(const MCSectionCOFF *Sec, + const MCSymbol *KeySym); + /// @} /// @name Dwarf Management diff --git a/include/llvm/MC/MCDisassembler.h b/include/llvm/MC/MCDisassembler.h index 9d441bb..d6b0a30 100644 --- a/include/llvm/MC/MCDisassembler.h +++ b/include/llvm/MC/MCDisassembler.h @@ -10,6 +10,7 @@ #define LLVM_MC_MCDISASSEMBLER_H #include "llvm-c/Disassembler.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/MC/MCRelocationInfo.h" #include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/DataTypes.h" @@ -18,12 +19,11 @@ namespace llvm { class MCInst; class MCSubtargetInfo; -class MemoryObject; class raw_ostream; class MCContext; -/// MCDisassembler - Superclass for all disassemblers. Consumes a memory region -/// and provides an array of assembly instructions. +/// Superclass for all disassemblers. Consumes a memory region and provides an +/// array of assembly instructions. class MCDisassembler { public: /// Ternary decode status. Most backends will just use Fail and @@ -54,34 +54,31 @@ public: Success = 3 }; - /// Constructor - Performs initial setup for the disassembler. MCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) : Ctx(Ctx), STI(STI), Symbolizer(), CommentStream(nullptr) {} virtual ~MCDisassembler(); - /// getInstruction - Returns the disassembly of a single instruction. + /// Returns the disassembly of a single instruction. /// - /// @param instr - An MCInst to populate with the contents of the + /// @param Instr - An MCInst to populate with the contents of the /// instruction. - /// @param size - A value to populate with the size of the instruction, or + /// @param Size - A value to populate with the size of the instruction, or /// the number of bytes consumed while attempting to decode /// an invalid instruction. - /// @param region - The memory object to use as a source for machine code. - /// @param address - The address, in the memory space of region, of the first + /// @param Address - The address, in the memory space of region, of the first /// byte of the instruction. - /// @param vStream - The stream to print warnings and diagnostic messages on. - /// @param cStream - The stream to print comments and annotations on. + /// @param VStream - The stream to print warnings and diagnostic messages on. + /// @param CStream - The stream to print comments and annotations on. /// @return - MCDisassembler::Success if the instruction is valid, /// MCDisassembler::SoftFail if the instruction was /// disassemblable but invalid, /// MCDisassembler::Fail if the instruction was invalid. - virtual DecodeStatus getInstruction(MCInst& instr, - uint64_t& size, - const MemoryObject ®ion, - uint64_t address, - raw_ostream &vStream, - raw_ostream &cStream) const = 0; + virtual DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const = 0; + private: MCContext &Ctx; diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 6cd9a9a..c266acf 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -16,16 +16,16 @@ #define LLVM_MC_MCDWARF_H #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/raw_ostream.h" #include -#include #include #include +#include namespace llvm { class MCAsmBackend; @@ -457,7 +457,7 @@ public: return Offset; } - const StringRef getValues() const { + StringRef getValues() const { assert(Operation == OpEscape); return StringRef(&Values[0], Values.size()); } @@ -466,13 +466,15 @@ public: struct MCDwarfFrameInfo { MCDwarfFrameInfo() : Begin(nullptr), End(nullptr), Personality(nullptr), Lsda(nullptr), - Instructions(), PersonalityEncoding(), LsdaEncoding(0), - CompactUnwindEncoding(0), IsSignalFrame(false), IsSimple(false) {} + Instructions(), CurrentCfaRegister(0), PersonalityEncoding(), + LsdaEncoding(0), CompactUnwindEncoding(0), IsSignalFrame(false), + IsSimple(false) {} MCSymbol *Begin; MCSymbol *End; const MCSymbol *Personality; const MCSymbol *Lsda; std::vector Instructions; + unsigned CurrentCfaRegister; unsigned PersonalityEncoding; unsigned LsdaEncoding; uint32_t CompactUnwindEncoding; diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 66729fe..ab6c5e3 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -41,10 +41,18 @@ public: virtual ~MCELFStreamer(); + /// state management + void reset() override { + LocalCommons.clear(); + BindingExplicitlySet.clear(); + SeenIdent = false; + MCObjectStreamer::reset(); + } + /// @name MCStreamer Interface /// @{ - void InitSections() override; + void InitSections(bool NoExecStack) override; void ChangeSection(const MCSection *Section, const MCExpr *Subsection) override; void EmitLabel(MCSymbol *Symbol) override; @@ -107,8 +115,7 @@ private: MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll, bool NoExecStack, - bool IsThumb); + bool RelaxAll, bool IsThumb); } // end namespace llvm diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index e96ecb4..bd9b2bc 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -19,6 +19,7 @@ class MCAsmInfo; class MCAsmLayout; class MCAssembler; class MCContext; +class MCFixup; class MCSection; class MCSectionData; class MCStreamer; @@ -49,11 +50,17 @@ private: bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const SectionAddrMap *Addrs) const; + + bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const; + protected: explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {} bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, + const MCFixup *Fixup, const SectionAddrMap *Addrs, bool InSet, bool ForceVarExpansion) const; @@ -87,13 +94,17 @@ public: bool EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const; bool EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const; + int64_t evaluateKnownAbsolute(const MCAsmLayout &Layout) const; + /// EvaluateAsRelocatable - Try to evaluate the expression to a relocatable /// value, i.e. an expression of the fixed form (a - b + constant). /// /// @param Res - The relocatable value, if evaluation succeeds. /// @param Layout - The assembler layout object to use for evaluating values. + /// @param Fixup - The Fixup object if available. /// @result - True on success. - bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout) const; + bool EvaluateAsRelocatable(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const; /// \brief Try to evaluate the expression to the form (a - b + constant) where /// neither a nor b are variables. @@ -101,7 +112,8 @@ public: /// This is a more aggressive variant of EvaluateAsRelocatable. The intended /// use is for when relocations are not available, like the symbol value in /// the symbol table. - bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const; + bool EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const; /// FindAssociatedSection - Find the "associated section" for this expression, /// which is currently defined as the absolute section for constants, or @@ -182,6 +194,7 @@ public: VK_ARM_TARGET1, VK_ARM_TARGET2, VK_ARM_PREL31, + VK_ARM_SBREL, // symbol(sbrel) VK_ARM_TLSLDO, // symbol(tlsldo) VK_ARM_TLSCALL, // symbol(tlscall) VK_ARM_TLSDESC, // symbol(tlsdesc) @@ -238,6 +251,7 @@ public: VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld + VK_PPC_LOCAL, // symbol@local VK_Mips_GPREL, VK_Mips_GOT_CALL, @@ -270,21 +284,20 @@ public: }; private: - /// The symbol being referenced. - const MCSymbol *Symbol; - /// The symbol reference modifier. - const VariantKind Kind; + const unsigned Kind : 16; - /// MCAsmInfo that is used to print symbol variants correctly. - const MCAsmInfo *MAI; + /// Specifies how the variant kind should be printed. + const unsigned UseParensForSymbolVariant : 1; - explicit MCSymbolRefExpr(const MCSymbol *_Symbol, VariantKind _Kind, - const MCAsmInfo *_MAI) - : MCExpr(MCExpr::SymbolRef), Symbol(_Symbol), Kind(_Kind), MAI(_MAI) { - assert(Symbol); - assert(MAI); - } + // FIXME: Remove this bit. + const unsigned HasSubsectionsViaSymbols : 1; + + /// The symbol being referenced. + const MCSymbol *Symbol; + + explicit MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, + const MCAsmInfo *MAI); public: /// @name Construction @@ -304,9 +317,12 @@ public: /// @{ const MCSymbol &getSymbol() const { return *Symbol; } - const MCAsmInfo &getMCAsmInfo() const { return *MAI; } - VariantKind getKind() const { return Kind; } + VariantKind getKind() const { return static_cast(Kind); } + + void printVariantKind(raw_ostream &OS) const; + + bool hasSubsectionsViaSymbols() const { return HasSubsectionsViaSymbols; } /// @} /// @name Static Utility Functions @@ -524,7 +540,8 @@ public: virtual void PrintImpl(raw_ostream &OS) const = 0; virtual bool EvaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout) const = 0; + const MCAsmLayout *Layout, + const MCFixup *Fixup) const = 0; virtual void visitUsedExpr(MCStreamer& Streamer) const = 0; virtual const MCSection *FindAssociatedSection() const = 0; diff --git a/include/llvm/MC/MCInst.h b/include/llvm/MC/MCInst.h index 6918280..25cd5cc 100644 --- a/include/llvm/MC/MCInst.h +++ b/include/llvm/MC/MCInst.h @@ -31,7 +31,7 @@ class MCInst; /// MCOperand - Instances of this class represent operands of the MCInst class. /// This is a simple discriminated union. class MCOperand { - enum MachineOperandType { + enum MachineOperandType : unsigned char { kInvalid, ///< Uninitialized. kRegister, ///< Register operand. kImmediate, ///< Immediate operand. @@ -39,7 +39,7 @@ class MCOperand { kExpr, ///< Relocatable immediate operand. kInst ///< Sub-instruction operand. }; - unsigned char Kind; + MachineOperandType Kind; union { unsigned RegVal; @@ -172,8 +172,11 @@ public: size_t size() { return Operands.size(); } typedef SmallVectorImpl::iterator iterator; + typedef SmallVectorImpl::const_iterator const_iterator; iterator begin() { return Operands.begin(); } - iterator end() { return Operands.end(); } + const_iterator begin() const { return Operands.begin(); } + iterator end() { return Operands.end(); } + const_iterator end() const { return Operands.end(); } iterator insert(iterator I, const MCOperand &Op) { return Operands.insert(I, Op); } diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index 7f55b29..95124c3 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -1,4 +1,4 @@ -//===-- MCInstPrinter.h - Convert an MCInst to target assembly syntax -----===// +//===- MCInstPrinter.h - MCInst to target assembly syntax -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 5896de7..3609893 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -44,11 +44,12 @@ namespace MCOI { /// Operand Type - Operands are tagged with one of the values of this enum. enum OperandType { - OPERAND_UNKNOWN, - OPERAND_IMMEDIATE, - OPERAND_REGISTER, - OPERAND_MEMORY, - OPERAND_PCREL + OPERAND_UNKNOWN = 0, + OPERAND_IMMEDIATE = 1, + OPERAND_REGISTER = 2, + OPERAND_MEMORY = 3, + OPERAND_PCREL = 4, + OPERAND_FIRST_TARGET = 5 }; } @@ -125,7 +126,10 @@ namespace MCID { Rematerializable, CheapAsAMove, ExtraSrcRegAllocReq, - ExtraDefRegAllocReq + ExtraDefRegAllocReq, + RegSequence, + ExtractSubreg, + InsertSubreg }; } @@ -357,6 +361,47 @@ public: return Flags & (1 << MCID::FoldableAsLoad); } + /// \brief Return true if this instruction behaves + /// the same way as the generic REG_SEQUENCE instructions. + /// E.g., on ARM, + /// dX VMOVDRR rY, rZ + /// is equivalent to + /// dX = REG_SEQUENCE rY, ssub_0, rZ, ssub_1. + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getRegSequenceLikeInputs has to be + /// override accordingly. + bool isRegSequenceLike() const { return Flags & (1 << MCID::RegSequence); } + + /// \brief Return true if this instruction behaves + /// the same way as the generic EXTRACT_SUBREG instructions. + /// E.g., on ARM, + /// rX, rY VMOVRRD dZ + /// is equivalent to two EXTRACT_SUBREG: + /// rX = EXTRACT_SUBREG dZ, ssub_0 + /// rY = EXTRACT_SUBREG dZ, ssub_1 + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getExtractSubregLikeInputs has to be + /// override accordingly. + bool isExtractSubregLike() const { + return Flags & (1 << MCID::ExtractSubreg); + } + + /// \brief Return true if this instruction behaves + /// the same way as the generic INSERT_SUBREG instructions. + /// E.g., on ARM, + /// dX = VSETLNi32 dY, rZ, Imm + /// is equivalent to a INSERT_SUBREG: + /// dX = INSERT_SUBREG dY, rZ, translateImmToSubIdx(Imm) + /// + /// Note that for the optimizers to be able to take advantage of + /// this property, TargetInstrInfo::getInsertSubregLikeInputs has to be + /// override accordingly. + bool isInsertSubregLike() const { + return Flags & (1 << MCID::InsertSubreg); + } + //===--------------------------------------------------------------------===// // Side Effect Analysis //===--------------------------------------------------------------------===// @@ -451,9 +496,12 @@ public: } /// isRematerializable - Returns true if this instruction is a candidate for - /// remat. This flag is deprecated, please don't use it anymore. If this - /// flag is set, the isReallyTriviallyReMaterializable() method is called to - /// verify the instruction is really rematable. + /// remat. This flag is only used in TargetInstrInfo method + /// isTriviallyRematerializable. + /// + /// If this flag is set, the isReallyTriviallyReMaterializable() + /// or isReallyTriviallyReMaterializableGeneric methods are called to verify + /// the instruction is really rematable. bool isRematerializable() const { return Flags & (1 << MCID::Rematerializable); } @@ -464,6 +512,9 @@ public: /// where we would like to remat or hoist the instruction, but not if it costs /// more than moving the instruction into the appropriate register. Note, we /// are not marking copies from and to the same register class with this flag. + /// + /// This method could be called by interface TargetInstrInfo::isAsCheapAsAMove + /// for different subtargets. bool isAsCheapAsAMove() const { return Flags & (1 << MCID::CheapAsAMove); } diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 5104345..94d599f 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -22,7 +22,7 @@ namespace llvm { //===----------------------------------------------------------------------===// -/// Instruction stage - These values represent a non-pipelined step in +/// These values represent a non-pipelined step in /// the execution of an instruction. Cycles represents the number of /// discrete time slots needed to complete the stage. Units represent /// the choice of functional units that can be used to complete the @@ -67,12 +67,12 @@ struct InstrStage { int NextCycles_; ///< Number of machine cycles to next stage ReservationKinds Kind_; ///< Kind of the FU reservation - /// getCycles - returns the number of cycles the stage is occupied + /// Returns the number of cycles the stage is occupied. unsigned getCycles() const { return Cycles_; } - /// getUnits - returns the choice of FUs + /// Returns the choice of FUs. unsigned getUnits() const { return Units_; } @@ -81,7 +81,7 @@ struct InstrStage { return Kind_; } - /// getNextCycles - returns the number of cycles from the start of + /// Returns the number of cycles from the start of /// this stage to the start of the next stage in the itinerary unsigned getNextCycles() const { return (NextCycles_ >= 0) ? (unsigned)NextCycles_ : Cycles_; @@ -90,10 +90,9 @@ struct InstrStage { //===----------------------------------------------------------------------===// -/// Instruction itinerary - An itinerary represents the scheduling -/// information for an instruction. This includes a set of stages -/// occupies by the instruction, and the pipeline cycle in which -/// operands are read and written. +/// An itinerary represents the scheduling information for an instruction. +/// This includes a set of stages occupied by the instruction and the pipeline +/// cycle in which operands are read and written. /// struct InstrItinerary { int NumMicroOps; ///< # of micro-ops, -1 means it's variable @@ -105,12 +104,11 @@ struct InstrItinerary { //===----------------------------------------------------------------------===// -/// Instruction itinerary Data - Itinerary data supplied by a subtarget to be -/// used by a target. +/// Itinerary data supplied by a subtarget to be used by a target. /// class InstrItineraryData { public: - const MCSchedModel *SchedModel; ///< Basic machine properties. + MCSchedModel SchedModel; ///< Basic machine properties. const InstrStage *Stages; ///< Array of stages selected const unsigned *OperandCycles; ///< Array of operand cycles selected const unsigned *Forwardings; ///< Array of pipeline forwarding pathes @@ -118,45 +116,38 @@ public: /// Ctors. /// - InstrItineraryData() : SchedModel(&MCSchedModel::DefaultSchedModel), + InstrItineraryData() : SchedModel(MCSchedModel::GetDefaultSchedModel()), Stages(nullptr), OperandCycles(nullptr), Forwardings(nullptr), Itineraries(nullptr) {} - InstrItineraryData(const MCSchedModel *SM, const InstrStage *S, + InstrItineraryData(const MCSchedModel &SM, const InstrStage *S, const unsigned *OS, const unsigned *F) : SchedModel(SM), Stages(S), OperandCycles(OS), Forwardings(F), - Itineraries(SchedModel->InstrItineraries) {} + Itineraries(SchedModel.InstrItineraries) {} - /// isEmpty - Returns true if there are no itineraries. - /// + /// Returns true if there are no itineraries. bool isEmpty() const { return Itineraries == nullptr; } - /// isEndMarker - Returns true if the index is for the end marker - /// itinerary. - /// + /// Returns true if the index is for the end marker itinerary. bool isEndMarker(unsigned ItinClassIndx) const { return ((Itineraries[ItinClassIndx].FirstStage == ~0U) && (Itineraries[ItinClassIndx].LastStage == ~0U)); } - /// beginStage - Return the first stage of the itinerary. - /// + /// Return the first stage of the itinerary. const InstrStage *beginStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].FirstStage; return Stages + StageIdx; } - /// endStage - Return the last+1 stage of the itinerary. - /// + /// Return the last+1 stage of the itinerary. const InstrStage *endStage(unsigned ItinClassIndx) const { unsigned StageIdx = Itineraries[ItinClassIndx].LastStage; return Stages + StageIdx; } - /// getStageLatency - Return the total stage latency of the given - /// class. The latency is the maximum completion time for any stage - /// in the itinerary. - /// + /// Return the total stage latency of the given class. + /// The latency is the maximum completion time for any stage in the itinerary. /// If no stages exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple @@ -174,9 +165,8 @@ public: return Latency; } - /// getOperandCycle - Return the cycle for the given class and - /// operand. Return -1 if no cycle is specified for the operand. - /// + /// Return the cycle for the given class and operand. + /// Return -1 if no cycle is specified for the operand. int getOperandCycle(unsigned ItinClassIndx, unsigned OperandIdx) const { if (isEmpty()) return -1; @@ -189,7 +179,7 @@ public: return (int)OperandCycles[FirstIdx + OperandIdx]; } - /// hasPipelineForwarding - Return true if there is a pipeline forwarding + /// Return true if there is a pipeline forwarding /// between instructions of itinerary classes DefClass and UseClasses so that /// value produced by an instruction of itinerary class DefClass, operand /// index DefIdx can be bypassed when it's read by an instruction of @@ -212,7 +202,7 @@ public: Forwardings[FirstUseIdx + UseIdx]; } - /// getOperandLatency - Compute and return the use operand latency of a given + /// Compute and return the use operand latency of a given /// itinerary class and operand index if the value is produced by an /// instruction of the specified itinerary class and def operand index. int getOperandLatency(unsigned DefClass, unsigned DefIdx, @@ -236,9 +226,8 @@ public: return UseCycle; } - /// getNumMicroOps - Return the number of micro-ops that the given class - /// decodes to. Return -1 for classes that require dynamic lookup via - /// TargetInstrInfo. + /// Return the number of micro-ops that the given class decodes to. + /// Return -1 for classes that require dynamic lookup via TargetInstrInfo. int getNumMicroOps(unsigned ItinClassIndx) const { if (isEmpty()) return 1; diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 50fd527..890d638 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -18,8 +18,8 @@ #define LLVM_MC_MCLINKEROPTIMIZATIONHINT_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCMachObjectWriter.h" #include "llvm/Support/raw_ostream.h" @@ -45,7 +45,7 @@ static inline StringRef MCLOHDirectiveName() { return StringRef(".loh"); } -static inline bool isValidMCLOHType(MCLOHType Kind) { +static inline bool isValidMCLOHType(unsigned Kind) { return Kind >= MCLOH_AdrpAdrp && Kind <= MCLOH_AdrpLdrGot; } diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 12a7f0e..e4681c0 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -14,6 +14,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/MachO.h" #include @@ -67,12 +68,10 @@ public: /// @name API /// @{ - virtual void RecordRelocation(MachObjectWriter *Writer, - const MCAssembler &Asm, + virtual void RecordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; /// @} @@ -96,15 +95,21 @@ class MachObjectWriter : public MCObjectWriter { /// @name Relocation Data /// @{ - llvm::DenseMap > Relocations; + struct RelAndSymbol { + const MCSymbolData *Sym; + MachO::any_relocation_info MRE; + RelAndSymbol(const MCSymbolData *Sym, const MachO::any_relocation_info &MRE) + : Sym(Sym), MRE(MRE) {} + }; + + llvm::DenseMap> Relocations; llvm::DenseMap IndirectSymBase; /// @} /// @name Symbol Table Data /// @{ - SmallString<256> StringTable; + StringTableBuilder StringTable; std::vector LocalSymbolData; std::vector ExternalSymbolData; std::vector UndefinedSymbolData; @@ -212,9 +217,15 @@ public: // - Input errors, where something cannot be correctly encoded. 'as' allows // these through in many cases. - void addRelocation(const MCSectionData *SD, + // Add a relocation to be output in the object file. At the time this is + // called, the symbol indexes are not know, so if the relocation refers + // to a symbol it should be passed as \p RelSymbol so that it can be updated + // afterwards. If the relocation doesn't refer to a symbol, nullptr should be + // used. + void addRelocation(const MCSymbolData *RelSymbol, const MCSectionData *SD, MachO::any_relocation_info &MRE) { - Relocations[SD].push_back(MRE); + RelAndSymbol P(RelSymbol, MRE); + Relocations[SD].push_back(P); } void RecordScatteredRelocation(const MCAssembler &Asm, @@ -230,7 +241,7 @@ public: const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; @@ -239,8 +250,7 @@ public: /// ComputeSymbolTable - Compute the symbol table data /// - /// \param StringTable [out] - The string table data. - void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, + void ComputeSymbolTable(MCAssembler &Asm, std::vector &LocalSymbolData, std::vector &ExternalSymbolData, std::vector &UndefinedSymbolData); diff --git a/include/llvm/MC/MCObjectDisassembler.h b/include/llvm/MC/MCObjectDisassembler.h deleted file mode 100644 index 5b935db..0000000 --- a/include/llvm/MC/MCObjectDisassembler.h +++ /dev/null @@ -1,174 +0,0 @@ -//===-- llvm/MC/MCObjectDisassembler.h --------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains the declaration of the MCObjectDisassembler class, which -// can be used to construct an MCModule and an MC CFG from an ObjectFile. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCOBJECTDISASSEMBLER_H -#define LLVM_MC_MCOBJECTDISASSEMBLER_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/DataTypes.h" -#include "llvm/Support/MemoryObject.h" -#include - -namespace llvm { - -namespace object { - class ObjectFile; - class MachOObjectFile; -} - -class MCBasicBlock; -class MCDisassembler; -class MCFunction; -class MCInstrAnalysis; -class MCModule; -class MCObjectSymbolizer; - -/// \brief Disassemble an ObjectFile to an MCModule and MCFunctions. -/// This class builds on MCDisassembler to disassemble whole sections, creating -/// MCAtom (MCTextAtom for disassembled sections and MCDataAtom for raw data). -/// It can also be used to create a control flow graph consisting of MCFunctions -/// and MCBasicBlocks. -class MCObjectDisassembler { -public: - MCObjectDisassembler(const object::ObjectFile &Obj, - const MCDisassembler &Dis, - const MCInstrAnalysis &MIA); - virtual ~MCObjectDisassembler() {} - - /// \brief Build an MCModule, creating atoms and optionally functions. - /// \param withCFG Also build a CFG by adding MCFunctions to the Module. - /// If withCFG is false, the MCModule built only contains atoms, representing - /// what was found in the object file. If withCFG is true, MCFunctions are - /// created, containing MCBasicBlocks. All text atoms are split to form basic - /// block atoms, which then each back an MCBasicBlock. - MCModule *buildModule(bool withCFG = false); - - MCModule *buildEmptyModule(); - - typedef std::vector AddressSetTy; - /// \name Create a new MCFunction. - MCFunction *createFunction(MCModule *Module, uint64_t BeginAddr, - AddressSetTy &CallTargets, - AddressSetTy &TailCallTargets); - - /// \brief Set the region on which to fallback if disassembly was requested - /// somewhere not accessible in the object file. - /// This is used for dynamic disassembly (see RawMemoryObject). - void setFallbackRegion(std::unique_ptr &Region) { - FallbackRegion.reset(Region.release()); - } - - /// \brief Set the symbolizer to use to get information on external functions. - /// Note that this isn't used to do instruction-level symbolization (that is, - /// plugged into MCDisassembler), but to symbolize function call targets. - void setSymbolizer(MCObjectSymbolizer *ObjectSymbolizer) { - MOS = ObjectSymbolizer; - } - - /// \brief Get the effective address of the entrypoint, or 0 if there is none. - virtual uint64_t getEntrypoint(); - - /// \name Get the addresses of static constructors/destructors in the object. - /// The caller is expected to know how to interpret the addresses; - /// for example, Mach-O init functions expect 5 arguments, not for ELF. - /// The addresses are original object file load addresses, not effective. - /// @{ - virtual ArrayRef getStaticInitFunctions(); - virtual ArrayRef getStaticExitFunctions(); - /// @} - - /// \name Translation between effective and objectfile load address. - /// @{ - /// \brief Compute the effective load address, from an objectfile virtual - /// address. This is implemented in a format-specific way, to take into - /// account things like PIE/ASLR when doing dynamic disassembly. - /// For example, on Mach-O this would be done by adding the VM addr slide, - /// on glibc ELF by keeping a map between segment load addresses, filled - /// using dl_iterate_phdr, etc.. - /// In most static situations and in the default impl., this returns \p Addr. - virtual uint64_t getEffectiveLoadAddr(uint64_t Addr); - - /// \brief Compute the original load address, as specified in the objectfile. - /// This is the inverse of getEffectiveLoadAddr. - virtual uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr); - /// @} - -protected: - const object::ObjectFile &Obj; - const MCDisassembler &Dis; - const MCInstrAnalysis &MIA; - MCObjectSymbolizer *MOS; - - /// \brief The fallback memory region, outside the object file. - std::unique_ptr FallbackRegion; - - /// \brief Return a memory region suitable for reading starting at \p Addr. - /// In most cases, this returns a StringRefMemoryObject backed by the - /// containing section. When no section was found, this returns the - /// FallbackRegion, if it is suitable. - /// If it is not, or if there is no fallback region, this returns 0. - MemoryObject *getRegionFor(uint64_t Addr); - -private: - /// \brief Fill \p Module by creating an atom for each section. - /// This could be made much smarter, using information like symbols, but also - /// format-specific features, like mach-o function_start or data_in_code LCs. - void buildSectionAtoms(MCModule *Module); - - /// \brief Enrich \p Module with a CFG consisting of MCFunctions. - /// \param Module An MCModule returned by buildModule, with no CFG. - /// NOTE: Each MCBasicBlock in a MCFunction is backed by a single MCTextAtom. - /// When the CFG is built, contiguous instructions that were previously in a - /// single MCTextAtom will be split in multiple basic block atoms. - void buildCFG(MCModule *Module); - - MCBasicBlock *getBBAt(MCModule *Module, MCFunction *MCFN, uint64_t BeginAddr, - AddressSetTy &CallTargets, - AddressSetTy &TailCallTargets); -}; - -class MCMachOObjectDisassembler : public MCObjectDisassembler { - const object::MachOObjectFile &MOOF; - - uint64_t VMAddrSlide; - uint64_t HeaderLoadAddress; - - // __DATA;__mod_init_func support. - llvm::StringRef ModInitContents; - // __DATA;__mod_exit_func support. - llvm::StringRef ModExitContents; - -public: - /// \brief Construct a Mach-O specific object disassembler. - /// \param VMAddrSlide The virtual address slide applied by dyld. - /// \param HeaderLoadAddress The load address of the mach_header for this - /// object. - MCMachOObjectDisassembler(const object::MachOObjectFile &MOOF, - const MCDisassembler &Dis, - const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, - uint64_t HeaderLoadAddress); - -protected: - uint64_t getEffectiveLoadAddr(uint64_t Addr) override; - uint64_t getOriginalLoadAddr(uint64_t EffectiveAddr) override; - uint64_t getEntrypoint() override; - - ArrayRef getStaticInitFunctions() override; - ArrayRef getStaticExitFunctions() override; -}; - -} - -#endif diff --git a/include/llvm/MC/MCObjectFileInfo.h b/include/llvm/MC/MCObjectFileInfo.h index 4d1715e..321043c 100644 --- a/include/llvm/MC/MCObjectFileInfo.h +++ b/include/llvm/MC/MCObjectFileInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCBJECTFILEINFO_H -#define LLVM_MC_MCBJECTFILEINFO_H +#ifndef LLVM_MC_MCOBJECTFILEINFO_H +#define LLVM_MC_MCOBJECTFILEINFO_H #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" @@ -116,6 +116,7 @@ protected: /// These are used for the Fission separate debug information files. const MCSection *DwarfInfoDWOSection; + const MCSection *DwarfTypesDWOSection; const MCSection *DwarfAbbrevDWOSection; const MCSection *DwarfStrDWOSection; const MCSection *DwarfLineDWOSection; @@ -261,7 +262,9 @@ public: return DwarfInfoDWOSection; } const MCSection *getDwarfTypesSection(uint64_t Hash) const; - const MCSection *getDwarfTypesDWOSection(uint64_t Hash) const; + const MCSection *getDwarfTypesDWOSection() const { + return DwarfTypesDWOSection; + } const MCSection *getDwarfAbbrevDWOSection() const { return DwarfAbbrevDWOSection; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 8d37c85..0866ff5 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -10,6 +10,7 @@ #ifndef LLVM_MC_MCOBJECTSTREAMER_H #define LLVM_MC_MCOBJECTSTREAMER_H +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCStreamer.h" @@ -37,11 +38,16 @@ class MCObjectStreamer : public MCStreamer { MCSectionData::iterator CurInsertionPoint; bool EmitEHFrame; bool EmitDebugFrame; + SmallVector PendingLabels; virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0; void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; + // If any labels have been emitted but not assigned fragments, ensure that + // they get assigned, either to F if possible or to a new data fragment. + void flushPendingLabels(MCFragment *F); + protected: MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &_OS, MCCodeEmitter *_Emitter); @@ -69,14 +75,15 @@ protected: MCFragment *getCurrentFragment() const; - void insert(MCFragment *F) const { + void insert(MCFragment *F) { + flushPendingLabels(F); CurSectionData->getFragmentList().insert(CurInsertionPoint, F); F->setParent(CurSectionData); } /// Get a data fragment to write into, creating a new one if the current /// fragment is not a data fragment. - MCDataFragment *getOrCreateDataFragment() const; + MCDataFragment *getOrCreateDataFragment(); public: void visitUsedSymbol(const MCSymbol &Sym) override; @@ -126,7 +133,7 @@ public: void EmitZeros(uint64_t NumBytes) override; void FinishImpl() override; - virtual bool mayHaveInstructions() const { + bool mayHaveInstructions() const override { return getCurrentSectionData()->hasInstructions(); } }; diff --git a/include/llvm/MC/MCObjectSymbolizer.h b/include/llvm/MC/MCObjectSymbolizer.h deleted file mode 100644 index f75b7f5..0000000 --- a/include/llvm/MC/MCObjectSymbolizer.h +++ /dev/null @@ -1,83 +0,0 @@ -//===-- llvm/MC/MCObjectSymbolizer.h --------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the MCObjectSymbolizer class, an MCSymbolizer that is -// backed by an object::ObjectFile. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_MC_MCOBJECTSYMBOLIZER_H -#define LLVM_MC_MCOBJECTSYMBOLIZER_H - -#include "llvm/ADT/DenseMap.h" -#include "llvm/MC/MCSymbolizer.h" -#include "llvm/Object/ObjectFile.h" -#include - -namespace llvm { - -class MCExpr; -class MCInst; -class MCRelocationInfo; -class raw_ostream; - -/// \brief An ObjectFile-backed symbolizer. -class MCObjectSymbolizer : public MCSymbolizer { -protected: - const object::ObjectFile *Obj; - - // Map a load address to the first relocation that applies there. As far as I - // know, if there are several relocations at the exact same address, they are - // related and the others can be determined from the first that was found in - // the relocation table. For instance, on x86-64 mach-o, a SUBTRACTOR - // relocation (referencing the minuend symbol) is followed by an UNSIGNED - // relocation (referencing the subtrahend symbol). - const object::RelocationRef *findRelocationAt(uint64_t Addr); - const object::SectionRef *findSectionContaining(uint64_t Addr); - - MCObjectSymbolizer(MCContext &Ctx, std::unique_ptr RelInfo, - const object::ObjectFile *Obj); - -public: - /// \name Overridden MCSymbolizer methods: - /// @{ - bool tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, - int64_t Value, uint64_t Address, - bool IsBranch, uint64_t Offset, - uint64_t InstSize) override; - - void tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, - uint64_t Address) override; - /// @} - - /// \brief Look for an external function symbol at \p Addr. - /// (References through the ELF PLT, Mach-O stubs, and similar). - /// \returns An MCExpr representing the external symbol, or 0 if not found. - virtual StringRef findExternalFunctionAt(uint64_t Addr); - - /// \brief Create an object symbolizer for \p Obj. - static MCObjectSymbolizer * - createObjectSymbolizer(MCContext &Ctx, - std::unique_ptr RelInfo, - const object::ObjectFile *Obj); - -private: - typedef DenseMap AddrToRelocMap; - typedef std::vector SortedSectionList; - SortedSectionList SortedSections; - AddrToRelocMap AddrToReloc; - - void buildSectionList(); - void buildRelocationByAddrMap(); -}; - -} - -#endif diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 55c828c..173ef41 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -76,12 +76,10 @@ public: /// post layout binding. The implementation is responsible for storing /// information about the relocation so that it can be emitted during /// WriteObject(). - virtual void RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, + virtual void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) = 0; + bool &IsPCRel, uint64_t &FixedValue) = 0; /// \brief Check whether the difference (A - B) between two symbol /// references is fully resolved. diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 0b550ba..a9a30f1 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -49,7 +49,7 @@ public: const AsmToken peekTok(bool ShouldSkipSpace = true) override; - bool isAtStartOfComment(char Char); + bool isAtStartOfComment(const char *Ptr); bool isAtStatementSeparator(const char *Ptr); const MCAsmInfo &getMAI() const { return MAI; } diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index e3d4181..b05891c 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -18,7 +18,7 @@ namespace llvm { -/// AsmToken - Target independent representation for an assembler token. +/// Target independent representation for an assembler token. class AsmToken { public: enum TokenKind { @@ -74,25 +74,26 @@ public: SMLoc getLoc() const; SMLoc getEndLoc() const; + SMRange getLocRange() const; - /// getStringContents - Get the contents of a string token (without quotes). + /// Get the contents of a string token (without quotes). StringRef getStringContents() const { assert(Kind == String && "This token isn't a string!"); return Str.slice(1, Str.size() - 1); } - /// getIdentifier - Get the identifier string for the current token, which - /// should be an identifier or a string. This gets the portion of the string - /// which should be used as the identifier, e.g., it does not include the - /// quotes on strings. + /// Get the identifier string for the current token, which should be an + /// identifier or a string. This gets the portion of the string which should + /// be used as the identifier, e.g., it does not include the quotes on + /// strings. StringRef getIdentifier() const { if (Kind == Identifier) return getString(); return getStringContents(); } - /// getString - Get the string for the current token, this includes all - /// characters (for example, the quotes on strings) in the token. + /// Get the string for the current token, this includes all characters (for + /// example, the quotes on strings) in the token. /// /// The returned StringRef points into the source manager's memory buffer, and /// is safe to store across calls to Lex(). @@ -113,8 +114,8 @@ public: } }; -/// MCAsmLexer - Generic assembler lexer interface, for use by target specific -/// assembly lexers. +/// Generic assembler lexer interface, for use by target specific assembly +/// lexers. class MCAsmLexer { /// The current token, stored in the base class for faster access. AsmToken CurTok; @@ -142,7 +143,7 @@ protected: // Can only create subclasses. public: virtual ~MCAsmLexer(); - /// Lex - Consume the next token from the input stream and return it. + /// Consume the next token from the input stream and return it. /// /// The lexer will continuosly return the end-of-file token once the end of /// the main input file has been reached. @@ -152,37 +153,37 @@ public: virtual StringRef LexUntilEndOfStatement() = 0; - /// getLoc - Get the current source location. + /// Get the current source location. SMLoc getLoc() const; - /// getTok - Get the current (last) lexed token. - const AsmToken &getTok() { + /// Get the current (last) lexed token. + const AsmToken &getTok() const { return CurTok; } - /// peekTok - Look ahead at the next token to be lexed. + /// Look ahead at the next token to be lexed. virtual const AsmToken peekTok(bool ShouldSkipSpace = true) = 0; - /// getErrLoc - Get the current error location + /// Get the current error location const SMLoc &getErrLoc() { return ErrLoc; } - /// getErr - Get the current error string + /// Get the current error string const std::string &getErr() { return Err; } - /// getKind - Get the kind of current token. + /// Get the kind of current token. AsmToken::TokenKind getKind() const { return CurTok.getKind(); } - /// is - Check if the current token has kind \p K. + /// Check if the current token has kind \p K. bool is(AsmToken::TokenKind K) const { return CurTok.is(K); } - /// isNot - Check if the current token has kind \p K. + /// Check if the current token has kind \p K. bool isNot(AsmToken::TokenKind K) const { return CurTok.isNot(K); } - /// setSkipSpace - Set whether spaces should be ignored by the lexer + /// Set whether spaces should be ignored by the lexer void setSkipSpace(bool val) { SkipSpace = val; } bool getAllowAtInIdentifier() { return AllowAtInIdentifier; } diff --git a/include/llvm/MC/MCParser/MCAsmParser.h b/include/llvm/MC/MCParser/MCAsmParser.h index 9836795..34188e66 100644 --- a/include/llvm/MC/MCParser/MCAsmParser.h +++ b/include/llvm/MC/MCParser/MCAsmParser.h @@ -45,20 +45,22 @@ public: } }; -/// MCAsmParserSemaCallback - Generic Sema callback for assembly parser. +/// Generic Sema callback for assembly parser. class MCAsmParserSemaCallback { public: virtual ~MCAsmParserSemaCallback(); virtual void *LookupInlineAsmIdentifier(StringRef &LineBuf, InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext) = 0; + virtual StringRef LookupInlineAsmLabel(StringRef Identifier, SourceMgr &SM, + SMLoc Location, bool Create) = 0; virtual bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset) = 0; }; -/// MCAsmParser - Generic assembler parser interface, for use by target specific -/// assembly parsers. +/// Generic assembler parser interface, for use by target specific assembly +/// parsers. class MCAsmParser { public: typedef bool (*DirectiveHandler)(MCAsmParserExtension*, StringRef, SMLoc); @@ -85,10 +87,13 @@ public: virtual SourceMgr &getSourceManager() = 0; virtual MCAsmLexer &getLexer() = 0; + const MCAsmLexer &getLexer() const { + return const_cast(this)->getLexer(); + } virtual MCContext &getContext() = 0; - /// getStreamer - Return the output streamer for the assembler. + /// Return the output streamer for the assembler. virtual MCStreamer &getStreamer() = 0; MCTargetAsmParser &getTargetParser() const { return *TargetParser; } @@ -100,51 +105,49 @@ public: bool getShowParsedOperands() const { return ShowParsedOperands; } void setShowParsedOperands(bool Value) { ShowParsedOperands = Value; } - /// Run - Run the parser on the input source buffer. + /// Run the parser on the input source buffer. virtual bool Run(bool NoInitialTextSection, bool NoFinalize = false) = 0; virtual void setParsingInlineAsm(bool V) = 0; virtual bool isParsingInlineAsm() = 0; - /// parseMSInlineAsm - Parse ms-style inline assembly. - virtual bool parseMSInlineAsm(void *AsmLoc, std::string &AsmString, - unsigned &NumOutputs, unsigned &NumInputs, - SmallVectorImpl > &OpDecls, - SmallVectorImpl &Constraints, - SmallVectorImpl &Clobbers, - const MCInstrInfo *MII, - const MCInstPrinter *IP, - MCAsmParserSemaCallback &SI) = 0; - - /// Note - Emit a note at the location \p L, with the message \p Msg. + /// Parse ms-style inline assembly. + virtual bool parseMSInlineAsm( + void *AsmLoc, std::string &AsmString, unsigned &NumOutputs, + unsigned &NumInputs, SmallVectorImpl> &OpDecls, + SmallVectorImpl &Constraints, + SmallVectorImpl &Clobbers, const MCInstrInfo *MII, + const MCInstPrinter *IP, MCAsmParserSemaCallback &SI) = 0; + + /// Emit a note at the location \p L, with the message \p Msg. virtual void Note(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) = 0; - /// Warning - Emit a warning at the location \p L, with the message \p Msg. + /// Emit a warning at the location \p L, with the message \p Msg. /// /// \return The return value is true, if warnings are fatal. virtual bool Warning(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) = 0; - /// Error - Emit an error at the location \p L, with the message \p Msg. + /// Emit an error at the location \p L, with the message \p Msg. /// /// \return The return value is always true, as an idiomatic convenience to /// clients. virtual bool Error(SMLoc L, const Twine &Msg, ArrayRef Ranges = None) = 0; - /// Lex - Get the next AsmToken in the stream, possibly handling file - /// inclusion first. + /// Get the next AsmToken in the stream, possibly handling file inclusion + /// first. virtual const AsmToken &Lex() = 0; - /// getTok - Get the current AsmToken from the stream. - const AsmToken &getTok(); + /// Get the current AsmToken from the stream. + const AsmToken &getTok() const; /// \brief Report an error at the current lexer location. bool TokError(const Twine &Msg, ArrayRef Ranges = None); - /// parseIdentifier - Parse an identifier or string (as a quoted identifier) - /// and set \p Res to the identifier contents. + /// Parse an identifier or string (as a quoted identifier) and set \p Res to + /// the identifier contents. virtual bool parseIdentifier(StringRef &Res) = 0; /// \brief Parse up to the end of statement and return the contents from the @@ -152,15 +155,14 @@ public: /// will be either the EndOfStatement or EOF. virtual StringRef parseStringToEndOfStatement() = 0; - /// parseEscapedString - Parse the current token as a string which may include - /// escaped characters and return the string contents. + /// Parse the current token as a string which may include escaped characters + /// and return the string contents. virtual bool parseEscapedString(std::string &Data) = 0; - /// eatToEndOfStatement - Skip to the end of the current statement, for error - /// recovery. + /// Skip to the end of the current statement, for error recovery. virtual void eatToEndOfStatement() = 0; - /// parseExpression - Parse an arbitrary expression. + /// Parse an arbitrary expression. /// /// @param Res - The value of the expression. The result is undefined /// on error. @@ -168,31 +170,30 @@ public: virtual bool parseExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; bool parseExpression(const MCExpr *&Res); - /// parsePrimaryExpr - Parse a primary expression. + /// Parse a primary expression. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. virtual bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// parseParenExpression - Parse an arbitrary expression, assuming that an - /// initial '(' has already been consumed. + /// Parse an arbitrary expression, assuming that an initial '(' has already + /// been consumed. /// /// @param Res - The value of the expression. The result is undefined /// on error. /// @result - False on success. virtual bool parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) = 0; - /// parseAbsoluteExpression - Parse an expression which must evaluate to an - /// absolute value. + /// Parse an expression which must evaluate to an absolute value. /// /// @param Res - The value of the absolute expression. The result is undefined /// on error. /// @result - False on success. virtual bool parseAbsoluteExpression(int64_t &Res) = 0; - /// checkForValidSection - Ensure that we have a valid section set in the - /// streamer. Otherwise, report an error and switch to .text. + /// Ensure that we have a valid section set in the streamer. Otherwise, report + /// an error and switch to .text. virtual void checkForValidSection() = 0; }; diff --git a/include/llvm/MC/MCParser/MCAsmParserExtension.h b/include/llvm/MC/MCParser/MCAsmParserExtension.h index 2eda3a9..bfc0afa 100644 --- a/include/llvm/MC/MCParser/MCAsmParserExtension.h +++ b/include/llvm/MC/MCParser/MCAsmParserExtension.h @@ -52,8 +52,17 @@ public: /// @{ MCContext &getContext() { return getParser().getContext(); } + MCAsmLexer &getLexer() { return getParser().getLexer(); } + const MCAsmLexer &getLexer() const { + return const_cast(this)->getLexer(); + } + MCAsmParser &getParser() { return *Parser; } + const MCAsmParser &getParser() const { + return const_cast(this)->getParser(); + } + SourceMgr &getSourceManager() { return getParser().getSourceManager(); } MCStreamer &getStreamer() { return getParser().getStreamer(); } bool Warning(SMLoc L, const Twine &Msg) { diff --git a/include/llvm/MC/MCRegisterInfo.h b/include/llvm/MC/MCRegisterInfo.h index 766f631..8e25ee1 100644 --- a/include/llvm/MC/MCRegisterInfo.h +++ b/include/llvm/MC/MCRegisterInfo.h @@ -32,9 +32,9 @@ public: typedef const MCPhysReg* iterator; typedef const MCPhysReg* const_iterator; - const char *Name; const iterator RegsBegin; const uint8_t *const RegSet; + const uint32_t NameIdx; const uint16_t RegsSize; const uint16_t RegSetSize; const uint16_t ID; @@ -46,10 +46,6 @@ public: /// unsigned getID() const { return ID; } - /// getName() - Return the register class name for debugging. - /// - const char *getName() const { return Name; } - /// begin/end - Return all of the registers in this class. /// iterator begin() const { return RegsBegin; } @@ -118,6 +114,10 @@ struct MCRegisterDesc { // RegUnits - Points to the list of register units. The low 4 bits holds the // Scale, the high bits hold an offset into DiffLists. See MCRegUnitIterator. uint32_t RegUnits; + + /// Index into list with lane mask sequences. The sequence contains a lanemask + /// for every register unit. + uint16_t RegUnitLaneMasks; }; /// MCRegisterInfo base class - We assume that the target defines a static @@ -161,7 +161,10 @@ private: unsigned NumRegUnits; // Number of regunits. const MCPhysReg (*RegUnitRoots)[2]; // Pointer to regunit root table. const MCPhysReg *DiffLists; // Pointer to the difflists array + const unsigned *RegUnitMaskSequences; // Pointer to lane mask sequences + // for register units. const char *RegStrings; // Pointer to the string table. + const char *RegClassStrings; // Pointer to the class strings. const uint16_t *SubRegIndices; // Pointer to the subreg lookup // array. const SubRegCoveredBits *SubRegIdxRanges; // Pointer to the subreg covered @@ -230,8 +233,10 @@ public: // These iterators are allowed to sub-class DiffListIterator and access // internal list pointers. friend class MCSubRegIterator; + friend class MCSubRegIndexIterator; friend class MCSuperRegIterator; friend class MCRegUnitIterator; + friend class MCRegUnitMaskIterator; friend class MCRegUnitRootIterator; /// \brief Initialize MCRegisterInfo, called by TableGen @@ -242,7 +247,9 @@ public: const MCPhysReg (*RURoots)[2], unsigned NRU, const MCPhysReg *DL, + const unsigned *RUMS, const char *Strings, + const char *ClassStrings, const uint16_t *SubIndices, unsigned NumIndices, const SubRegCoveredBits *SubIdxRanges, @@ -253,7 +260,9 @@ public: PCReg = PC; Classes = C; DiffLists = DL; + RegUnitMaskSequences = RUMS; RegStrings = Strings; + RegClassStrings = ClassStrings; NumClasses = NC; RegUnitRoots = RURoots; NumRegUnits = NRU; @@ -401,6 +410,10 @@ public: return Classes[i]; } + const char *getRegClassName(const MCRegisterClass *Class) const { + return RegClassStrings + Class->NameIdx; + } + /// \brief Returns the encoding for RegNo uint16_t getEncodingValue(unsigned RegNo) const { assert(RegNo < NumRegs && @@ -449,6 +462,38 @@ public: } }; +/// Iterator that enumerates the sub-registers of a Reg and the associated +/// sub-register indices. +class MCSubRegIndexIterator { + MCSubRegIterator SRIter; + const uint16_t *SRIndex; +public: + /// Constructs an iterator that traverses subregisters and their + /// associated subregister indices. + MCSubRegIndexIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : SRIter(Reg, MCRI) { + SRIndex = MCRI->SubRegIndices + MCRI->get(Reg).SubRegIndices; + } + + /// Returns current sub-register. + unsigned getSubReg() const { + return *SRIter; + } + /// Returns sub-register index of the current sub-register. + unsigned getSubRegIndex() const { + return *SRIndex; + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return SRIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++SRIter; + ++SRIndex; + } +}; + /// MCSuperRegIterator enumerates all super-registers of Reg. /// If IncludeSelf is set, Reg itself is included in the list. class MCSuperRegIterator : public MCRegisterInfo::DiffListIterator { @@ -510,6 +555,36 @@ public: } }; +/// MCRegUnitIterator enumerates a list of register units and their associated +/// lane masks for Reg. The register units are in ascending numerical order. +class MCRegUnitMaskIterator { + MCRegUnitIterator RUIter; + const unsigned *MaskListIter; +public: + MCRegUnitMaskIterator() {} + /// Constructs an iterator that traverses the register units and their + /// associated LaneMasks in Reg. + MCRegUnitMaskIterator(unsigned Reg, const MCRegisterInfo *MCRI) + : RUIter(Reg, MCRI) { + uint16_t Idx = MCRI->get(Reg).RegUnitLaneMasks; + MaskListIter = &MCRI->RegUnitMaskSequences[Idx]; + } + + /// Returns a (RegUnit, LaneMask) pair. + std::pair operator*() const { + return std::make_pair(*RUIter, *MaskListIter); + } + + /// Returns true if this iterator is not yet at the end. + bool isValid() const { return RUIter.isValid(); } + + /// Moves to the next position. + void operator++() { + ++MaskListIter; + ++RUIter; + } +}; + // Each register unit has one or two root registers. The complete set of // registers containing a register unit is the union of the roots and their // super-registers. All registers aliasing Unit can be visited like this: diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index 43b8672..1adfedd 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -133,10 +133,7 @@ struct MCSchedClassDesc { /// provides a detailed reservation table describing each cycle of instruction /// execution. Subtargets may define any or all of the above categories of data /// depending on the type of CPU and selected scheduler. -class MCSchedModel { -public: - static MCSchedModel DefaultSchedModel; // For unknown processors. - +struct MCSchedModel { // IssueWidth is the maximum number of instructions that may be scheduled in // the same per-cycle group. unsigned IssueWidth; @@ -191,7 +188,6 @@ public: bool CompleteModel; -private: unsigned ProcID; const MCProcResourceDesc *ProcResourceTable; const MCSchedClassDesc *SchedClassTable; @@ -201,37 +197,6 @@ private: friend class InstrItineraryData; const InstrItinerary *InstrItineraries; -public: - // Default's must be specified as static const literals so that tablegenerated - // target code can use it in static initializers. The defaults need to be - // initialized in this default ctor because some clients directly instantiate - // MCSchedModel instead of using a generated itinerary. - MCSchedModel(): IssueWidth(DefaultIssueWidth), - MicroOpBufferSize(DefaultMicroOpBufferSize), - LoopMicroOpBufferSize(DefaultLoopMicroOpBufferSize), - LoadLatency(DefaultLoadLatency), - HighLatency(DefaultHighLatency), - MispredictPenalty(DefaultMispredictPenalty), - PostRAScheduler(false), CompleteModel(true), - ProcID(0), ProcResourceTable(nullptr), - SchedClassTable(nullptr), NumProcResourceKinds(0), - NumSchedClasses(0), InstrItineraries(nullptr) { - (void)NumProcResourceKinds; - (void)NumSchedClasses; - } - - // Table-gen driven ctor. - MCSchedModel(unsigned iw, int mbs, int lmbs, unsigned ll, unsigned hl, - unsigned mp, bool postRASched, bool cm, unsigned pi, - const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, - unsigned npr, unsigned nsc, const InstrItinerary *ii): - IssueWidth(iw), MicroOpBufferSize(mbs), LoopMicroOpBufferSize(lmbs), - LoadLatency(ll), HighLatency(hl), - MispredictPenalty(mp), PostRAScheduler(postRASched), - CompleteModel(cm), ProcID(pi), - ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), - NumSchedClasses(nsc), InstrItineraries(ii) {} - unsigned getProcessorID() const { return ProcID; } /// Does this machine model include instruction-level scheduling. @@ -258,6 +223,26 @@ public: assert(SchedClassIdx < NumSchedClasses && "bad scheduling class idx"); return &SchedClassTable[SchedClassIdx]; } + + // /\brief Returns a default initialized model. Used for unknown processors. + static MCSchedModel GetDefaultSchedModel() { + MCSchedModel Ret = { DefaultIssueWidth, + DefaultMicroOpBufferSize, + DefaultLoopMicroOpBufferSize, + DefaultLoadLatency, + DefaultHighLatency, + DefaultMispredictPenalty, + false, + true, + 0, + nullptr, + nullptr, + 0, + 0, + nullptr + }; + return Ret; + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 63a43d0..18855f9 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -20,7 +20,7 @@ #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCDwarf.h" #include "llvm/MC/MCLinkerOptimizationHint.h" -#include "llvm/MC/MCWin64EH.h" +#include "llvm/MC/MCWinEH.h" #include "llvm/Support/DataTypes.h" #include @@ -49,14 +49,14 @@ typedef std::pair MCSectionSubPair; /// /// If target foo wants to use this, it should implement 3 classes: /// * FooTargetStreamer : public MCTargetStreamer -/// * FooTargetAsmSreamer : public FooTargetStreamer +/// * FooTargetAsmStreamer : public FooTargetStreamer /// * FooTargetELFStreamer : public FooTargetStreamer /// /// FooTargetStreamer should have a pure virtual method for each directive. For /// example, for a ".bar symbol_name" directive, it should have /// virtual emitBar(const MCSymbol &Symbol) = 0; /// -/// The FooTargetAsmSreamer and FooTargetELFStreamer classes implement the +/// The FooTargetAsmStreamer and FooTargetELFStreamer classes implement the /// method. The assembly streamer just prints ".bar symbol_name". The object /// streamer does whatever is needed to implement .bar in the object file. /// @@ -66,8 +66,9 @@ typedef std::pair MCSectionSubPair; /// MCTargetStreamer &TS = OutStreamer.getTargetStreamer(); /// FooTargetStreamer &ATS = static_cast(TS); /// -/// The base classes FooTargetAsmSreamer and FooTargetELFStreamer should *never* -/// be treated differently. Callers should always talk to a FooTargetStreamer. +/// The base classes FooTargetAsmStreamer and FooTargetELFStreamer should +/// *never* be treated differently. Callers should always talk to a +/// FooTargetStreamer. class MCTargetStreamer { protected: MCStreamer &Streamer; @@ -91,7 +92,6 @@ public: AArch64TargetStreamer(MCStreamer &S); ~AArch64TargetStreamer(); - void finish() override; /// Callback used to implement the ldr= pseudo. @@ -103,6 +103,9 @@ public: /// Emit contents of constant pool for the current section. void emitCurrentConstantPool(); + /// Callback used to implement the .inst directive. + virtual void emitInst(uint32_t Inst); + private: std::unique_ptr ConstantPools; }; @@ -181,8 +184,8 @@ class MCStreamer { MCSymbol *EmitCFICommon(); - std::vector WinFrameInfos; - MCWinFrameInfo *CurrentWinFrameInfo; + std::vector WinFrameInfos; + WinEH::FrameInfo *CurrentWinFrameInfo; void EnsureValidWinFrameInfo(); // SymbolOrdering - Tracks an index to represent the order @@ -196,19 +199,14 @@ class MCStreamer { protected: MCStreamer(MCContext &Ctx); - const MCExpr *BuildSymbolDiff(MCContext &Context, const MCSymbol *A, - const MCSymbol *B); - - const MCExpr *ForceExpAbs(const MCExpr *Expr); - virtual void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame); virtual void EmitCFIEndProcImpl(MCDwarfFrameInfo &CurFrame); - MCWinFrameInfo *getCurrentWinFrameInfo() { + WinEH::FrameInfo *getCurrentWinFrameInfo() { return CurrentWinFrameInfo; } - void EmitWindowsUnwindTables(); + virtual void EmitWindowsUnwindTables(); virtual void EmitRawTextImpl(StringRef String); @@ -238,7 +236,7 @@ public: } unsigned getNumWinFrameInfos() { return WinFrameInfos.size(); } - ArrayRef getWinFrameInfos() const { + ArrayRef getWinFrameInfos() const { return WinFrameInfos; } @@ -349,8 +347,8 @@ public: /// @p Section. This is required to update CurSection. /// /// This corresponds to assembler directives like .section, .text, etc. - void SwitchSection(const MCSection *Section, - const MCExpr *Subsection = nullptr) { + virtual void SwitchSection(const MCSection *Section, + const MCExpr *Subsection = nullptr) { assert(Section && "Cannot switch to a null section!"); MCSectionSubPair curSection = SectionStack.back().first; SectionStack.back().second = curSection; @@ -373,7 +371,7 @@ public: } /// Create the default sections and set the initial one. - virtual void InitSections(); + virtual void InitSections(bool NoExecStack); /// AssignSection - Sets the symbol's section. /// @@ -552,12 +550,6 @@ public: /// to pass in a MCExpr for constant integers. virtual void EmitIntValue(uint64_t Value, unsigned Size); - /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO - /// this is done by producing - /// foo = value - /// .long foo - void EmitAbsValue(const MCExpr *Value, unsigned Size); - virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); @@ -669,11 +661,6 @@ public: StringRef FileName); virtual MCSymbol *getDwarfLineTableSymbol(unsigned CUID); - - void EmitDwarfSetLineAddr(int64_t LineDelta, const MCSymbol *Label, - int PointerSize); - - virtual void EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding); virtual void EmitCFISections(bool EH, bool Debug); void EmitCFIStartProc(bool IsSimple); void EmitCFIEndProc(); @@ -782,8 +769,8 @@ MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, /// createELFStreamer - Create a machine code streamer which will generate /// ELF format object files. MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll, - bool NoExecStack); + raw_ostream &OS, MCCodeEmitter *CE, + bool RelaxAll); } // end namespace llvm diff --git a/include/llvm/MC/MCSubtargetInfo.h b/include/llvm/MC/MCSubtargetInfo.h index 088c5e7..3f38bd5 100644 --- a/include/llvm/MC/MCSubtargetInfo.h +++ b/include/llvm/MC/MCSubtargetInfo.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_MCSUBTARGET_H -#define LLVM_MC_MCSUBTARGET_H +#ifndef LLVM_MC_MCSUBTARGETINFO_H +#define LLVM_MC_MCSUBTARGETINFO_H #include "llvm/MC/MCInstrItineraries.h" #include "llvm/MC/SubtargetFeature.h" @@ -36,7 +36,7 @@ class MCSubtargetInfo { const MCWriteProcResEntry *WriteProcResTable; const MCWriteLatencyEntry *WriteLatencyTable; const MCReadAdvanceEntry *ReadAdvanceTable; - const MCSchedModel *CPUSchedModel; + MCSchedModel CPUSchedModel; const InstrStage *Stages; // Instruction itinerary stages const unsigned *OperandCycles; // Itinerary operand cycles @@ -65,6 +65,10 @@ public: return FeatureBits; } + /// setFeatureBits - Set the feature bits. + /// + void setFeatureBits(uint64_t FeatureBits_) { FeatureBits = FeatureBits_; } + /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented with /// feature string). Recompute feature bits and scheduling model. void InitMCProcessorInfo(StringRef CPU, StringRef FS); @@ -82,11 +86,11 @@ public: /// getSchedModelForCPU - Get the machine model of a CPU. /// - const MCSchedModel *getSchedModelForCPU(StringRef CPU) const; + MCSchedModel getSchedModelForCPU(StringRef CPU) const; /// getSchedModel - Get the machine model for this subtarget's CPU. /// - const MCSchedModel *getSchedModel() const { return CPUSchedModel; } + const MCSchedModel &getSchedModel() const { return CPUSchedModel; } /// Return an iterator at the first process resource consumed by the given /// scheduling class. @@ -132,6 +136,15 @@ public: /// Initialize an InstrItineraryData instance. void initInstrItins(InstrItineraryData &InstrItins) const; + + /// Check whether the CPU string is valid. + bool isCPUStringValid(StringRef CPU) { + auto Found = std::find_if(ProcDesc.begin(), ProcDesc.end(), + [=](const SubtargetFeatureKV &KV) { + return CPU == KV.Key; + }); + return Found != ProcDesc.end(); + } }; } // End llvm namespace diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 0b3c3ce..47a8789 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -53,6 +53,9 @@ namespace llvm { /// "Lfoo" or ".foo". unsigned IsTemporary : 1; + /// \brief True if this symbol can be redefined. + unsigned IsRedefinable : 1; + /// IsUsed - True if this symbol has been used. mutable unsigned IsUsed : 1; @@ -61,7 +64,7 @@ namespace llvm { friend class MCContext; MCSymbol(StringRef name, bool isTemporary) : Name(name), Section(nullptr), Value(nullptr), - IsTemporary(isTemporary), IsUsed(false) {} + IsTemporary(isTemporary), IsRedefinable(false), IsUsed(false) {} MCSymbol(const MCSymbol&) LLVM_DELETED_FUNCTION; void operator=(const MCSymbol&) LLVM_DELETED_FUNCTION; @@ -79,6 +82,19 @@ namespace llvm { bool isUsed() const { return IsUsed; } void setUsed(bool Value) const { IsUsed = Value; } + /// \brief Check if this symbol is redefinable. + bool isRedefinable() const { return IsRedefinable; } + /// \brief Mark this symbol as redefinable. + void setRedefinable(bool Value) { IsRedefinable = Value; } + /// \brief Prepare this symbol to be redefined. + void redefineIfPossible() { + if (IsRedefinable) { + Value = nullptr; + Section = nullptr; + IsRedefinable = false; + } + } + /// @} /// @name Associated Sections /// @{ diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 9a5881b..ea71d1f 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -7,13 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_TARGETPARSER_H -#define LLVM_MC_TARGETPARSER_H +#ifndef LLVM_MC_MCTARGETASMPARSER_H +#define LLVM_MC_MCTARGETASMPARSER_H #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCParser/MCAsmParserExtension.h" #include "llvm/MC/MCTargetOptions.h" - #include namespace llvm { @@ -38,20 +37,22 @@ enum AsmRewriteKind { AOK_Input, // Rewrite in terms of $N. AOK_Output, // Rewrite in terms of $N. AOK_SizeDirective, // Add a sizing directive (e.g., dword ptr). + AOK_Label, // Rewrite local labels. AOK_Skip // Skip emission (e.g., offset/type operators). }; const char AsmRewritePrecedence [] = { 0, // AOK_Delete - 1, // AOK_Align - 1, // AOK_DotOperator - 1, // AOK_Emit - 3, // AOK_Imm - 3, // AOK_ImmPrefix - 2, // AOK_Input - 2, // AOK_Output - 4, // AOK_SizeDirective - 1 // AOK_Skip + 2, // AOK_Align + 2, // AOK_DotOperator + 2, // AOK_Emit + 4, // AOK_Imm + 4, // AOK_ImmPrefix + 3, // AOK_Input + 3, // AOK_Output + 5, // AOK_SizeDirective + 1, // AOK_Label + 2 // AOK_Skip }; struct AsmRewrite { @@ -59,9 +60,12 @@ struct AsmRewrite { SMLoc Loc; unsigned Len; unsigned Val; + StringRef Label; public: AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len = 0, unsigned val = 0) : Kind(kind), Loc(loc), Len(len), Val(val) {} + AsmRewrite(AsmRewriteKind kind, SMLoc loc, unsigned len, StringRef label) + : Kind(kind), Loc(loc), Len(len), Val(0), Label(label) {} }; struct ParseInstructionInfo { @@ -93,7 +97,7 @@ protected: // Can only create subclasses. MCTargetAsmParser(); /// AvailableFeatures - The current set of available features. - unsigned AvailableFeatures; + uint64_t AvailableFeatures; /// ParsingInlineAsm - Are we parsing ms-style inline assembly? bool ParsingInlineAsm; @@ -108,12 +112,14 @@ protected: // Can only create subclasses. public: virtual ~MCTargetAsmParser(); - unsigned getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(unsigned Value) { AvailableFeatures = Value; } + uint64_t getAvailableFeatures() const { return AvailableFeatures; } + void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } bool isParsingInlineAsm () { return ParsingInlineAsm; } void setParsingInlineAsm (bool Value) { ParsingInlineAsm = Value; } + MCTargetOptions getTargetOptions() const { return MCOptions; } + void setSemaCallback(MCAsmParserSemaCallback *Callback) { SemaCallback = Callback; } @@ -121,6 +127,9 @@ public: virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0; + /// Sets frame register corresponding to the current MachineFunction. + virtual void SetFrameRegister(unsigned RegNo) {} + /// ParseInstruction - Parse one assembly instruction. /// /// The parser is positioned following the instruction name. The target @@ -161,7 +170,7 @@ public: /// explaining the match failure. virtual bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, OperandVector &Operands, MCStreamer &Out, - unsigned &ErrorInfo, + uint64_t &ErrorInfo, bool MatchingInlineAsm) = 0; /// Allows targets to let registers opt out of clobber lists. diff --git a/include/llvm/MC/MCTargetOptions.h b/include/llvm/MC/MCTargetOptions.h index eb4348e..ce28a19 100644 --- a/include/llvm/MC/MCTargetOptions.h +++ b/include/llvm/MC/MCTargetOptions.h @@ -10,8 +10,12 @@ #ifndef LLVM_MC_MCTARGETOPTIONS_H #define LLVM_MC_MCTARGETOPTIONS_H +#include + namespace llvm { +class StringRef; + class MCTargetOptions { public: enum AsmInstrumentation { @@ -24,12 +28,18 @@ public: bool MCRelaxAll : 1; bool MCNoExecStack : 1; + bool MCFatalWarnings : 1; bool MCSaveTempLabels : 1; bool MCUseDwarfDirectory : 1; bool ShowMCEncoding : 1; bool ShowMCInst : 1; bool AsmVerbose : 1; int DwarfVersion; + /// getABIName - If this returns a non-empty string this represents the + /// textual name of the ABI that we want the backend to use, e.g. o32, or + /// aapcs-linux. + StringRef getABIName() const; + std::string ABIName; MCTargetOptions(); }; @@ -38,12 +48,14 @@ inline bool operator==(const MCTargetOptions &LHS, const MCTargetOptions &RHS) { return (ARE_EQUAL(SanitizeAddress) && ARE_EQUAL(MCRelaxAll) && ARE_EQUAL(MCNoExecStack) && + ARE_EQUAL(MCFatalWarnings) && ARE_EQUAL(MCSaveTempLabels) && ARE_EQUAL(MCUseDwarfDirectory) && ARE_EQUAL(ShowMCEncoding) && ARE_EQUAL(ShowMCInst) && ARE_EQUAL(AsmVerbose) && - ARE_EQUAL(DwarfVersion)); + ARE_EQUAL(DwarfVersion) && + ARE_EQUAL(ABIName)); #undef ARE_EQUAL } diff --git a/include/llvm/MC/MCTargetOptionsCommandFlags.h b/include/llvm/MC/MCTargetOptionsCommandFlags.h index 6d4eb0e..af23a92 100644 --- a/include/llvm/MC/MCTargetOptionsCommandFlags.h +++ b/include/llvm/MC/MCTargetOptionsCommandFlags.h @@ -15,8 +15,8 @@ #ifndef LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H #define LLVM_MC_MCTARGETOPTIONSCOMMANDFLAGS_H -#include "llvm/Support/CommandLine.h" #include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; cl::opt AsmInstrumentation( @@ -40,6 +40,11 @@ cl::opt ShowMCInst("asm-show-inst", cl::desc("Emit internal instruction representation to " "assembly file")); +cl::opt +ABIName("target-abi", cl::Hidden, + cl::desc("The name of the ABI to be targeted from the backend."), + cl::init("")); + static inline MCTargetOptions InitMCTargetOptionsFromFlags() { MCTargetOptions Options; Options.SanitizeAddress = @@ -47,6 +52,7 @@ static inline MCTargetOptions InitMCTargetOptionsFromFlags() { Options.MCRelaxAll = RelaxAll; Options.DwarfVersion = DwarfVersion; Options.ShowMCInst = ShowMCInst; + Options.ABIName = ABIName; return Options; } diff --git a/include/llvm/MC/MCWin64EH.h b/include/llvm/MC/MCWin64EH.h index 3df0d0a..0e81a19 100644 --- a/include/llvm/MC/MCWin64EH.h +++ b/include/llvm/MC/MCWin64EH.h @@ -20,9 +20,8 @@ #include namespace llvm { - class StringRef; - class MCStreamer; - class MCSymbol; +class MCStreamer; +class MCSymbol; namespace Win64EH { struct Instruction { @@ -52,36 +51,13 @@ struct Instruction { return WinEH::Instruction(UOP_SetFPReg, L, Reg, Off); } }; -} - - struct MCWinFrameInfo { - MCWinFrameInfo() - : Begin(nullptr), End(nullptr),ExceptionHandler(nullptr), - Function(nullptr), PrologEnd(nullptr), Symbol(nullptr), - HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), - ChainedParent(nullptr), Instructions() {} - MCSymbol *Begin; - MCSymbol *End; - const MCSymbol *ExceptionHandler; - const MCSymbol *Function; - MCSymbol *PrologEnd; - MCSymbol *Symbol; - bool HandlesUnwind; - bool HandlesExceptions; - int LastFrameInst; - MCWinFrameInfo *ChainedParent; - std::vector Instructions; - }; - class MCWin64EHUnwindEmitter { - public: - static StringRef GetSectionSuffix(const MCSymbol *func); - // - // This emits the unwind info sections (.pdata and .xdata in PE/COFF). - // - static void Emit(MCStreamer &streamer); - static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info); - }; +class UnwindEmitter : public WinEH::UnwindEmitter { +public: + void Emit(MCStreamer &Streamer) const override; + void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI) const override; +}; +} } // end namespace llvm #endif diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 7d2d0e4..57a75ce 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -30,10 +30,16 @@ public: MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, raw_ostream &OS); + /// state management + void reset() override { + CurSymbol = nullptr; + MCObjectStreamer::reset(); + } + /// \name MCStreamer interface /// \{ - void InitSections() override; + void InitSections(bool NoExecStack) override; void EmitLabel(MCSymbol *Symbol) override; void EmitAssemblerFlag(MCAssemblerFlag Flag) override; void EmitThumbFunc(MCSymbol *Func) override; diff --git a/include/llvm/MC/MCWinEH.h b/include/llvm/MC/MCWinEH.h index 1cd1b0f..05b58c7 100644 --- a/include/llvm/MC/MCWinEH.h +++ b/include/llvm/MC/MCWinEH.h @@ -10,8 +10,14 @@ #ifndef LLVM_MC_MCWINEH_H #define LLVM_MC_MCWINEH_H +#include + namespace llvm { +class MCContext; +class MCSection; +class MCStreamer; class MCSymbol; +class StringRef; namespace WinEH { struct Instruction { @@ -23,6 +29,55 @@ struct Instruction { Instruction(unsigned Op, MCSymbol *L, unsigned Reg, unsigned Off) : Label(L), Offset(Off), Register(Reg), Operation(Op) {} }; + +struct FrameInfo { + const MCSymbol *Begin; + const MCSymbol *End; + const MCSymbol *ExceptionHandler; + const MCSymbol *Function; + const MCSymbol *PrologEnd; + const MCSymbol *Symbol; + + bool HandlesUnwind; + bool HandlesExceptions; + + int LastFrameInst; + const FrameInfo *ChainedParent; + std::vector Instructions; + + FrameInfo() + : Begin(nullptr), End(nullptr), ExceptionHandler(nullptr), + Function(nullptr), PrologEnd(nullptr), Symbol(nullptr), + HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), + ChainedParent(nullptr), Instructions() {} + FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel) + : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr), + Function(Function), PrologEnd(nullptr), Symbol(nullptr), + HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), + ChainedParent(nullptr), Instructions() {} + FrameInfo(const MCSymbol *Function, const MCSymbol *BeginFuncEHLabel, + const FrameInfo *ChainedParent) + : Begin(BeginFuncEHLabel), End(nullptr), ExceptionHandler(nullptr), + Function(Function), PrologEnd(nullptr), Symbol(nullptr), + HandlesUnwind(false), HandlesExceptions(false), LastFrameInst(-1), + ChainedParent(ChainedParent), Instructions() {} +}; + +class UnwindEmitter { +public: + static const MCSection *getPDataSection(const MCSymbol *Function, + MCContext &Context); + static const MCSection *getXDataSection(const MCSymbol *Function, + MCContext &Context); + + virtual ~UnwindEmitter() { } + + // + // This emits the unwind info sections (.pdata and .xdata in PE/COFF). + // + virtual void Emit(MCStreamer &Streamer) const = 0; + virtual void EmitUnwindInfo(MCStreamer &Streamer, FrameInfo *FI) const = 0; +}; } } diff --git a/include/llvm/MC/StringTableBuilder.h b/include/llvm/MC/StringTableBuilder.h index 065e9e0..897d449 100644 --- a/include/llvm/MC/StringTableBuilder.h +++ b/include/llvm/MC/StringTableBuilder.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_STRINGTABLE_BUILDER_H -#define LLVM_MC_STRINGTABLE_BUILDER_H +#ifndef LLVM_MC_STRINGTABLEBUILDER_H +#define LLVM_MC_STRINGTABLEBUILDER_H #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringMap.h" @@ -26,12 +26,18 @@ public: /// copy of s. Can only be used before the table is finalized. StringRef add(StringRef s) { assert(!isFinalized()); - return StringIndexMap.GetOrCreateValue(s, 0).getKey(); + return StringIndexMap.insert(std::make_pair(s, 0)).first->first(); } + enum Kind { + ELF, + WinCOFF, + MachO + }; + /// \brief Analyze the strings and build the final table. No more strings can /// be added after this point. - void finalize(); + void finalize(Kind kind); /// \brief Retrieve the string table data. Can only be used after the table /// is finalized. @@ -48,6 +54,8 @@ public: return StringIndexMap[s]; } + void clear(); + private: bool isFinalized() { return !StringTable.empty(); diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index c5d62a6..bfecb8b 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -72,21 +72,21 @@ struct SubtargetInfoKV { class SubtargetFeatures { std::vector Features; // Subtarget features as a vector public: - explicit SubtargetFeatures(const StringRef Initial = ""); + explicit SubtargetFeatures(StringRef Initial = ""); /// Features string accessors. std::string getString() const; /// Adding Features. - void AddFeature(const StringRef String); + void AddFeature(StringRef String); /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. - uint64_t ToggleFeature(uint64_t Bits, const StringRef String, + uint64_t ToggleFeature(uint64_t Bits, StringRef String, ArrayRef FeatureTable); /// Get feature bits of a CPU. - uint64_t getFeatureBits(const StringRef CPU, + uint64_t getFeatureBits(StringRef CPU, ArrayRef CPUTable, ArrayRef FeatureTable); diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index af6c995..4e96205 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -15,6 +15,7 @@ #define LLVM_OBJECT_ARCHIVE_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Object/Binary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ErrorOr.h" @@ -83,14 +84,13 @@ public: return getHeader()->getAccessMode(); } /// \return the size of the archive member without the header or padding. - uint64_t getSize() const { return Data.size() - StartOfFile; } + uint64_t getSize() const; StringRef getBuffer() const { return StringRef(Data.data() + StartOfFile, getSize()); } - ErrorOr> - getMemoryBuffer(bool FullPath = false) const; + ErrorOr getMemoryBufferRef() const; ErrorOr> getAsBinary(LLVMContext *Context = nullptr) const; @@ -98,12 +98,12 @@ public: class child_iterator { Child child; + public: child_iterator() : child(Child(nullptr, nullptr)) {} child_iterator(const Child &c) : child(c) {} - const Child* operator->() const { - return &child; - } + const Child *operator->() const { return &child; } + const Child &operator*() const { return child; } bool operator==(const child_iterator &other) const { return child == other.child; @@ -113,11 +113,11 @@ public: return !(*this == other); } - bool operator <(const child_iterator &other) const { + bool operator<(const child_iterator &other) const { return child < other.child; } - child_iterator& operator++() { // Preincrement + child_iterator &operator++() { // Preincrement child = child.getNext(); return *this; } @@ -164,8 +164,8 @@ public: } }; - Archive(std::unique_ptr Source, std::error_code &EC); - static ErrorOr create(std::unique_ptr Source); + Archive(MemoryBufferRef Source, std::error_code &EC); + static ErrorOr> create(MemoryBufferRef Source); enum Kind { K_GNU, @@ -173,12 +173,14 @@ public: K_COFF }; - Kind kind() const { - return Format; - } + Kind kind() const { return (Kind)Format; } child_iterator child_begin(bool SkipInternal = true) const; child_iterator child_end() const; + iterator_range children(bool SkipInternal = true) const { + return iterator_range(child_begin(SkipInternal), + child_end()); + } symbol_iterator symbol_begin() const; symbol_iterator symbol_end() const; @@ -197,7 +199,8 @@ private: child_iterator SymbolTable; child_iterator StringTable; child_iterator FirstRegular; - Kind Format; + unsigned Format : 2; + unsigned IsThin : 1; }; } diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 91984cb..4b2b7e6 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -17,11 +17,11 @@ #include "llvm/Object/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" namespace llvm { class LLVMContext; -class MemoryBuffer; class StringRef; namespace object { @@ -34,9 +34,9 @@ private: unsigned int TypeID; protected: - std::unique_ptr Data; + MemoryBufferRef Data; - Binary(unsigned int Type, std::unique_ptr Source); + Binary(unsigned int Type, MemoryBufferRef Source); enum { ID_Archive, @@ -78,8 +78,8 @@ public: virtual ~Binary(); StringRef getData() const; - MemoryBuffer *releaseBuffer() { return Data.release(); } StringRef getFileName() const; + MemoryBufferRef getMemoryBufferRef() const; // Cast methods. unsigned int getType() const { return TypeID; } @@ -126,10 +126,58 @@ public: /// @brief Create a Binary from Source, autodetecting the file type. /// /// @param Source The data to create the Binary from. -ErrorOr createBinary(std::unique_ptr Source, - LLVMContext *Context = nullptr); +ErrorOr> createBinary(MemoryBufferRef Source, + LLVMContext *Context = nullptr); -ErrorOr createBinary(StringRef Path); +template class OwningBinary { + std::unique_ptr Bin; + std::unique_ptr Buf; + +public: + OwningBinary(); + OwningBinary(std::unique_ptr Bin, std::unique_ptr Buf); + OwningBinary(OwningBinary&& Other); + OwningBinary &operator=(OwningBinary &&Other); + + std::pair, std::unique_ptr> takeBinary(); + + T* getBinary(); + const T* getBinary() const; +}; + +template +OwningBinary::OwningBinary(std::unique_ptr Bin, + std::unique_ptr Buf) + : Bin(std::move(Bin)), Buf(std::move(Buf)) {} + +template OwningBinary::OwningBinary() {} + +template +OwningBinary::OwningBinary(OwningBinary &&Other) + : Bin(std::move(Other.Bin)), Buf(std::move(Other.Buf)) {} + +template +OwningBinary &OwningBinary::operator=(OwningBinary &&Other) { + Bin = std::move(Other.Bin); + Buf = std::move(Other.Buf); + return *this; +} + +template +std::pair, std::unique_ptr> +OwningBinary::takeBinary() { + return std::make_pair(std::move(Bin), std::move(Buf)); +} + +template T* OwningBinary::getBinary() { + return Bin.get(); +} + +template const T* OwningBinary::getBinary() const { + return Bin.get(); +} + +ErrorOr> createBinary(StringRef Path); } } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index e2da070..522bf68 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -14,22 +14,31 @@ #ifndef LLVM_OBJECT_COFF_H #define LLVM_OBJECT_COFF_H +#include "llvm/ADT/PointerUnion.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/ErrorOr.h" namespace llvm { template class ArrayRef; namespace object { class ImportDirectoryEntryRef; +class DelayImportDirectoryEntryRef; class ExportDirectoryEntryRef; +class ImportedSymbolRef; +class BaseRelocRef; typedef content_iterator import_directory_iterator; +typedef content_iterator + delay_import_directory_iterator; typedef content_iterator export_directory_iterator; +typedef content_iterator imported_symbol_iterator; +typedef content_iterator base_reloc_iterator; /// The DOS compatible header at the front of all PE/COFF executables. struct dos_header { - support::ulittle16_t Magic; + char Magic[2]; support::ulittle16_t UsedBytesInTheLastPage; support::ulittle16_t FileSizeInPages; support::ulittle16_t NumberOfRelocationItems; @@ -62,6 +71,22 @@ struct coff_file_header { bool isImportLibrary() const { return NumberOfSections == 0xffff; } }; +struct coff_bigobj_file_header { + support::ulittle16_t Sig1; + support::ulittle16_t Sig2; + support::ulittle16_t Version; + support::ulittle16_t Machine; + support::ulittle32_t TimeDateStamp; + uint8_t UUID[16]; + support::ulittle32_t unused1; + support::ulittle32_t unused2; + support::ulittle32_t unused3; + support::ulittle32_t unused4; + support::ulittle32_t NumberOfSections; + support::ulittle32_t PointerToSymbolTable; + support::ulittle32_t NumberOfSymbols; +}; + /// The 32-bit PE header that follows the COFF header. struct pe32_header { support::ulittle16_t Magic; @@ -87,12 +112,14 @@ struct pe32_header { support::ulittle32_t SizeOfHeaders; support::ulittle32_t CheckSum; support::ulittle16_t Subsystem; + // FIXME: This should be DllCharacteristics. support::ulittle16_t DLLCharacteristics; support::ulittle32_t SizeOfStackReserve; support::ulittle32_t SizeOfStackCommit; support::ulittle32_t SizeOfHeapReserve; support::ulittle32_t SizeOfHeapCommit; support::ulittle32_t LoaderFlags; + // FIXME: This should be NumberOfRvaAndSizes. support::ulittle32_t NumberOfRvaAndSize; }; @@ -142,22 +169,40 @@ struct import_directory_table_entry { support::ulittle32_t ImportAddressTableRVA; }; -struct import_lookup_table_entry32 { - support::ulittle32_t data; +template +struct import_lookup_table_entry { + IntTy Data; - bool isOrdinal() const { return data & 0x80000000; } + bool isOrdinal() const { return Data < 0; } uint16_t getOrdinal() const { assert(isOrdinal() && "ILT entry is not an ordinal!"); - return data & 0xFFFF; + return Data & 0xFFFF; } uint32_t getHintNameRVA() const { assert(!isOrdinal() && "ILT entry is not a Hint/Name RVA!"); - return data; + return Data & 0xFFFFFFFF; } }; +typedef import_lookup_table_entry + import_lookup_table_entry32; +typedef import_lookup_table_entry + import_lookup_table_entry64; + +struct delay_import_directory_table_entry { + // dumpbin reports this field as "Characteristics" instead of "Attributes". + support::ulittle32_t Attributes; + support::ulittle32_t Name; + support::ulittle32_t ModuleHandle; + support::ulittle32_t DelayImportAddressTable; + support::ulittle32_t DelayImportNameTable; + support::ulittle32_t BoundDelayImportTable; + support::ulittle32_t UnloadDelayImportTable; + support::ulittle32_t TimeStamp; +}; + struct export_directory_table_entry { support::ulittle32_t ExportFlags; support::ulittle32_t TimeDateStamp; @@ -180,67 +225,156 @@ union export_address_table_entry { typedef support::ulittle32_t export_name_pointer_table_entry; typedef support::ulittle16_t export_ordinal_table_entry; -struct coff_symbol { - struct StringTableOffset { - support::ulittle32_t Zeroes; - support::ulittle32_t Offset; - }; +struct StringTableOffset { + support::ulittle32_t Zeroes; + support::ulittle32_t Offset; +}; +template +struct coff_symbol { union { - char ShortName[8]; + char ShortName[COFF::NameSize]; StringTableOffset Offset; } Name; support::ulittle32_t Value; - support::ulittle16_t SectionNumber; + SectionNumberType SectionNumber; support::ulittle16_t Type; - support::ulittle8_t StorageClass; - support::ulittle8_t NumberOfAuxSymbols; + uint8_t StorageClass; + uint8_t NumberOfAuxSymbols; +}; + +typedef coff_symbol coff_symbol16; +typedef coff_symbol coff_symbol32; + +class COFFSymbolRef { +public: + COFFSymbolRef(const coff_symbol16 *CS) : CS16(CS), CS32(nullptr) {} + COFFSymbolRef(const coff_symbol32 *CS) : CS16(nullptr), CS32(CS) {} + COFFSymbolRef() : CS16(nullptr), CS32(nullptr) {} + + const void *getRawPtr() const { + return CS16 ? static_cast(CS16) : CS32; + } + + friend bool operator<(COFFSymbolRef A, COFFSymbolRef B) { + return A.getRawPtr() < B.getRawPtr(); + } + + bool isBigObj() const { + if (CS16) + return false; + if (CS32) + return true; + llvm_unreachable("COFFSymbolRef points to nothing!"); + } + + const char *getShortName() const { + return CS16 ? CS16->Name.ShortName : CS32->Name.ShortName; + } + + const StringTableOffset &getStringTableOffset() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Name.Offset : CS32->Name.Offset; + } + + uint32_t getValue() const { return CS16 ? CS16->Value : CS32->Value; } + + int32_t getSectionNumber() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + if (CS16) { + // Reserved sections are returned as negative numbers. + if (CS16->SectionNumber <= COFF::MaxNumberOfSections16) + return CS16->SectionNumber; + return static_cast(CS16->SectionNumber); + } + return static_cast(CS32->SectionNumber); + } + + uint16_t getType() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->Type : CS32->Type; + } + + uint8_t getStorageClass() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->StorageClass : CS32->StorageClass; + } + + uint8_t getNumberOfAuxSymbols() const { + assert(isSet() && "COFFSymbolRef points to nothing!"); + return CS16 ? CS16->NumberOfAuxSymbols : CS32->NumberOfAuxSymbols; + } + + uint8_t getBaseType() const { return getType() & 0x0F; } - uint8_t getBaseType() const { return Type & 0x0F; } + uint8_t getComplexType() const { + return (getType() & 0xF0) >> COFF::SCT_COMPLEX_TYPE_SHIFT; + } + + bool isExternal() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL; + } + + bool isCommon() const { + return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && + getValue() != 0; + } + + bool isUndefined() const { + return isExternal() && getSectionNumber() == COFF::IMAGE_SYM_UNDEFINED && + getValue() == 0; + } - uint8_t getComplexType() const { return (Type & 0xF0) >> 4; } + bool isWeakExternal() const { + return getStorageClass() == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL; + } bool isFunctionDefinition() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && + return isExternal() && getBaseType() == COFF::IMAGE_SYM_TYPE_NULL && getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION && - !COFF::isReservedSectionNumber(SectionNumber); + !COFF::isReservedSectionNumber(getSectionNumber()); } bool isFunctionLineInfo() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_FUNCTION; + return getStorageClass() == COFF::IMAGE_SYM_CLASS_FUNCTION; } - bool isWeakExternal() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL || - (StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - SectionNumber == COFF::IMAGE_SYM_UNDEFINED && Value == 0); + bool isAnyUndefined() const { + return isUndefined() || isWeakExternal(); } bool isFileRecord() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_FILE; + return getStorageClass() == COFF::IMAGE_SYM_CLASS_FILE; } bool isSectionDefinition() const { // C++/CLI creates external ABS symbols for non-const appdomain globals. // These are also followed by an auxiliary section definition. - bool isAppdomainGlobal = StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - SectionNumber == COFF::IMAGE_SYM_ABSOLUTE; - bool isOrdinarySection = - StorageClass == COFF::IMAGE_SYM_CLASS_STATIC && Value == 0; + bool isAppdomainGlobal = + getStorageClass() == COFF::IMAGE_SYM_CLASS_EXTERNAL && + getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE; + bool isOrdinarySection = getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC; + if (!getNumberOfAuxSymbols()) + return false; return isAppdomainGlobal || isOrdinarySection; } bool isCLRToken() const { - return StorageClass == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; + return getStorageClass() == COFF::IMAGE_SYM_CLASS_CLR_TOKEN; } + +private: + bool isSet() const { return CS16 || CS32; } + + const coff_symbol16 *CS16; + const coff_symbol32 *CS32; }; struct coff_section { - char Name[8]; + char Name[COFF::NameSize]; support::ulittle32_t VirtualSize; support::ulittle32_t VirtualAddress; support::ulittle32_t SizeOfRawData; @@ -254,9 +388,9 @@ struct coff_section { // Returns true if the actual number of relocations is stored in // VirtualAddress field of the first relocation table entry. bool hasExtendedRelocations() const { - return Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL && - NumberOfRelocations == UINT16_MAX; - }; + return (Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) && + NumberOfRelocations == UINT16_MAX; + } }; struct coff_relocation { @@ -270,7 +404,6 @@ struct coff_aux_function_definition { support::ulittle32_t TotalSize; support::ulittle32_t PointerToLinenumber; support::ulittle32_t PointerToNextFunction; - char Unused[2]; }; struct coff_aux_bf_and_ef_symbol { @@ -278,17 +411,11 @@ struct coff_aux_bf_and_ef_symbol { support::ulittle16_t Linenumber; char Unused2[6]; support::ulittle32_t PointerToNextFunction; - char Unused3[2]; }; struct coff_aux_weak_external { support::ulittle32_t TagIndex; support::ulittle32_t Characteristics; - char Unused[10]; -}; - -struct coff_aux_file { - char FileName[18]; }; struct coff_aux_section_definition { @@ -296,16 +423,22 @@ struct coff_aux_section_definition { support::ulittle16_t NumberOfRelocations; support::ulittle16_t NumberOfLinenumbers; support::ulittle32_t CheckSum; - support::ulittle16_t Number; - support::ulittle8_t Selection; - char Unused[3]; + support::ulittle16_t NumberLowPart; + uint8_t Selection; + uint8_t Unused; + support::ulittle16_t NumberHighPart; + int32_t getNumber(bool IsBigObj) const { + uint32_t Number = static_cast(NumberLowPart); + if (IsBigObj) + Number |= static_cast(NumberHighPart) << 16; + return static_cast(Number); + } }; struct coff_aux_clr_token { - support::ulittle8_t AuxType; - support::ulittle8_t Reserved; + uint8_t AuxType; + uint8_t Reserved; support::ulittle32_t SymbolTableIndex; - char Unused[12]; }; struct coff_load_configuration32 { @@ -324,7 +457,7 @@ struct coff_load_configuration32 { support::ulittle32_t ProcessAffinityMask; support::ulittle32_t ProcessHeapFlags; support::ulittle16_t CSDVersion; - uint16_t Reserved; + support::ulittle16_t Reserved; support::ulittle32_t EditList; support::ulittle32_t SecurityCookie; support::ulittle32_t SEHandlerTable; @@ -337,32 +470,114 @@ struct coff_runtime_function_x64 { support::ulittle32_t UnwindInformation; }; +struct coff_base_reloc_block_header { + support::ulittle32_t PageRVA; + support::ulittle32_t BlockSize; +}; + +struct coff_base_reloc_block_entry { + support::ulittle16_t Data; + int getType() const { return Data >> 12; } + int getOffset() const { return Data & ((1 << 12) - 1); } +}; + class COFFObjectFile : public ObjectFile { private: friend class ImportDirectoryEntryRef; friend class ExportDirectoryEntryRef; const coff_file_header *COFFHeader; + const coff_bigobj_file_header *COFFBigObjHeader; const pe32_header *PE32Header; const pe32plus_header *PE32PlusHeader; const data_directory *DataDirectory; const coff_section *SectionTable; - const coff_symbol *SymbolTable; + const coff_symbol16 *SymbolTable16; + const coff_symbol32 *SymbolTable32; const char *StringTable; uint32_t StringTableSize; const import_directory_table_entry *ImportDirectory; uint32_t NumberOfImportDirectory; + const delay_import_directory_table_entry *DelayImportDirectory; + uint32_t NumberOfDelayImportDirectory; const export_directory_table_entry *ExportDirectory; + const coff_base_reloc_block_header *BaseRelocHeader; + const coff_base_reloc_block_header *BaseRelocEnd; std::error_code getString(uint32_t offset, StringRef &Res) const; - const coff_symbol *toSymb(DataRefImpl Symb) const; + template + const coff_symbol_type *toSymb(DataRefImpl Symb) const; const coff_section *toSec(DataRefImpl Sec) const; const coff_relocation *toRel(DataRefImpl Rel) const; std::error_code initSymbolTablePtr(); std::error_code initImportTablePtr(); + std::error_code initDelayImportTablePtr(); std::error_code initExportTablePtr(); + std::error_code initBaseRelocPtr(); +public: + uintptr_t getSymbolTable() const { + if (SymbolTable16) + return reinterpret_cast(SymbolTable16); + if (SymbolTable32) + return reinterpret_cast(SymbolTable32); + return uintptr_t(0); + } + uint16_t getMachine() const { + if (COFFHeader) + return COFFHeader->Machine; + if (COFFBigObjHeader) + return COFFBigObjHeader->Machine; + llvm_unreachable("no COFF header!"); + } + uint16_t getSizeOfOptionalHeader() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 + : COFFHeader->SizeOfOptionalHeader; + // bigobj doesn't have this field. + if (COFFBigObjHeader) + return 0; + llvm_unreachable("no COFF header!"); + } + uint16_t getCharacteristics() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->Characteristics; + // bigobj doesn't have characteristics to speak of, + // editbin will silently lie to you if you attempt to set any. + if (COFFBigObjHeader) + return 0; + llvm_unreachable("no COFF header!"); + } + uint32_t getTimeDateStamp() const { + if (COFFHeader) + return COFFHeader->TimeDateStamp; + if (COFFBigObjHeader) + return COFFBigObjHeader->TimeDateStamp; + llvm_unreachable("no COFF header!"); + } + uint32_t getNumberOfSections() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSections; + if (COFFBigObjHeader) + return COFFBigObjHeader->NumberOfSections; + llvm_unreachable("no COFF header!"); + } + uint32_t getPointerToSymbolTable() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 + : COFFHeader->PointerToSymbolTable; + if (COFFBigObjHeader) + return COFFBigObjHeader->PointerToSymbolTable; + llvm_unreachable("no COFF header!"); + } + uint32_t getNumberOfSymbols() const { + if (COFFHeader) + return COFFHeader->isImportLibrary() ? 0 : COFFHeader->NumberOfSymbols; + if (COFFBigObjHeader) + return COFFBigObjHeader->NumberOfSymbols; + llvm_unreachable("no COFF header!"); + } protected: void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code getSymbolName(DataRefImpl Symb, @@ -378,24 +593,16 @@ protected: void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const override; - std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -414,54 +621,93 @@ protected: getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const override; - std::error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Result) const override; - std::error_code getLibraryPath(DataRefImpl LibData, - StringRef &Result) const override; - public: - COFFObjectFile(std::unique_ptr Object, std::error_code &EC); + COFFObjectFile(MemoryBufferRef Object, std::error_code &EC); basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; - library_iterator needed_library_begin() const override; - library_iterator needed_library_end() const override; section_iterator section_begin() const override; section_iterator section_end() const override; const coff_section *getCOFFSection(const SectionRef &Section) const; - const coff_symbol *getCOFFSymbol(const SymbolRef &Symbol) const; + COFFSymbolRef getCOFFSymbol(const DataRefImpl &Ref) const; + COFFSymbolRef getCOFFSymbol(const SymbolRef &Symbol) const; const coff_relocation *getCOFFRelocation(const RelocationRef &Reloc) const; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - StringRef getLoadName() const override; import_directory_iterator import_directory_begin() const; import_directory_iterator import_directory_end() const; + delay_import_directory_iterator delay_import_directory_begin() const; + delay_import_directory_iterator delay_import_directory_end() const; export_directory_iterator export_directory_begin() const; export_directory_iterator export_directory_end() const; - - std::error_code getHeader(const coff_file_header *&Res) const; - std::error_code getCOFFHeader(const coff_file_header *&Res) const; + base_reloc_iterator base_reloc_begin() const; + base_reloc_iterator base_reloc_end() const; + + iterator_range import_directories() const; + iterator_range + delay_import_directories() const; + iterator_range export_directories() const; + iterator_range base_relocs() const; + + const dos_header *getDOSHeader() const { + if (!PE32Header && !PE32PlusHeader) + return nullptr; + return reinterpret_cast(base()); + } std::error_code getPE32Header(const pe32_header *&Res) const; std::error_code getPE32PlusHeader(const pe32plus_header *&Res) const; std::error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; std::error_code getSection(int32_t index, const coff_section *&Res) const; - std::error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; + template + std::error_code getSymbol(uint32_t Index, + const coff_symbol_type *&Res) const { + if (Index >= getNumberOfSymbols()) + return object_error::parse_failed; + + Res = reinterpret_cast(getSymbolTable()) + Index; + return object_error::success; + } + ErrorOr getSymbol(uint32_t index) const { + if (SymbolTable16) { + const coff_symbol16 *Symb = nullptr; + if (std::error_code EC = getSymbol(index, Symb)) + return EC; + return COFFSymbolRef(Symb); + } + if (SymbolTable32) { + const coff_symbol32 *Symb = nullptr; + if (std::error_code EC = getSymbol(index, Symb)) + return EC; + return COFFSymbolRef(Symb); + } + return object_error::parse_failed; + } template std::error_code getAuxSymbol(uint32_t index, const T *&Res) const { - const coff_symbol *s; - std::error_code ec = getSymbol(index, s); - Res = reinterpret_cast(s); - return ec; + ErrorOr s = getSymbol(index); + if (std::error_code EC = s.getError()) + return EC; + Res = reinterpret_cast(s->getRawPtr()); + return object_error::success; + } + std::error_code getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const; + + ArrayRef getSymbolAuxData(COFFSymbolRef Symbol) const; + + size_t getSymbolTableEntrySize() const { + if (COFFHeader) + return sizeof(coff_symbol16); + if (COFFBigObjHeader) + return sizeof(coff_symbol32); + llvm_unreachable("null symbol table pointer!"); } - std::error_code getSymbolName(const coff_symbol *symbol, - StringRef &Res) const; - ArrayRef getSymbolAuxData(const coff_symbol *symbol) const; std::error_code getSectionName(const coff_section *Sec, StringRef &Res) const; + uint64_t getSectionSize(const coff_section *Sec) const; std::error_code getSectionContents(const coff_section *Sec, ArrayRef &Res) const; @@ -470,6 +716,9 @@ public: std::error_code getHintName(uint32_t Rva, uint16_t &Hint, StringRef &Name) const; + bool isRelocatableObject() const override; + bool is64() const { return PE32PlusHeader; } + static inline bool classof(const Binary *v) { return v->isCOFF(); } }; @@ -483,7 +732,14 @@ public: bool operator==(const ImportDirectoryEntryRef &Other) const; void moveNext(); + + imported_symbol_iterator imported_symbol_begin() const; + imported_symbol_iterator imported_symbol_end() const; + iterator_range imported_symbols() const; + std::error_code getName(StringRef &Result) const; + std::error_code getImportLookupTableRVA(uint32_t &Result) const; + std::error_code getImportAddressTableRVA(uint32_t &Result) const; std::error_code getImportTableEntry(const import_directory_table_entry *&Result) const; @@ -497,6 +753,31 @@ private: const COFFObjectFile *OwningObject; }; +class DelayImportDirectoryEntryRef { +public: + DelayImportDirectoryEntryRef() : OwningObject(nullptr) {} + DelayImportDirectoryEntryRef(const delay_import_directory_table_entry *T, + uint32_t I, const COFFObjectFile *Owner) + : Table(T), Index(I), OwningObject(Owner) {} + + bool operator==(const DelayImportDirectoryEntryRef &Other) const; + void moveNext(); + + imported_symbol_iterator imported_symbol_begin() const; + imported_symbol_iterator imported_symbol_end() const; + iterator_range imported_symbols() const; + + std::error_code getName(StringRef &Result) const; + std::error_code getDelayImportTable( + const delay_import_directory_table_entry *&Result) const; + std::error_code getImportAddress(int AddrIndex, uint64_t &Result) const; + +private: + const delay_import_directory_table_entry *Table; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + // The iterator for the export directory table entry. class ExportDirectoryEntryRef { public: @@ -519,6 +800,49 @@ private: uint32_t Index; const COFFObjectFile *OwningObject; }; + +class ImportedSymbolRef { +public: + ImportedSymbolRef() : OwningObject(nullptr) {} + ImportedSymbolRef(const import_lookup_table_entry32 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(Entry), Entry64(nullptr), Index(I), OwningObject(Owner) {} + ImportedSymbolRef(const import_lookup_table_entry64 *Entry, uint32_t I, + const COFFObjectFile *Owner) + : Entry32(nullptr), Entry64(Entry), Index(I), OwningObject(Owner) {} + + bool operator==(const ImportedSymbolRef &Other) const; + void moveNext(); + + std::error_code getSymbolName(StringRef &Result) const; + std::error_code getOrdinal(uint16_t &Result) const; + +private: + const import_lookup_table_entry32 *Entry32; + const import_lookup_table_entry64 *Entry64; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + +class BaseRelocRef { +public: + BaseRelocRef() : OwningObject(nullptr) {} + BaseRelocRef(const coff_base_reloc_block_header *Header, + const COFFObjectFile *Owner) + : Header(Header), Index(0), OwningObject(Owner) {} + + bool operator==(const BaseRelocRef &Other) const; + void moveNext(); + + std::error_code getType(uint8_t &Type) const; + std::error_code getRVA(uint32_t &Result) const; + +private: + const coff_base_reloc_block_header *Header; + uint32_t Index; + const COFFObjectFile *OwningObject; +}; + } // end namespace object } // end namespace llvm diff --git a/include/llvm/Object/COFFYAML.h b/include/llvm/Object/COFFYAML.h index 4aba08f..12a2522 100644 --- a/include/llvm/Object/COFFYAML.h +++ b/include/llvm/Object/COFFYAML.h @@ -31,6 +31,12 @@ inline SectionCharacteristics operator|(SectionCharacteristics a, uint32_t Ret = static_cast(a) | static_cast(b); return static_cast(Ret); } + +inline DLLCharacteristics operator|(DLLCharacteristics a, + DLLCharacteristics b) { + uint16_t Ret = static_cast(a) | static_cast(b); + return static_cast(Ret); +} } // The structure of the yaml files is not an exact 1:1 match to COFF. In order @@ -69,7 +75,13 @@ namespace COFFYAML { Symbol(); }; + struct PEHeader { + COFF::PE32Header Header; + Optional DataDirectories[COFF::NUM_DATA_DIRECTORIES]; + }; + struct Object { + Optional OptionalHeader; COFF::header Header; std::vector
Sections; std::vector Symbols; @@ -131,6 +143,11 @@ struct ScalarEnumerationTraits { }; template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, COFF::WindowsSubsystem &Value); +}; + +template <> struct ScalarBitSetTraits { static void bitset(IO &IO, COFF::Characteristics &Value); }; @@ -141,11 +158,26 @@ struct ScalarBitSetTraits { }; template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, COFF::DLLCharacteristics &Value); +}; + +template <> struct MappingTraits { static void mapping(IO &IO, COFFYAML::Relocation &Rel); }; template <> +struct MappingTraits { + static void mapping(IO &IO, COFFYAML::PEHeader &PH); +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, COFF::DataDirectory &DD); +}; + +template <> struct MappingTraits { static void mapping(IO &IO, COFF::header &H); }; diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index fbc48e6..7c10bbf 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -540,7 +540,7 @@ ELFFile::getSectionContents(const Elf_Shdr *Sec) const { if (Sec->sh_offset + Sec->sh_size > Buf.size()) return object_error::parse_failed; const uint8_t *Start = base() + Sec->sh_offset; - return ArrayRef(Start, Sec->sh_size); + return makeArrayRef(Start, Sec->sh_size); } template diff --git a/include/llvm/Object/ELFObjectFile.h b/include/llvm/Object/ELFObjectFile.h index 069f381..c2d6438 100644 --- a/include/llvm/Object/ELFObjectFile.h +++ b/include/llvm/Object/ELFObjectFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_ELF_OBJECT_FILE_H -#define LLVM_OBJECT_ELF_OBJECT_FILE_H +#ifndef LLVM_OBJECT_ELFOBJECTFILE_H +#define LLVM_OBJECT_ELFOBJECTFILE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" @@ -35,8 +35,26 @@ namespace llvm { namespace object { -template -class ELFObjectFile : public ObjectFile { +class ELFObjectFileBase : public ObjectFile { +protected: + ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source); + +public: + virtual std::error_code getRelocationAddend(DataRefImpl Rel, + int64_t &Res) const = 0; + virtual std::pair + getELFDynamicSymbolIterators() const = 0; + + virtual std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, + bool &IsDefault) const = 0; + + virtual uint64_t getSectionFlags(SectionRef Sec) const = 0; + virtual uint32_t getSectionType(SectionRef Sec) const = 0; + + static inline bool classof(const Binary *v) { return v->isELF(); } +}; + +template class ELFObjectFile : public ELFObjectFileBase { public: LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) @@ -71,32 +89,19 @@ protected: std::error_code getSymbolSection(DataRefImpl Symb, section_iterator &Res) const override; - std::error_code getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const override; - std::error_code getLibraryPath(DataRefImpl Data, - StringRef &Res) const override; - void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const override; - std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; section_iterator getRelocatedSection(DataRefImpl Sec) const override; @@ -178,7 +183,7 @@ protected: bool isDyldELFObject; public: - ELFObjectFile(std::unique_ptr Object, std::error_code &EC); + ELFObjectFile(MemoryBufferRef Object, std::error_code &EC); const Elf_Sym *getSymbol(DataRefImpl Symb) const; @@ -191,17 +196,18 @@ public: section_iterator section_begin() const override; section_iterator section_end() const override; - library_iterator needed_library_begin() const override; - library_iterator needed_library_end() const override; - - std::error_code getRelocationAddend(DataRefImpl Rel, int64_t &Res) const; + std::error_code getRelocationAddend(DataRefImpl Rel, + int64_t &Res) const override; std::error_code getSymbolVersion(SymbolRef Symb, StringRef &Version, - bool &IsDefault) const; + bool &IsDefault) const override; + + uint64_t getSectionFlags(SectionRef Sec) const override; + uint32_t getSectionType(SectionRef Sec) const override; uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - StringRef getLoadName() const override; + StringRef getLoadName() const; std::error_code getPlatformFlags(unsigned &Result) const override { Result = EF.getHeader()->e_flags; @@ -215,6 +221,11 @@ public: return v->getType() == getELFType(ELFT::TargetEndianness == support::little, ELFT::Is64Bits); } + + std::pair + getELFDynamicSymbolIterators() const override; + + bool isRelocatableObject() const override; }; // Use an alignment of 2 for the typedefs since that is the worst case for @@ -254,6 +265,18 @@ std::error_code ELFObjectFile::getSymbolVersion(SymbolRef SymRef, } template +uint64_t ELFObjectFile::getSectionFlags(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_flags; +} + +template +uint32_t ELFObjectFile::getSectionType(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + return toELFShdrIter(DRI)->sh_type; +} + +template std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, uint64_t &Result) const { const Elf_Sym *ESym = getSymbol(Symb); @@ -272,8 +295,9 @@ std::error_code ELFObjectFile::getSymbolAddress(DataRefImpl Symb, const Elf_Ehdr *Header = EF.getHeader(); Result = ESym->st_value; - // Clear the ARM/Thumb indicator flag. - if (Header->e_machine == ELF::EM_ARM && ESym->getType() == ELF::STT_FUNC) + // Clear the ARM/Thumb or microMIPS indicator flag. + if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && + ESym->getType() == ELF::STT_FUNC) Result &= ~1; if (Header->e_type == ELF::ET_REL) @@ -400,17 +424,13 @@ std::error_code ELFObjectFile::getSectionName(DataRefImpl Sec, } template -std::error_code ELFObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_addr; - return object_error::success; +uint64_t ELFObjectFile::getSectionAddress(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_addr; } template -std::error_code ELFObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_size; - return object_error::success; +uint64_t ELFObjectFile::getSectionSize(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_size; } template @@ -423,79 +443,43 @@ ELFObjectFile::getSectionContents(DataRefImpl Sec, } template -std::error_code -ELFObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Result) const { - Result = toELFShdrIter(Sec)->sh_addralign; - return object_error::success; +uint64_t ELFObjectFile::getSectionAlignment(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_addralign; } template -std::error_code ELFObjectFile::isSectionText(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; - return object_error::success; +bool ELFObjectFile::isSectionText(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_flags & ELF::SHF_EXECINSTR; } template -std::error_code ELFObjectFile::isSectionData(DataRefImpl Sec, - bool &Result) const { +bool ELFObjectFile::isSectionData(DataRefImpl Sec) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && - EShdr->sh_type == ELF::SHT_PROGBITS; - return object_error::success; + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_PROGBITS; } template -std::error_code ELFObjectFile::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +bool ELFObjectFile::isSectionBSS(DataRefImpl Sec) const { Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - Result = EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && - EShdr->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -template -std::error_code -ELFObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_flags & ELF::SHF_ALLOC; - return object_error::success; + return EShdr->sh_flags & (ELF::SHF_ALLOC | ELF::SHF_WRITE) && + EShdr->sh_type == ELF::SHT_NOBITS; } template -std::error_code ELFObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; - return object_error::success; +bool ELFObjectFile::isSectionVirtual(DataRefImpl Sec) const { + return toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; } template -std::error_code ELFObjectFile::isSectionZeroInit(DataRefImpl Sec, - bool &Result) const { - Result = toELFShdrIter(Sec)->sh_type == ELF::SHT_NOBITS; - return object_error::success; -} - -template -std::error_code ELFObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { - Elf_Shdr_Iter EShdr = toELFShdrIter(Sec); - Result = !(EShdr->sh_flags & (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); - return object_error::success; -} - -template -std::error_code ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +bool ELFObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb) const { Elf_Sym_Iter ESym = toELFSymIter(Symb); uintX_t Index = ESym->st_shndx; bool Reserved = Index >= ELF::SHN_LORESERVE && Index <= ELF::SHN_HIRESERVE; - Result = !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); - return object_error::success; + return !Reserved && (&*toELFShdrIter(Sec) == EF.getSection(ESym->st_shndx)); } template @@ -754,6 +738,7 @@ std::error_code ELFObjectFile::getRelocationValueString( Result.append(fmtbuf.begin(), fmtbuf.end()); break; } + case ELF::EM_386: case ELF::EM_ARM: case ELF::EM_HEXAGON: case ELF::EM_MIPS: @@ -786,13 +771,13 @@ ELFObjectFile::getRela(DataRefImpl Rela) const { } template -ELFObjectFile::ELFObjectFile(std::unique_ptr Object, - std::error_code &EC) - : ObjectFile(getELFType(static_cast(ELFT::TargetEndianness) == - support::little, - ELFT::Is64Bits), - std::move(Object)), - EF(Data->getBuffer(), EC) {} +ELFObjectFile::ELFObjectFile(MemoryBufferRef Object, std::error_code &EC) + : ELFObjectFileBase( + getELFType(static_cast(ELFT::TargetEndianness) == + support::little, + ELFT::Is64Bits), + Object), + EF(Data.getBuffer(), EC) {} template basic_symbol_iterator ELFObjectFile::symbol_begin_impl() const { @@ -838,50 +823,13 @@ StringRef ELFObjectFile::getLoadName() const { } template -library_iterator ELFObjectFile::needed_library_begin() const { - Elf_Dyn_Iter DI = EF.begin_dynamic_table(); - Elf_Dyn_Iter DE = EF.end_dynamic_table(); - - while (DI != DE && DI->getTag() != ELF::DT_SONAME) - ++DI; - - return library_iterator(LibraryRef(toDRI(DI), this)); -} - -template -std::error_code ELFObjectFile::getLibraryNext(DataRefImpl Data, - LibraryRef &Result) const { - Elf_Dyn_Iter DI = toELFDynIter(Data); - Elf_Dyn_Iter DE = EF.end_dynamic_table(); - - // Skip to the next DT_NEEDED entry. - do - ++DI; - while (DI != DE && DI->getTag() != ELF::DT_NEEDED); - - Result = LibraryRef(toDRI(DI), this); - return object_error::success; -} - -template -std::error_code ELFObjectFile::getLibraryPath(DataRefImpl Data, - StringRef &Res) const { - Res = EF.getDynamicString(toELFDynIter(Data)->getVal()); - return object_error::success; -} - -template -library_iterator ELFObjectFile::needed_library_end() const { - return library_iterator(LibraryRef(toDRI(EF.end_dynamic_table()), this)); -} - -template uint8_t ELFObjectFile::getBytesInAddress() const { return ELFT::Is64Bits ? 8 : 4; } template StringRef ELFObjectFile::getFileFormatName() const { + bool IsLittleEndian = ELFT::TargetEndianness == support::little; switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: switch (EF.getHeader()->e_machine) { @@ -890,7 +838,7 @@ StringRef ELFObjectFile::getFileFormatName() const { case ELF::EM_X86_64: return "ELF32-x86-64"; case ELF::EM_ARM: - return "ELF32-arm"; + return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big"); case ELF::EM_HEXAGON: return "ELF32-hexagon"; case ELF::EM_MIPS: @@ -910,7 +858,7 @@ StringRef ELFObjectFile::getFileFormatName() const { case ELF::EM_X86_64: return "ELF64-x86-64"; case ELF::EM_AARCH64: - return "ELF64-aarch64"; + return (IsLittleEndian ? "ELF64-aarch64-little" : "ELF64-aarch64-big"); case ELF::EM_PPC64: return "ELF64-ppc64"; case ELF::EM_S390: @@ -951,6 +899,8 @@ unsigned ELFObjectFile::getArch() const { default: report_fatal_error("Invalid ELFCLASS!"); } + case ELF::EM_PPC: + return Triple::ppc; case ELF::EM_PPC64: return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: @@ -967,73 +917,34 @@ unsigned ELFObjectFile::getArch() const { } } -/// FIXME: Maybe we should have a base ElfObjectFile that is not a template -/// and make these member functions? +template +std::pair +ELFObjectFile::getELFDynamicSymbolIterators() const { + return std::make_pair(dynamic_symbol_begin(), dynamic_symbol_end()); +} + +template bool ELFObjectFile::isRelocatableObject() const { + return EF.getHeader()->e_type == ELF::ET_REL; +} + inline std::error_code getELFRelocationAddend(const RelocationRef R, int64_t &Addend) { const ObjectFile *Obj = R.getObjectFile(); DataRefImpl DRI = R.getRawDataRefImpl(); - // Little-endian 32-bit - if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getRelocationAddend(DRI, Addend); - - llvm_unreachable("Object passed to getELFRelocationAddend() is not ELF"); + return cast(Obj)->getRelocationAddend(DRI, Addend); } inline std::pair -getELFDynamicSymbolIterators(SymbolicFile *Obj) { - if (const ELF32LEObjectFile *ELF = dyn_cast(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - if (const ELF64LEObjectFile *ELF = dyn_cast(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - if (const ELF32BEObjectFile *ELF = dyn_cast(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - if (const ELF64BEObjectFile *ELF = cast(Obj)) - return std::make_pair(ELF->dynamic_symbol_begin(), - ELF->dynamic_symbol_end()); - - llvm_unreachable( - "Object passed to getELFDynamicSymbolIterators() is not ELF"); +getELFDynamicSymbolIterators(const SymbolicFile *Obj) { + return cast(Obj)->getELFDynamicSymbolIterators(); } -/// This is a generic interface for retrieving GNU symbol version -/// information from an ELFObjectFile. inline std::error_code GetELFSymbolVersion(const ObjectFile *Obj, const SymbolRef &Sym, StringRef &Version, bool &IsDefault) { - // Little-endian 32-bit - if (const ELF32LEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 32-bit - if (const ELF32BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Little-endian 64-bit - if (const ELF64LEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - // Big-endian 64-bit - if (const ELF64BEObjectFile *ELFObj = dyn_cast(Obj)) - return ELFObj->getSymbolVersion(Sym, Version, IsDefault); - - llvm_unreachable("Object passed to GetELFSymbolVersion() is not ELF"); + return cast(Obj) + ->getSymbolVersion(Sym, Version, IsDefault); } } } diff --git a/include/llvm/Object/ELFTypes.h b/include/llvm/Object/ELFTypes.h index 84b6031..4bc0c7c 100644 --- a/include/llvm/Object/ELFTypes.h +++ b/include/llvm/Object/ELFTypes.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_ELF_TYPES_H -#define LLVM_OBJECT_ELF_TYPES_H +#ifndef LLVM_OBJECT_ELFTYPES_H +#define LLVM_OBJECT_ELFTYPES_H #include "llvm/Support/AlignOf.h" #include "llvm/Support/DataTypes.h" @@ -176,6 +176,7 @@ struct Elf_Sym_Base > { template struct Elf_Sym_Impl : Elf_Sym_Base { using Elf_Sym_Base::st_info; + using Elf_Sym_Base::st_other; // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: @@ -186,6 +187,9 @@ struct Elf_Sym_Impl : Elf_Sym_Base { void setBindingAndType(unsigned char b, unsigned char t) { st_info = (b << 4) + (t & 0x0f); } + + /// Access to the STV_xxx flag stored in the first two bits of st_other. + unsigned char getVisibility() const { return st_other & 0x3; } }; /// Elf_Versym: This is the structure of entries in the SHT_GNU_versym section diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index fc8cc95..b71946d 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -40,11 +40,12 @@ LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_EF) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) -LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_REL) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_REL) // Just use 64, since it can hold 32-bit values too. LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STV) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STO) // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. @@ -63,7 +64,7 @@ struct Symbol { StringRef Section; llvm::yaml::Hex64 Value; llvm::yaml::Hex64 Size; - ELF_STV Visibility; + uint8_t Other; }; struct LocalGlobalWeakSymbols { std::vector Local; @@ -175,6 +176,11 @@ struct ScalarEnumerationTraits { }; template <> +struct ScalarBitSetTraits { + static void bitset(IO &IO, ELFYAML::ELF_STO &Value); +}; + +template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, ELFYAML::ELF_REL &Value); }; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index 701da12..90c2bd7 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -26,7 +26,8 @@ enum class object_error { arch_not_found, invalid_file_type, parse_failed, - unexpected_eof + unexpected_eof, + bitcode_section_not_found, }; inline std::error_code make_error_code(object_error e) { diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index b33cc26..74f4666 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_IR_OBJECT_FILE_H -#define LLVM_OBJECT_IR_OBJECT_FILE_H +#ifndef LLVM_OBJECT_IROBJECTFILE_H +#define LLVM_OBJECT_IROBJECTFILE_H #include "llvm/Object/SymbolicFile.h" @@ -22,19 +22,24 @@ class Module; class GlobalValue; namespace object { +class ObjectFile; + class IRObjectFile : public SymbolicFile { std::unique_ptr M; std::unique_ptr Mang; std::vector> AsmSymbols; public: - IRObjectFile(std::unique_ptr Object, std::unique_ptr M); + IRObjectFile(MemoryBufferRef Object, std::unique_ptr M); ~IRObjectFile(); void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; uint32_t getSymbolFlags(DataRefImpl Symb) const override; - const GlobalValue *getSymbolGV(DataRefImpl Symb) const; + GlobalValue *getSymbolGV(DataRefImpl Symb); + const GlobalValue *getSymbolGV(DataRefImpl Symb) const { + return const_cast(this)->getSymbolGV(Symb); + } basic_symbol_iterator symbol_begin_impl() const override; basic_symbol_iterator symbol_end_impl() const override; @@ -44,14 +49,24 @@ public: Module &getModule() { return *M; } + std::unique_ptr takeModule(); static inline bool classof(const Binary *v) { return v->isIR(); } - static ErrorOr - createIRObjectFile(std::unique_ptr Object, - LLVMContext &Context); + /// \brief Finds and returns bitcode embedded in the given object file, or an + /// error code if not found. + static ErrorOr findBitcodeInObject(const ObjectFile &Obj); + + /// \brief Finds and returns bitcode in the given memory buffer (which may + /// be either a bitcode file or a native object file with embedded bitcode), + /// or an error code if not found. + static ErrorOr + findBitcodeInMemBuffer(MemoryBufferRef Object); + + static ErrorOr> create(MemoryBufferRef Object, + LLVMContext &Context); }; } } diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 4835eb8..bee1f6c 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -49,6 +49,141 @@ public: }; typedef content_iterator dice_iterator; +/// ExportEntry encapsulates the current-state-of-the-walk used when doing a +/// non-recursive walk of the trie data structure. This allows you to iterate +/// across all exported symbols using: +/// for (const llvm::object::ExportEntry &AnExport : Obj->exports()) { +/// } +class ExportEntry { +public: + ExportEntry(ArrayRef Trie); + + StringRef name() const; + uint64_t flags() const; + uint64_t address() const; + uint64_t other() const; + StringRef otherName() const; + uint32_t nodeOffset() const; + + bool operator==(const ExportEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(const uint8_t *&p); + void pushDownUntilBottom(); + void pushNode(uint64_t Offset); + + // Represents a node in the mach-o exports trie. + struct NodeState { + NodeState(const uint8_t *Ptr); + const uint8_t *Start; + const uint8_t *Current; + uint64_t Flags; + uint64_t Address; + uint64_t Other; + const char *ImportName; + unsigned ChildCount; + unsigned NextChildIndex; + unsigned ParentStringLength; + bool IsExportNode; + }; + + ArrayRef Trie; + SmallString<256> CumulativeString; + SmallVector Stack; + bool Malformed; + bool Done; +}; +typedef content_iterator export_iterator; + +/// MachORebaseEntry encapsulates the current state in the decompression of +/// rebasing opcodes. This allows you to iterate through the compressed table of +/// rebasing using: +/// for (const llvm::object::MachORebaseEntry &Entry : Obj->rebaseTable()) { +/// } +class MachORebaseEntry { +public: + MachORebaseEntry(ArrayRef opcodes, bool is64Bit); + + uint32_t segmentIndex() const; + uint64_t segmentOffset() const; + StringRef typeName() const; + + bool operator==(const MachORebaseEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(); + + ArrayRef Opcodes; + const uint8_t *Ptr; + uint64_t SegmentOffset; + uint32_t SegmentIndex; + uint64_t RemainingLoopCount; + uint64_t AdvanceAmount; + uint8_t RebaseType; + uint8_t PointerSize; + bool Malformed; + bool Done; +}; +typedef content_iterator rebase_iterator; + +/// MachOBindEntry encapsulates the current state in the decompression of +/// binding opcodes. This allows you to iterate through the compressed table of +/// bindings using: +/// for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) { +/// } +class MachOBindEntry { +public: + enum class Kind { Regular, Lazy, Weak }; + + MachOBindEntry(ArrayRef Opcodes, bool is64Bit, MachOBindEntry::Kind); + + uint32_t segmentIndex() const; + uint64_t segmentOffset() const; + StringRef typeName() const; + StringRef symbolName() const; + uint32_t flags() const; + int64_t addend() const; + int ordinal() const; + + bool operator==(const MachOBindEntry &) const; + + void moveNext(); + +private: + friend class MachOObjectFile; + void moveToFirst(); + void moveToEnd(); + uint64_t readULEB128(); + int64_t readSLEB128(); + + ArrayRef Opcodes; + const uint8_t *Ptr; + uint64_t SegmentOffset; + uint32_t SegmentIndex; + StringRef SymbolName; + int Ordinal; + uint32_t Flags; + int64_t Addend; + uint64_t RemainingLoopCount; + uint64_t AdvanceAmount; + uint8_t BindType; + uint8_t PointerSize; + Kind TableKind; + bool Malformed; + bool Done; +}; +typedef content_iterator bind_iterator; + class MachOObjectFile : public ObjectFile { public: struct LoadCommandInfo { @@ -56,8 +191,8 @@ public: MachO::load_command C; // The command itself. }; - MachOObjectFile(std::unique_ptr Object, bool IsLittleEndian, - bool Is64Bits, std::error_code &EC); + MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, bool Is64Bits, + std::error_code &EC); void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code getSymbolName(DataRefImpl Symb, @@ -65,6 +200,7 @@ public: // MachO specific. std::error_code getIndirectName(DataRefImpl Symb, StringRef &Res) const; + unsigned getSectionType(SectionRef Sec) const; std::error_code getSymbolAddress(DataRefImpl Symb, uint64_t &Res) const override; @@ -80,24 +216,16 @@ public: void moveSectionNext(DataRefImpl &Sec) const override; std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code getSectionSize(DataRefImpl Sec, uint64_t &Res) const override; + uint64_t getSectionAddress(DataRefImpl Sec) const override; + uint64_t getSectionSize(DataRefImpl Sec) const override; std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const override; - std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const override; - std::error_code isSectionText(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionData(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const override; - std::error_code isSectionVirtual(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionZeroInit(DataRefImpl Sec, bool &Res) const override; - std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const override; - std::error_code sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb, - bool &Result) const override; + uint64_t getSectionAlignment(DataRefImpl Sec) const override; + bool isSectionText(DataRefImpl Sec) const override; + bool isSectionData(DataRefImpl Sec) const override; + bool isSectionBSS(DataRefImpl Sec) const override; + bool isSectionVirtual(DataRefImpl Sec) const override; + bool sectionContainsSymbol(DataRefImpl Sec, DataRefImpl Symb) const override; relocation_iterator section_rel_begin(DataRefImpl Sec) const override; relocation_iterator section_rel_end(DataRefImpl Sec) const override; @@ -118,13 +246,8 @@ public: std::error_code getRelocationHidden(DataRefImpl Rel, bool &Result) const override; - std::error_code getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const override; - std::error_code getLibraryPath(DataRefImpl LibData, - StringRef &Res) const override; - // MachO specific. - std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &Res); + std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const; // TODO: Would be useful to have an iterator based version // of the load command interface too. @@ -138,21 +261,45 @@ public: section_iterator section_begin() const override; section_iterator section_end() const override; - library_iterator needed_library_begin() const override; - library_iterator needed_library_end() const override; - uint8_t getBytesInAddress() const override; StringRef getFileFormatName() const override; unsigned getArch() const override; - - StringRef getLoadName() const override; + Triple getArch(const char **McpuDefault, Triple *ThumbTriple) const; relocation_iterator section_rel_begin(unsigned Index) const; relocation_iterator section_rel_end(unsigned Index) const; dice_iterator begin_dices() const; dice_iterator end_dices() const; + + /// For use iterating over all exported symbols. + iterator_range exports() const; + + /// For use examining a trie not in a MachOObjectFile. + static iterator_range exports(ArrayRef Trie); + + /// For use iterating over all rebase table entries. + iterator_range rebaseTable() const; + + /// For use examining rebase opcodes not in a MachOObjectFile. + static iterator_range rebaseTable(ArrayRef Opcodes, + bool is64); + + /// For use iterating over all bind table entries. + iterator_range bindTable() const; + + /// For use iterating over all lazy bind table entries. + iterator_range lazyBindTable() const; + + /// For use iterating over all lazy bind table entries. + iterator_range weakBindTable() const; + + /// For use examining bind opcodes not in a MachOObjectFile. + static iterator_range bindTable(ArrayRef Opcodes, + bool is64, + MachOBindEntry::Kind); + // In a MachO file, sections have a segment name. This is used in the .o // files. They have a single segment, but this field specifies which segment @@ -173,6 +320,8 @@ public: const MachO::any_relocation_info &RE) const; uint32_t getScatteredRelocationValue( const MachO::any_relocation_info &RE) const; + uint32_t getScatteredRelocationType( + const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationAddress(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationPCRel(const MachO::any_relocation_info &RE) const; unsigned getAnyRelocationLength(const MachO::any_relocation_info &RE) const; @@ -197,12 +346,42 @@ public: getSegmentLoadCommand(const LoadCommandInfo &L) const; MachO::segment_command_64 getSegment64LoadCommand(const LoadCommandInfo &L) const; - MachO::linker_options_command - getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const; + MachO::linker_option_command + getLinkerOptionLoadCommand(const LoadCommandInfo &L) const; MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const; MachO::dylib_command getDylibIDLoadCommand(const LoadCommandInfo &L) const; + MachO::dyld_info_command + getDyldInfoLoadCommand(const LoadCommandInfo &L) const; + MachO::dylinker_command + getDylinkerCommand(const LoadCommandInfo &L) const; + MachO::uuid_command + getUuidCommand(const LoadCommandInfo &L) const; + MachO::rpath_command + getRpathCommand(const LoadCommandInfo &L) const; + MachO::source_version_command + getSourceVersionCommand(const LoadCommandInfo &L) const; + MachO::entry_point_command + getEntryPointCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command + getEncryptionInfoCommand(const LoadCommandInfo &L) const; + MachO::encryption_info_command_64 + getEncryptionInfoCommand64(const LoadCommandInfo &L) const; + MachO::sub_framework_command + getSubFrameworkCommand(const LoadCommandInfo &L) const; + MachO::sub_umbrella_command + getSubUmbrellaCommand(const LoadCommandInfo &L) const; + MachO::sub_library_command + getSubLibraryCommand(const LoadCommandInfo &L) const; + MachO::sub_client_command + getSubClientCommand(const LoadCommandInfo &L) const; + MachO::routines_command + getRoutinesCommand(const LoadCommandInfo &L) const; + MachO::routines_command_64 + getRoutinesCommand64(const LoadCommandInfo &L) const; + MachO::thread_command + getThreadCommand(const LoadCommandInfo &L) const; MachO::any_relocation_info getRelocation(DataRefImpl Rel) const; MachO::data_in_code_entry getDice(DataRefImpl Rel) const; @@ -216,6 +395,12 @@ public: MachO::symtab_command getSymtabLoadCommand() const; MachO::dysymtab_command getDysymtabLoadCommand() const; MachO::linkedit_data_command getDataInCodeLoadCommand() const; + ArrayRef getDyldInfoRebaseOpcodes() const; + ArrayRef getDyldInfoBindOpcodes() const; + ArrayRef getDyldInfoWeakBindOpcodes() const; + ArrayRef getDyldInfoLazyBindOpcodes() const; + ArrayRef getDyldInfoExportsTrie() const; + ArrayRef getUuid() const; StringRef getStringTableData() const; bool is64Bit() const; @@ -225,10 +410,19 @@ public: StringRef &Suffix); static Triple::ArchType getArch(uint32_t CPUType); - static Triple getArch(uint32_t CPUType, uint32_t CPUSubType); - static Triple getArch(StringRef ArchFlag); + static Triple getArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault = nullptr); + static Triple getThumbArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault = nullptr); + static Triple getArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault, Triple *ThumbTriple); + static bool isValidArch(StringRef ArchFlag); static Triple getHostArch(); + bool isRelocatableObject() const override; + + bool hasPageZeroSegment() const { return HasPageZeroSegment; } + static bool classof(const Binary *v) { return v->isMachO(); } @@ -239,10 +433,13 @@ private: typedef SmallVector LibraryList; LibraryList Libraries; typedef SmallVector LibraryShortName; - LibraryShortName LibrariesShortNames; + mutable LibraryShortName LibrariesShortNames; const char *SymtabLoadCmd; const char *DysymtabLoadCmd; const char *DataInCodeLoadCmd; + const char *DyldInfoLoadCmd; + const char *UuidLoadCmd; + bool HasPageZeroSegment; }; /// DiceRef diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h index e6677f5..93f6654 100644 --- a/include/llvm/Object/MachOUniversal.h +++ b/include/llvm/Object/MachOUniversal.h @@ -16,8 +16,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/Object/Binary.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" #include "llvm/Object/MachO.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MachO.h" @@ -25,8 +25,6 @@ namespace llvm { namespace object { -class ObjectFile; - class MachOUniversalBinary : public Binary { virtual void anchor(); @@ -53,14 +51,18 @@ public: ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } uint32_t getCPUType() const { return Header.cputype; } + uint32_t getCPUSubType() const { return Header.cpusubtype; } + uint32_t getOffset() const { return Header.offset; } + uint32_t getSize() const { return Header.size; } + uint32_t getAlign() const { return Header.align; } std::string getArchTypeName() const { Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype); return T.getArchName(); } - ErrorOr> getAsObjectFile() const; + ErrorOr> getAsObjectFile() const; - std::error_code getAsArchive(std::unique_ptr &Result) const; + ErrorOr> getAsArchive() const; }; class object_iterator { @@ -84,10 +86,9 @@ public: } }; - MachOUniversalBinary(std::unique_ptr Source, - std::error_code &ec); - static ErrorOr - create(std::unique_ptr Source); + MachOUniversalBinary(MemoryBufferRef Souce, std::error_code &EC); + static ErrorOr> + create(MemoryBufferRef Source); object_iterator begin_objects() const { return ObjectForArch(this, 0); @@ -103,7 +104,7 @@ public: return V->isMachOUniversalBinary(); } - ErrorOr> + ErrorOr> getObjectForArch(Triple::ArchType Arch) const; }; diff --git a/include/llvm/Object/ObjectFile.h b/include/llvm/Object/ObjectFile.h index a4370a3..6aa985d 100644 --- a/include/llvm/Object/ObjectFile.h +++ b/include/llvm/Object/ObjectFile.h @@ -27,6 +27,8 @@ namespace llvm { namespace object { class ObjectFile; +class COFFObjectFile; +class MachOObjectFile; class SymbolRef; class symbol_iterator; @@ -93,23 +95,19 @@ public: void moveNext(); std::error_code getName(StringRef &Result) const; - std::error_code getAddress(uint64_t &Result) const; - std::error_code getSize(uint64_t &Result) const; + uint64_t getAddress() const; + uint64_t getSize() const; std::error_code getContents(StringRef &Result) const; /// @brief Get the alignment of this section as the actual value (not log 2). - std::error_code getAlignment(uint64_t &Result) const; + uint64_t getAlignment() const; - // FIXME: Move to the normalization layer when it's created. - std::error_code isText(bool &Result) const; - std::error_code isData(bool &Result) const; - std::error_code isBSS(bool &Result) const; - std::error_code isRequiredForExecution(bool &Result) const; - std::error_code isVirtual(bool &Result) const; - std::error_code isZeroInit(bool &Result) const; - std::error_code isReadOnlyData(bool &Result) const; + bool isText() const; + bool isData() const; + bool isBSS() const; + bool isVirtual() const; - std::error_code containsSymbol(SymbolRef S, bool &Result) const; + bool containsSymbol(SymbolRef S) const; relocation_iterator relocation_begin() const; relocation_iterator relocation_end() const; @@ -120,6 +118,7 @@ public: section_iterator getRelocatedSection() const; DataRefImpl getRawDataRefImpl() const; + const ObjectFile *getObject() const; }; /// SymbolRef - This is a value type class that represents a single symbol in @@ -176,30 +175,6 @@ public: } }; -/// LibraryRef - This is a value type class that represents a single library in -/// the list of libraries needed by a shared or dynamic object. -class LibraryRef { - friend class SectionRef; - DataRefImpl LibraryPimpl; - const ObjectFile *OwningObject; - -public: - LibraryRef() : OwningObject(nullptr) { } - - LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner); - - bool operator==(const LibraryRef &Other) const; - bool operator<(const LibraryRef &Other) const; - - std::error_code getNext(LibraryRef &Result) const; - - // Get the path to this library, as stored in the object file. - std::error_code getPath(StringRef &Result) const; - - DataRefImpl getRawDataRefImpl() const; -}; -typedef content_iterator library_iterator; - /// ObjectFile - This class is the base class for all object file types. /// Concrete instances of this object are created by createObjectFile, which /// figures out which type to create. @@ -209,10 +184,10 @@ class ObjectFile : public SymbolicFile { ObjectFile(const ObjectFile &other) LLVM_DELETED_FUNCTION; protected: - ObjectFile(unsigned int Type, std::unique_ptr Source); + ObjectFile(unsigned int Type, MemoryBufferRef Source); const uint8_t *base() const { - return reinterpret_cast(Data->getBufferStart()); + return reinterpret_cast(Data.getBufferStart()); } // These functions are for SymbolRef to call internally. The main goal of @@ -248,29 +223,18 @@ protected: virtual void moveSectionNext(DataRefImpl &Sec) const = 0; virtual std::error_code getSectionName(DataRefImpl Sec, StringRef &Res) const = 0; - virtual std::error_code getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const = 0; - virtual std::error_code getSectionSize(DataRefImpl Sec, - uint64_t &Res) const = 0; + virtual uint64_t getSectionAddress(DataRefImpl Sec) const = 0; + virtual uint64_t getSectionSize(DataRefImpl Sec) const = 0; virtual std::error_code getSectionContents(DataRefImpl Sec, StringRef &Res) const = 0; - virtual std::error_code getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const = 0; - virtual std::error_code isSectionText(DataRefImpl Sec, bool &Res) const = 0; - virtual std::error_code isSectionData(DataRefImpl Sec, bool &Res) const = 0; - virtual std::error_code isSectionBSS(DataRefImpl Sec, bool &Res) const = 0; - virtual std::error_code isSectionRequiredForExecution(DataRefImpl Sec, - bool &Res) const = 0; + virtual uint64_t getSectionAlignment(DataRefImpl Sec) const = 0; + virtual bool isSectionText(DataRefImpl Sec) const = 0; + virtual bool isSectionData(DataRefImpl Sec) const = 0; + virtual bool isSectionBSS(DataRefImpl Sec) const = 0; // A section is 'virtual' if its contents aren't present in the object image. - virtual std::error_code isSectionVirtual(DataRefImpl Sec, - bool &Res) const = 0; - virtual std::error_code isSectionZeroInit(DataRefImpl Sec, - bool &Res) const = 0; - virtual std::error_code isSectionReadOnlyData(DataRefImpl Sec, - bool &Res) const = 0; - virtual std::error_code sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const = 0; + virtual bool isSectionVirtual(DataRefImpl Sec) const = 0; + virtual bool sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb) const = 0; virtual relocation_iterator section_rel_begin(DataRefImpl Sec) const = 0; virtual relocation_iterator section_rel_end(DataRefImpl Sec) const = 0; virtual section_iterator getRelocatedSection(DataRefImpl Sec) const; @@ -297,13 +261,6 @@ protected: return object_error::success; } - // Same for LibraryRef - friend class LibraryRef; - virtual std::error_code getLibraryNext(DataRefImpl Lib, - LibraryRef &Res) const = 0; - virtual std::error_code getLibraryPath(DataRefImpl Lib, - StringRef &Res) const = 0; - public: typedef iterator_range symbol_iterator_range; symbol_iterator_range symbols() const { @@ -318,9 +275,6 @@ public: return section_iterator_range(section_begin(), section_end()); } - virtual library_iterator needed_library_begin() const = 0; - virtual library_iterator needed_library_end() const = 0; - /// @brief The number of bytes used to represent an address in this object /// file format. virtual uint8_t getBytesInAddress() const = 0; @@ -328,27 +282,26 @@ public: virtual StringRef getFileFormatName() const = 0; virtual /* Triple::ArchType */ unsigned getArch() const = 0; - /// For shared objects, returns the name which this object should be - /// loaded from at runtime. This corresponds to DT_SONAME on ELF and - /// LC_ID_DYLIB (install name) on MachO. - virtual StringRef getLoadName() const = 0; - /// Returns platform-specific object flags, if any. virtual std::error_code getPlatformFlags(unsigned &Result) const { Result = 0; return object_error::invalid_file_type; } + /// True if this is a relocatable object (.o/.obj). + virtual bool isRelocatableObject() const = 0; + /// @returns Pointer to ObjectFile subclass to handle this type of object. /// @param ObjectPath The path to the object file. ObjectPath.isObject must /// return true. /// @brief Create ObjectFile from path. - static ErrorOr createObjectFile(StringRef ObjectPath); - static ErrorOr - createObjectFile(std::unique_ptr &Object, - sys::fs::file_magic Type); - static ErrorOr - createObjectFile(std::unique_ptr &Object) { + static ErrorOr> + createObjectFile(StringRef ObjectPath); + + static ErrorOr> + createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type); + static ErrorOr> + createObjectFile(MemoryBufferRef Object) { return createObjectFile(Object, sys::fs::file_magic::unknown); } @@ -357,13 +310,14 @@ public: return v->isObject(); } -public: - static ErrorOr - createCOFFObjectFile(std::unique_ptr Object); - static ErrorOr - createELFObjectFile(std::unique_ptr &Object); - static ErrorOr - createMachOObjectFile(std::unique_ptr &Object); + static ErrorOr> + createCOFFObjectFile(MemoryBufferRef Object); + + static ErrorOr> + createELFObjectFile(MemoryBufferRef Object); + + static ErrorOr> + createMachOObjectFile(MemoryBufferRef Object); }; // Inline function definitions. @@ -430,54 +384,41 @@ inline std::error_code SectionRef::getName(StringRef &Result) const { return OwningObject->getSectionName(SectionPimpl, Result); } -inline std::error_code SectionRef::getAddress(uint64_t &Result) const { - return OwningObject->getSectionAddress(SectionPimpl, Result); +inline uint64_t SectionRef::getAddress() const { + return OwningObject->getSectionAddress(SectionPimpl); } -inline std::error_code SectionRef::getSize(uint64_t &Result) const { - return OwningObject->getSectionSize(SectionPimpl, Result); +inline uint64_t SectionRef::getSize() const { + return OwningObject->getSectionSize(SectionPimpl); } inline std::error_code SectionRef::getContents(StringRef &Result) const { return OwningObject->getSectionContents(SectionPimpl, Result); } -inline std::error_code SectionRef::getAlignment(uint64_t &Result) const { - return OwningObject->getSectionAlignment(SectionPimpl, Result); +inline uint64_t SectionRef::getAlignment() const { + return OwningObject->getSectionAlignment(SectionPimpl); } -inline std::error_code SectionRef::isText(bool &Result) const { - return OwningObject->isSectionText(SectionPimpl, Result); +inline bool SectionRef::isText() const { + return OwningObject->isSectionText(SectionPimpl); } -inline std::error_code SectionRef::isData(bool &Result) const { - return OwningObject->isSectionData(SectionPimpl, Result); +inline bool SectionRef::isData() const { + return OwningObject->isSectionData(SectionPimpl); } -inline std::error_code SectionRef::isBSS(bool &Result) const { - return OwningObject->isSectionBSS(SectionPimpl, Result); +inline bool SectionRef::isBSS() const { + return OwningObject->isSectionBSS(SectionPimpl); } -inline std::error_code SectionRef::isRequiredForExecution(bool &Result) const { - return OwningObject->isSectionRequiredForExecution(SectionPimpl, Result); +inline bool SectionRef::isVirtual() const { + return OwningObject->isSectionVirtual(SectionPimpl); } -inline std::error_code SectionRef::isVirtual(bool &Result) const { - return OwningObject->isSectionVirtual(SectionPimpl, Result); -} - -inline std::error_code SectionRef::isZeroInit(bool &Result) const { - return OwningObject->isSectionZeroInit(SectionPimpl, Result); -} - -inline std::error_code SectionRef::isReadOnlyData(bool &Result) const { - return OwningObject->isSectionReadOnlyData(SectionPimpl, Result); -} - -inline std::error_code SectionRef::containsSymbol(SymbolRef S, - bool &Result) const { +inline bool SectionRef::containsSymbol(SymbolRef S) const { return OwningObject->sectionContainsSymbol(SectionPimpl, - S.getRawDataRefImpl(), Result); + S.getRawDataRefImpl()); } inline relocation_iterator SectionRef::relocation_begin() const { @@ -496,6 +437,10 @@ inline DataRefImpl SectionRef::getRawDataRefImpl() const { return SectionPimpl; } +inline const ObjectFile *SectionRef::getObject() const { + return OwningObject; +} + /// RelocationRef inline RelocationRef::RelocationRef(DataRefImpl RelocationP, const ObjectFile *Owner) @@ -548,26 +493,6 @@ inline const ObjectFile *RelocationRef::getObjectFile() const { return OwningObject; } -// Inline function definitions. -inline LibraryRef::LibraryRef(DataRefImpl LibraryP, const ObjectFile *Owner) - : LibraryPimpl(LibraryP) - , OwningObject(Owner) {} - -inline bool LibraryRef::operator==(const LibraryRef &Other) const { - return LibraryPimpl == Other.LibraryPimpl; -} - -inline bool LibraryRef::operator<(const LibraryRef &Other) const { - return LibraryPimpl < Other.LibraryPimpl; -} - -inline std::error_code LibraryRef::getNext(LibraryRef &Result) const { - return OwningObject->getLibraryNext(LibraryPimpl, Result); -} - -inline std::error_code LibraryRef::getPath(StringRef &Result) const { - return OwningObject->getLibraryPath(LibraryPimpl, Result); -} } // end namespace object } // end namespace llvm diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 5ca2450..91eafd5 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -17,6 +17,7 @@ #define LLVM_OBJECT_RELOCVISITOR_H #include "llvm/ADT/StringRef.h" +#include "llvm/Object/COFF.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Debug.h" @@ -40,22 +41,39 @@ struct RelocToApply { /// @brief Base class for object file relocation visitors. class RelocVisitor { public: - explicit RelocVisitor(StringRef FileFormat) - : FileFormat(FileFormat), HasError(false) {} + explicit RelocVisitor(const ObjectFile &Obj) + : ObjToVisit(Obj), HasError(false) {} // TODO: Should handle multiple applied relocations via either passing in the // previously computed value or just count paired relocations as a single // visit. - RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t SecAddr = 0, - uint64_t Value = 0) { - if (FileFormat == "ELF64-x86-64") { - switch (RelocType) { + RelocToApply visit(uint32_t RelocType, RelocationRef R, uint64_t Value = 0) { + if (isa(ObjToVisit)) + return visitELF(RelocType, R, Value); + if (isa(ObjToVisit)) + return visitCOFF(RelocType, R, Value); + + HasError = true; + return RelocToApply(); + } + + bool error() { return HasError; } + +private: + const ObjectFile &ObjToVisit; + bool HasError; + + RelocToApply visitELF(uint32_t RelocType, RelocationRef R, uint64_t Value) { + if (ObjToVisit.getBytesInAddress() == 8) { // 64-bit object file + switch (ObjToVisit.getArch()) { + case Triple::x86_64: + switch (RelocType) { case llvm::ELF::R_X86_64_NONE: return visitELF_X86_64_NONE(R); case llvm::ELF::R_X86_64_64: return visitELF_X86_64_64(R, Value); case llvm::ELF::R_X86_64_PC32: - return visitELF_X86_64_PC32(R, Value, SecAddr); + return visitELF_X86_64_PC32(R, Value); case llvm::ELF::R_X86_64_32: return visitELF_X86_64_32(R, Value); case llvm::ELF::R_X86_64_32S: @@ -63,116 +81,147 @@ public: default: HasError = true; return RelocToApply(); - } - } else if (FileFormat == "ELF32-i386") { - switch (RelocType) { - case llvm::ELF::R_386_NONE: - return visitELF_386_NONE(R); - case llvm::ELF::R_386_32: - return visitELF_386_32(R, Value); - case llvm::ELF::R_386_PC32: - return visitELF_386_PC32(R, Value, SecAddr); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-ppc64") { - switch (RelocType) { - case llvm::ELF::R_PPC64_ADDR32: - return visitELF_PPC64_ADDR32(R, Value); - case llvm::ELF::R_PPC64_ADDR64: - return visitELF_PPC64_ADDR64(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF32-ppc") { - switch (RelocType) { - case llvm::ELF::R_PPC_ADDR32: - return visitELF_PPC_ADDR32(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF32-mips") { - switch (RelocType) { - case llvm::ELF::R_MIPS_32: - return visitELF_MIPS_32(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-mips") { - switch (RelocType) { - case llvm::ELF::R_MIPS_32: - return visitELF_MIPS_32(R, Value); - case llvm::ELF::R_MIPS_64: - return visitELF_MIPS_64(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-aarch64") { - switch (RelocType) { - case llvm::ELF::R_AARCH64_ABS32: - return visitELF_AARCH64_ABS32(R, Value); - case llvm::ELF::R_AARCH64_ABS64: - return visitELF_AARCH64_ABS64(R, Value); - default: - HasError = true; - return RelocToApply(); - } - } else if (FileFormat == "ELF64-s390") { - switch (RelocType) { - case llvm::ELF::R_390_32: - return visitELF_390_32(R, Value); - case llvm::ELF::R_390_64: - return visitELF_390_64(R, Value); + } + case Triple::aarch64: + switch (RelocType) { + case llvm::ELF::R_AARCH64_ABS32: + return visitELF_AARCH64_ABS32(R, Value); + case llvm::ELF::R_AARCH64_ABS64: + return visitELF_AARCH64_ABS64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::mips64el: + case Triple::mips64: + switch (RelocType) { + case llvm::ELF::R_MIPS_32: + return visitELF_MIPS_32(R, Value); + case llvm::ELF::R_MIPS_64: + return visitELF_MIPS_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::ppc64le: + case Triple::ppc64: + switch (RelocType) { + case llvm::ELF::R_PPC64_ADDR32: + return visitELF_PPC64_ADDR32(R, Value); + case llvm::ELF::R_PPC64_ADDR64: + return visitELF_PPC64_ADDR64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::systemz: + switch (RelocType) { + case llvm::ELF::R_390_32: + return visitELF_390_32(R, Value); + case llvm::ELF::R_390_64: + return visitELF_390_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::sparcv9: + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARCV9_32(R, Value); + case llvm::ELF::R_SPARC_64: + case llvm::ELF::R_SPARC_UA64: + return visitELF_SPARCV9_64(R, Value); + default: + HasError = true; + return RelocToApply(); + } default: HasError = true; return RelocToApply(); } - } else if (FileFormat == "ELF32-sparc") { - switch (RelocType) { - case llvm::ELF::R_SPARC_32: - case llvm::ELF::R_SPARC_UA32: - return visitELF_SPARC_32(R, Value); + } else if (ObjToVisit.getBytesInAddress() == 4) { // 32-bit object file + switch (ObjToVisit.getArch()) { + case Triple::x86: + switch (RelocType) { + case llvm::ELF::R_386_NONE: + return visitELF_386_NONE(R); + case llvm::ELF::R_386_32: + return visitELF_386_32(R, Value); + case llvm::ELF::R_386_PC32: + return visitELF_386_PC32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::ppc: + switch (RelocType) { + case llvm::ELF::R_PPC_ADDR32: + return visitELF_PPC_ADDR32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::arm: + case Triple::armeb: + switch (RelocType) { + default: + HasError = true; + return RelocToApply(); + case llvm::ELF::R_ARM_ABS32: + return visitELF_ARM_ABS32(R, Value); + } + case Triple::mipsel: + case Triple::mips: + switch (RelocType) { + case llvm::ELF::R_MIPS_32: + return visitELF_MIPS_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } + case Triple::sparc: + switch (RelocType) { + case llvm::ELF::R_SPARC_32: + case llvm::ELF::R_SPARC_UA32: + return visitELF_SPARC_32(R, Value); + default: + HasError = true; + return RelocToApply(); + } default: HasError = true; return RelocToApply(); } - } else if (FileFormat == "ELF64-sparc") { + } else { + report_fatal_error("Invalid word size in object file"); + } + } + + RelocToApply visitCOFF(uint32_t RelocType, RelocationRef R, uint64_t Value) { + switch (ObjToVisit.getArch()) { + case Triple::x86: switch (RelocType) { - case llvm::ELF::R_SPARC_32: - case llvm::ELF::R_SPARC_UA32: - return visitELF_SPARCV9_32(R, Value); - case llvm::ELF::R_SPARC_64: - case llvm::ELF::R_SPARC_UA64: - return visitELF_SPARCV9_64(R, Value); - default: - HasError = true; - return RelocToApply(); + case COFF::IMAGE_REL_I386_SECREL: + return visitCOFF_I386_SECREL(R, Value); + case COFF::IMAGE_REL_I386_DIR32: + return visitCOFF_I386_DIR32(R, Value); } - } else if (FileFormat == "ELF32-arm") { + break; + case Triple::x86_64: switch (RelocType) { - default: - HasError = true; - return RelocToApply(); - case llvm::ELF::R_ARM_ABS32: - return visitELF_ARM_ABS32(R, Value); + case COFF::IMAGE_REL_AMD64_SECREL: + return visitCOFF_AMD64_SECREL(R, Value); + case COFF::IMAGE_REL_AMD64_ADDR64: + return visitCOFF_AMD64_ADDR64(R, Value); } + break; } HasError = true; return RelocToApply(); } - bool error() { return HasError; } - -private: - StringRef FileFormat; - bool HasError; - - int64_t getAddend32LE(RelocationRef R) { + int64_t getELFAddend32LE(RelocationRef R) { const ELF32LEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -180,7 +229,7 @@ private: return Addend; } - int64_t getAddend64LE(RelocationRef R) { + int64_t getELFAddend64LE(RelocationRef R) { const ELF64LEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -188,7 +237,7 @@ private: return Addend; } - int64_t getAddend32BE(RelocationRef R) { + int64_t getELFAddend32BE(RelocationRef R) { const ELF32BEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -196,7 +245,7 @@ private: return Addend; } - int64_t getAddend64BE(RelocationRef R) { + int64_t getELFAddend64BE(RelocationRef R) { const ELF64BEObjectFile *Obj = cast(R.getObjectFile()); DataRefImpl DRI = R.getRawDataRefImpl(); int64_t Addend; @@ -213,13 +262,12 @@ private: // Ideally the Addend here will be the addend in the data for // the relocation. It's not actually the case for Rel relocations. RelocToApply visitELF_386_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32LE(R); + int64_t Addend = getELFAddend32LE(R); return RelocToApply(Value + Addend, 4); } - RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend32LE(R); + RelocToApply visitELF_386_PC32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend32LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); @@ -230,23 +278,22 @@ private: return RelocToApply(0, 0); } RelocToApply visitELF_X86_64_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); return RelocToApply(Value + Addend, 8); } - RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value, - uint64_t SecAddr) { - int64_t Addend = getAddend64LE(R); + RelocToApply visitELF_X86_64_PC32(RelocationRef R, uint64_t Value) { + int64_t Addend = getELFAddend64LE(R); uint64_t Address; R.getOffset(Address); return RelocToApply(Value + Addend - Address, 4); } RelocToApply visitELF_X86_64_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } RelocToApply visitELF_X86_64_32S(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend = getELFAddend64LE(R); int32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -266,7 +313,7 @@ private: /// PPC32 ELF RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32BE(R); + int64_t Addend = getELFAddend32BE(R); uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } @@ -288,7 +335,8 @@ private: // AArch64 ELF RelocToApply visitELF_AARCH64_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -299,13 +347,14 @@ private: } RelocToApply visitELF_AARCH64_ABS64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64LE(R); + int64_t Addend; + getELFRelocationAddend(R, Addend); return RelocToApply(Value + Addend, 8); } // SystemZ ELF RelocToApply visitELF_390_32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); int64_t Res = Value + Addend; // Overflow check allows for both signed and unsigned interpretation. @@ -316,30 +365,54 @@ private: } RelocToApply visitELF_390_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_SPARC_32(RelocationRef R, uint32_t Value) { - int32_t Addend = getAddend32BE(R); + int32_t Addend = getELFAddend32BE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_32(RelocationRef R, uint64_t Value) { - int32_t Addend = getAddend64BE(R); + int32_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 4); } RelocToApply visitELF_SPARCV9_64(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend64BE(R); + int64_t Addend = getELFAddend64BE(R); return RelocToApply(Value + Addend, 8); } RelocToApply visitELF_ARM_ABS32(RelocationRef R, uint64_t Value) { - int64_t Addend = getAddend32LE(R); - return RelocToApply(Value + Addend, 4); + int64_t Addend; + getELFRelocationAddend(R, Addend); + int64_t Res = Value + Addend; + + // Overflow check allows for both signed and unsigned interpretation. + if (Res < INT32_MIN || Res > UINT32_MAX) + HasError = true; + + return RelocToApply(static_cast(Res), 4); } + /// I386 COFF + RelocToApply visitCOFF_I386_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_I386_DIR32(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + /// AMD64 COFF + RelocToApply visitCOFF_AMD64_SECREL(RelocationRef R, uint64_t Value) { + return RelocToApply(static_cast(Value), /*Width=*/4); + } + + RelocToApply visitCOFF_AMD64_ADDR64(RelocationRef R, uint64_t Value) { + return RelocToApply(Value, /*Width=*/8); + } }; } diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index 77eef4a..435799a 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_SYMBOLIC_FILE_H -#define LLVM_OBJECT_SYMBOLIC_FILE_H +#ifndef LLVM_OBJECT_SYMBOLICFILE_H +#define LLVM_OBJECT_SYMBOLICFILE_H #include "llvm/Object/Binary.h" @@ -87,8 +87,9 @@ public: SF_Absolute = 1U << 3, // Absolute symbol SF_Common = 1U << 4, // Symbol has common linkage SF_Indirect = 1U << 5, // Symbol is an alias to another symbol - SF_FormatSpecific = 1U << 6 // Specific to the object file format + SF_FormatSpecific = 1U << 6, // Specific to the object file format // (e.g. section symbols) + SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary }; BasicSymbolRef() : OwningObject(nullptr) { } @@ -115,7 +116,7 @@ const uint64_t UnknownAddressOrSize = ~0ULL; class SymbolicFile : public Binary { public: virtual ~SymbolicFile(); - SymbolicFile(unsigned int Type, std::unique_ptr Source); + SymbolicFile(unsigned int Type, MemoryBufferRef Source); // virtual interface. virtual void moveSymbolNext(DataRefImpl &Symb) const = 0; @@ -142,15 +143,16 @@ public: } // construction aux. - static ErrorOr - createSymbolicFile(std::unique_ptr &Object, - sys::fs::file_magic Type, LLVMContext *Context); + static ErrorOr> + createSymbolicFile(MemoryBufferRef Object, sys::fs::file_magic Type, + LLVMContext *Context); - static ErrorOr - createSymbolicFile(std::unique_ptr &Object) { + static ErrorOr> + createSymbolicFile(MemoryBufferRef Object) { return createSymbolicFile(Object, sys::fs::file_magic::unknown, nullptr); } - static ErrorOr createSymbolicFile(StringRef ObjectPath); + static ErrorOr> + createSymbolicFile(StringRef ObjectPath); static inline bool classof(const Binary *v) { return v->isSymbolic(); diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index d46b0e8..3f8547e 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -187,6 +187,7 @@ public: /// /// \p Claim Whether the argument should be claimed, if it exists. Arg *getLastArgNoClaim(OptSpecifier Id) const; + Arg *getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const; Arg *getLastArg(OptSpecifier Id) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1) const; Arg *getLastArg(OptSpecifier Id0, OptSpecifier Id1, OptSpecifier Id2) const; diff --git a/include/llvm/PassRegistry.h b/include/llvm/PassRegistry.h index 1558c51..8c28ef5 100644 --- a/include/llvm/PassRegistry.h +++ b/include/llvm/PassRegistry.h @@ -42,61 +42,51 @@ class PassRegistry { mutable sys::SmartRWMutex Lock; /// PassInfoMap - Keep track of the PassInfo object for each registered pass. - typedef DenseMap MapType; + typedef DenseMap MapType; MapType PassInfoMap; - - typedef StringMap StringMapType; + + typedef StringMap StringMapType; StringMapType PassInfoStringMap; - - /// AnalysisGroupInfo - Keep track of information for each analysis group. - struct AnalysisGroupInfo { - SmallPtrSet Implementations; - }; - DenseMap AnalysisGroupInfoMap; - + std::vector> ToFree; - std::vector Listeners; - + std::vector Listeners; + public: - PassRegistry() { } + PassRegistry() {} ~PassRegistry(); - - /// getPassRegistry - Access the global registry object, which is + + /// getPassRegistry - Access the global registry object, which is /// automatically initialized at application launch and destroyed by /// llvm_shutdown. static PassRegistry *getPassRegistry(); - + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' /// type identifier (&MyPass::ID). const PassInfo *getPassInfo(const void *TI) const; - + /// getPassInfo - Look up a pass' corresponding PassInfo, indexed by the pass' /// argument string. const PassInfo *getPassInfo(StringRef Arg) const; - - /// registerPass - Register a pass (by means of its PassInfo) with the + + /// registerPass - Register a pass (by means of its PassInfo) with the /// registry. Required in order to use the pass with a PassManager. void registerPass(const PassInfo &PI, bool ShouldFree = false); - - /// registerPass - Unregister a pass (by means of its PassInfo) with the - /// registry. - void unregisterPass(const PassInfo &PI); - + /// registerAnalysisGroup - Register an analysis group (or a pass implementing - // an analysis group) with the registry. Like registerPass, this is required + // an analysis group) with the registry. Like registerPass, this is required // in order for a PassManager to be able to use this group/pass. void registerAnalysisGroup(const void *InterfaceID, const void *PassID, - PassInfo& Registeree, bool isDefault, + PassInfo &Registeree, bool isDefault, bool ShouldFree = false); - + /// enumerateWith - Enumerate the registered passes, calling the provided /// PassRegistrationListener's passEnumerate() callback on each of them. void enumerateWith(PassRegistrationListener *L); - + /// addRegistrationListener - Register the given PassRegistrationListener /// to receive passRegistered() callbacks whenever a new pass is registered. void addRegistrationListener(PassRegistrationListener *L); - + /// removeRegistrationListener - Unregister a PassRegistrationListener so that /// it no longer receives passRegistered() callbacks. void removeRegistrationListener(PassRegistrationListener *L); diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h index 449bc92..6cb6516 100644 --- a/include/llvm/PassSupport.h +++ b/include/llvm/PassSupport.h @@ -82,6 +82,15 @@ class TargetMachine; CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ } +#define INITIALIZE_PASS_WITH_OPTIONS(PassName, Arg, Name, Cfg, Analysis) \ + INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + PassName::registerOptions(); \ + INITIALIZE_PASS_END(PassName, Arg, Name, Cfg, Analysis) + +#define INITIALIZE_PASS_WITH_OPTIONS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + INITIALIZE_PASS_BEGIN(PassName, Arg, Name, Cfg, Analysis) \ + PassName::registerOptions(); \ + template Pass *callDefaultCtor() { return new PassName(); } diff --git a/include/llvm/ProfileData/CoverageMapping.h b/include/llvm/ProfileData/CoverageMapping.h new file mode 100644 index 0000000..38fc8ca --- /dev/null +++ b/include/llvm/ProfileData/CoverageMapping.h @@ -0,0 +1,448 @@ +//=-- CoverageMapping.h - Code coverage mapping support ---------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Code coverage mapping data is generated by clang and read by +// llvm-cov to show code coverage statistics for a file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_COVERAGEMAPPING_H_ +#define LLVM_PROFILEDATA_COVERAGEMAPPING_H_ + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/iterator.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { +class IndexedInstrProfReader; +namespace coverage { + +class ObjectFileCoverageMappingReader; + +class CoverageMapping; +struct CounterExpressions; + +enum CoverageMappingVersion { CoverageMappingVersion1 }; + +/// \brief A Counter is an abstract value that describes how to compute the +/// execution count for a region of code using the collected profile count data. +struct Counter { + enum CounterKind { Zero, CounterValueReference, Expression }; + static const unsigned EncodingTagBits = 2; + static const unsigned EncodingTagMask = 0x3; + static const unsigned EncodingCounterTagAndExpansionRegionTagBits = + EncodingTagBits + 1; + +private: + CounterKind Kind; + unsigned ID; + + Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} + +public: + Counter() : Kind(Zero), ID(0) {} + + CounterKind getKind() const { return Kind; } + + bool isZero() const { return Kind == Zero; } + + bool isExpression() const { return Kind == Expression; } + + unsigned getCounterID() const { return ID; } + + unsigned getExpressionID() const { return ID; } + + bool operator==(const Counter &Other) const { + return Kind == Other.Kind && ID == Other.ID; + } + + friend bool operator<(const Counter &LHS, const Counter &RHS) { + return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); + } + + /// \brief Return the counter that represents the number zero. + static Counter getZero() { return Counter(); } + + /// \brief Return the counter that corresponds to a specific profile counter. + static Counter getCounter(unsigned CounterId) { + return Counter(CounterValueReference, CounterId); + } + + /// \brief Return the counter that corresponds to a specific + /// addition counter expression. + static Counter getExpression(unsigned ExpressionId) { + return Counter(Expression, ExpressionId); + } +}; + +/// \brief A Counter expression is a value that represents an arithmetic +/// operation with two counters. +struct CounterExpression { + enum ExprKind { Subtract, Add }; + ExprKind Kind; + Counter LHS, RHS; + + CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) + : Kind(Kind), LHS(LHS), RHS(RHS) {} +}; + +/// \brief A Counter expression builder is used to construct the +/// counter expressions. It avoids unecessary duplication +/// and simplifies algebraic expressions. +class CounterExpressionBuilder { + /// \brief A list of all the counter expressions + std::vector Expressions; + /// \brief A lookup table for the index of a given expression. + llvm::DenseMap ExpressionIndices; + + /// \brief Return the counter which corresponds to the given expression. + /// + /// If the given expression is already stored in the builder, a counter + /// that references that expression is returned. Otherwise, the given + /// expression is added to the builder's collection of expressions. + Counter get(const CounterExpression &E); + + /// \brief Gather the terms of the expression tree for processing. + /// + /// This collects each addition and subtraction referenced by the counter into + /// a sequence that can be sorted and combined to build a simplified counter + /// expression. + void extractTerms(Counter C, int Sign, + SmallVectorImpl> &Terms); + + /// \brief Simplifies the given expression tree + /// by getting rid of algebraically redundant operations. + Counter simplify(Counter ExpressionTree); + +public: + ArrayRef getExpressions() const { return Expressions; } + + /// \brief Return a counter that represents the expression + /// that adds LHS and RHS. + Counter add(Counter LHS, Counter RHS); + + /// \brief Return a counter that represents the expression + /// that subtracts RHS from LHS. + Counter subtract(Counter LHS, Counter RHS); +}; + +/// \brief A Counter mapping region associates a source range with +/// a specific counter. +struct CounterMappingRegion { + enum RegionKind { + /// \brief A CodeRegion associates some code with a counter + CodeRegion, + + /// \brief An ExpansionRegion represents a file expansion region that + /// associates a source range with the expansion of a virtual source file, + /// such as for a macro instantiation or #include file. + ExpansionRegion, + + /// \brief A SkippedRegion represents a source range with code that + /// was skipped by a preprocessor or similar means. + SkippedRegion + }; + + static const unsigned EncodingHasCodeBeforeBits = 1; + + Counter Count; + unsigned FileID, ExpandedFileID; + unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; + RegionKind Kind; + /// \brief A flag that is set to true when there is already code before + /// this region on the same line. + /// This is useful to accurately compute the execution counts for a line. + bool HasCodeBefore; + + CounterMappingRegion(Counter Count, unsigned FileID, unsigned LineStart, + unsigned ColumnStart, unsigned LineEnd, + unsigned ColumnEnd, bool HasCodeBefore = false, + RegionKind Kind = CodeRegion) + : Count(Count), FileID(FileID), ExpandedFileID(0), LineStart(LineStart), + ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), + Kind(Kind), HasCodeBefore(HasCodeBefore) {} + + inline std::pair startLoc() const { + return std::pair(LineStart, ColumnStart); + } + + inline std::pair endLoc() const { + return std::pair(LineEnd, ColumnEnd); + } + + bool operator<(const CounterMappingRegion &Other) const { + if (FileID != Other.FileID) + return FileID < Other.FileID; + return startLoc() < Other.startLoc(); + } + + bool contains(const CounterMappingRegion &Other) const { + if (FileID != Other.FileID) + return false; + if (startLoc() > Other.startLoc()) + return false; + if (endLoc() < Other.endLoc()) + return false; + return true; + } +}; + +/// \brief Associates a source range with an execution count. +struct CountedRegion : public CounterMappingRegion { + uint64_t ExecutionCount; + + CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount) + : CounterMappingRegion(R), ExecutionCount(ExecutionCount) {} +}; + +/// \brief A Counter mapping context is used to connect the counters, +/// expressions and the obtained counter values. +class CounterMappingContext { + ArrayRef Expressions; + ArrayRef CounterValues; + +public: + CounterMappingContext(ArrayRef Expressions, + ArrayRef CounterValues = ArrayRef()) + : Expressions(Expressions), CounterValues(CounterValues) {} + + void dump(const Counter &C, llvm::raw_ostream &OS) const; + void dump(const Counter &C) const { dump(C, llvm::outs()); } + + /// \brief Return the number of times that a region of code associated with + /// this counter was executed. + ErrorOr evaluate(const Counter &C) const; +}; + +/// \brief Code coverage information for a single function. +struct FunctionRecord { + /// \brief Raw function name. + std::string Name; + /// \brief Associated files. + std::vector Filenames; + /// \brief Regions in the function along with their counts. + std::vector CountedRegions; + /// \brief The number of times this function was executed. + uint64_t ExecutionCount; + + FunctionRecord(StringRef Name, ArrayRef Filenames, + uint64_t ExecutionCount) + : Name(Name), Filenames(Filenames.begin(), Filenames.end()), + ExecutionCount(ExecutionCount) {} +}; + +/// \brief Iterator over Functions, optionally filtered to a single file. +class FunctionRecordIterator + : public iterator_facade_base { + ArrayRef Records; + ArrayRef::iterator Current; + StringRef Filename; + + /// \brief Skip records whose primary file is not \c Filename. + void skipOtherFiles(); + +public: + FunctionRecordIterator(ArrayRef Records_, + StringRef Filename = "") + : Records(Records_), Current(Records.begin()), Filename(Filename) { + skipOtherFiles(); + } + + FunctionRecordIterator() : Current(Records.begin()) {} + + bool operator==(const FunctionRecordIterator &RHS) const { + return Current == RHS.Current && Filename == RHS.Filename; + } + + const FunctionRecord &operator*() const { return *Current; } + + FunctionRecordIterator &operator++() { + assert(Current != Records.end() && "incremented past end"); + ++Current; + skipOtherFiles(); + return *this; + } +}; + +/// \brief Coverage information for a macro expansion or #included file. +/// +/// When covered code has pieces that can be expanded for more detail, such as a +/// preprocessor macro use and its definition, these are represented as +/// expansions whose coverage can be looked up independently. +struct ExpansionRecord { + /// \brief The abstract file this expansion covers. + unsigned FileID; + /// \brief The region that expands to this record. + const CountedRegion &Region; + /// \brief Coverage for the expansion. + const FunctionRecord &Function; + + ExpansionRecord(const CountedRegion &Region, + const FunctionRecord &Function) + : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} +}; + +/// \brief The execution count information starting at a point in a file. +/// +/// A sequence of CoverageSegments gives execution counts for a file in format +/// that's simple to iterate through for processing. +struct CoverageSegment { + /// \brief The line where this segment begins. + unsigned Line; + /// \brief The column where this segment begins. + unsigned Col; + /// \brief The execution count, or zero if no count was recorded. + uint64_t Count; + /// \brief When false, the segment was uninstrumented or skipped. + bool HasCount; + /// \brief Whether this enters a new region or returns to a previous count. + bool IsRegionEntry; + + CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) + : Line(Line), Col(Col), Count(0), HasCount(false), + IsRegionEntry(IsRegionEntry) {} + void setCount(uint64_t NewCount) { + Count = NewCount; + HasCount = true; + } + void addCount(uint64_t NewCount) { setCount(Count + NewCount); } +}; + +/// \brief Coverage information to be processed or displayed. +/// +/// This represents the coverage of an entire file, expansion, or function. It +/// provides a sequence of CoverageSegments to iterate through, as well as the +/// list of expansions that can be further processed. +class CoverageData { + std::string Filename; + std::vector Segments; + std::vector Expansions; + friend class CoverageMapping; + +public: + CoverageData() {} + + CoverageData(StringRef Filename) : Filename(Filename) {} + + CoverageData(CoverageData &&RHS) + : Filename(std::move(RHS.Filename)), Segments(std::move(RHS.Segments)), + Expansions(std::move(RHS.Expansions)) {} + + /// \brief Get the name of the file this data covers. + StringRef getFilename() { return Filename; } + + std::vector::iterator begin() { return Segments.begin(); } + std::vector::iterator end() { return Segments.end(); } + bool empty() { return Segments.empty(); } + + /// \brief Expansions that can be further processed. + std::vector getExpansions() { return Expansions; } +}; + +/// \brief The mapping of profile information to coverage data. +/// +/// This is the main interface to get coverage information, using a profile to +/// fill out execution counts. +class CoverageMapping { + std::vector Functions; + unsigned MismatchedFunctionCount; + + CoverageMapping() : MismatchedFunctionCount(0) {} + +public: + /// \brief Load the coverage mapping using the given readers. + static ErrorOr> + load(ObjectFileCoverageMappingReader &CoverageReader, + IndexedInstrProfReader &ProfileReader); + + /// \brief Load the coverage mapping from the given files. + static ErrorOr> + load(StringRef ObjectFilename, StringRef ProfileFilename); + + /// \brief The number of functions that couldn't have their profiles mapped. + /// + /// This is a count of functions whose profile is out of date or otherwise + /// can't be associated with any coverage information. + unsigned getMismatchedCount() { return MismatchedFunctionCount; } + + /// \brief Returns the list of files that are covered. + std::vector getUniqueSourceFiles() const; + + /// \brief Get the coverage for a particular file. + /// + /// The given filename must be the name as recorded in the coverage + /// information. That is, only names returned from getUniqueSourceFiles will + /// yield a result. + CoverageData getCoverageForFile(StringRef Filename); + + /// \brief Gets all of the functions covered by this profile. + iterator_range getCoveredFunctions() const { + return make_range(FunctionRecordIterator(Functions), + FunctionRecordIterator()); + } + + /// \brief Gets all of the functions in a particular file. + iterator_range + getCoveredFunctions(StringRef Filename) const { + return make_range(FunctionRecordIterator(Functions, Filename), + FunctionRecordIterator()); + } + + /// \brief Get the list of function instantiations in the file. + /// + /// Fucntions that are instantiated more than once, such as C++ template + /// specializations, have distinct coverage records for each instantiation. + std::vector getInstantiations(StringRef Filename); + + /// \brief Get the coverage for a particular function. + CoverageData getCoverageForFunction(const FunctionRecord &Function); + + /// \brief Get the coverage for an expansion within a coverage set. + CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion); +}; + +} // end namespace coverage + +/// \brief Provide DenseMapInfo for CounterExpression +template<> struct DenseMapInfo { + static inline coverage::CounterExpression getEmptyKey() { + using namespace coverage; + return CounterExpression(CounterExpression::ExprKind::Subtract, + Counter::getCounter(~0U), + Counter::getCounter(~0U)); + } + + static inline coverage::CounterExpression getTombstoneKey() { + using namespace coverage; + return CounterExpression(CounterExpression::ExprKind::Add, + Counter::getCounter(~0U), + Counter::getCounter(~0U)); + } + + static unsigned getHashValue(const coverage::CounterExpression &V) { + return static_cast( + hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), + V.RHS.getKind(), V.RHS.getCounterID())); + } + + static bool isEqual(const coverage::CounterExpression &LHS, + const coverage::CounterExpression &RHS) { + return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; + } +}; + + +} // end namespace llvm + +#endif // LLVM_PROFILEDATA_COVERAGEMAPPING_H_ diff --git a/include/llvm/ProfileData/CoverageMappingReader.h b/include/llvm/ProfileData/CoverageMappingReader.h new file mode 100644 index 0000000..5a6b44b --- /dev/null +++ b/include/llvm/ProfileData/CoverageMappingReader.h @@ -0,0 +1,208 @@ +//=-- CoverageMappingReader.h - Code coverage mapping reader ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for reading coverage mapping data for +// instrumentation based coverage. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H +#define LLVM_PROFILEDATA_COVERAGEMAPPINGREADER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include + +namespace llvm { +namespace coverage { + +class ObjectFileCoverageMappingReader; + +/// \brief Coverage mapping information for a single function. +struct CoverageMappingRecord { + StringRef FunctionName; + uint64_t FunctionHash; + ArrayRef Filenames; + ArrayRef Expressions; + ArrayRef MappingRegions; +}; + +/// \brief A file format agnostic iterator over coverage mapping data. +class CoverageMappingIterator + : public std::iterator { + ObjectFileCoverageMappingReader *Reader; + CoverageMappingRecord Record; + + void increment(); + +public: + CoverageMappingIterator() : Reader(nullptr) {} + CoverageMappingIterator(ObjectFileCoverageMappingReader *Reader) + : Reader(Reader) { + increment(); + } + + CoverageMappingIterator &operator++() { + increment(); + return *this; + } + bool operator==(const CoverageMappingIterator &RHS) { + return Reader == RHS.Reader; + } + bool operator!=(const CoverageMappingIterator &RHS) { + return Reader != RHS.Reader; + } + CoverageMappingRecord &operator*() { return Record; } + CoverageMappingRecord *operator->() { return &Record; } +}; + +/// \brief Base class for the raw coverage mapping and filenames data readers. +class RawCoverageReader { +protected: + StringRef Data; + + /// \brief Return the error code. + std::error_code error(std::error_code EC) { return EC; } + + /// \brief Clear the current error code and return a successful one. + std::error_code success() { return error(instrprof_error::success); } + + RawCoverageReader(StringRef Data) : Data(Data) {} + + std::error_code readULEB128(uint64_t &Result); + std::error_code readIntMax(uint64_t &Result, uint64_t MaxPlus1); + std::error_code readSize(uint64_t &Result); + std::error_code readString(StringRef &Result); +}; + +/// \brief Reader for the raw coverage filenames. +class RawCoverageFilenamesReader : public RawCoverageReader { + std::vector &Filenames; + + RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) + LLVM_DELETED_FUNCTION; + RawCoverageFilenamesReader & + operator=(const RawCoverageFilenamesReader &) LLVM_DELETED_FUNCTION; + +public: + RawCoverageFilenamesReader(StringRef Data, std::vector &Filenames) + : RawCoverageReader(Data), Filenames(Filenames) {} + + std::error_code read(); +}; + +/// \brief Reader for the raw coverage mapping data. +class RawCoverageMappingReader : public RawCoverageReader { + StringRef FunctionName; + ArrayRef TranslationUnitFilenames; + std::vector &Filenames; + std::vector &Expressions; + std::vector &MappingRegions; + + RawCoverageMappingReader(const RawCoverageMappingReader &) + LLVM_DELETED_FUNCTION; + RawCoverageMappingReader & + operator=(const RawCoverageMappingReader &) LLVM_DELETED_FUNCTION; + +public: + RawCoverageMappingReader(StringRef FunctionName, StringRef MappingData, + ArrayRef TranslationUnitFilenames, + std::vector &Filenames, + std::vector &Expressions, + std::vector &MappingRegions) + : RawCoverageReader(MappingData), FunctionName(FunctionName), + TranslationUnitFilenames(TranslationUnitFilenames), + Filenames(Filenames), Expressions(Expressions), + MappingRegions(MappingRegions) {} + + std::error_code read(CoverageMappingRecord &Record); + +private: + std::error_code decodeCounter(unsigned Value, Counter &C); + std::error_code readCounter(Counter &C); + std::error_code + readMappingRegionsSubArray(std::vector &MappingRegions, + unsigned InferredFileID, size_t NumFileIDs); +}; + +/// \brief Reader for the coverage mapping data that is emitted by the +/// frontend and stored in an object file. +class ObjectFileCoverageMappingReader { +public: + struct ProfileMappingRecord { + CoverageMappingVersion Version; + StringRef FunctionName; + uint64_t FunctionHash; + StringRef CoverageMapping; + size_t FilenamesBegin; + size_t FilenamesSize; + + ProfileMappingRecord(CoverageMappingVersion Version, StringRef FunctionName, + uint64_t FunctionHash, StringRef CoverageMapping, + size_t FilenamesBegin, size_t FilenamesSize) + : Version(Version), FunctionName(FunctionName), + FunctionHash(FunctionHash), CoverageMapping(CoverageMapping), + FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {} + }; + +private: + std::error_code LastError; + object::OwningBinary Object; + std::vector Filenames; + std::vector MappingRecords; + size_t CurrentRecord; + std::vector FunctionsFilenames; + std::vector Expressions; + std::vector MappingRegions; + + ObjectFileCoverageMappingReader(const ObjectFileCoverageMappingReader &) + LLVM_DELETED_FUNCTION; + ObjectFileCoverageMappingReader & + operator=(const ObjectFileCoverageMappingReader &) LLVM_DELETED_FUNCTION; + + /// \brief Set the current error_code and return same. + std::error_code error(std::error_code EC) { + LastError = EC; + return EC; + } + + /// \brief Clear the current error code and return a successful one. + std::error_code success() { return error(instrprof_error::success); } + +public: + ObjectFileCoverageMappingReader(StringRef FileName); + ObjectFileCoverageMappingReader( + std::unique_ptr &ObjectBuffer, + sys::fs::file_magic Type = sys::fs::file_magic::unknown); + + std::error_code readHeader(); + std::error_code readNextRecord(CoverageMappingRecord &Record); + + /// Iterator over profile data. + CoverageMappingIterator begin() { return CoverageMappingIterator(this); } + CoverageMappingIterator end() { return CoverageMappingIterator(); } + + /// \brief Return true if the reader has finished reading the profile data. + bool isEOF() { return LastError == instrprof_error::eof; } + /// \brief Return true if the reader encountered an error reading profiling + /// data. + bool hasError() { return LastError && !isEOF(); } + /// \brief Get the current error code. + std::error_code getError() { return LastError; } +}; + +} // end namespace coverage +} // end namespace llvm + +#endif diff --git a/include/llvm/ProfileData/CoverageMappingWriter.h b/include/llvm/ProfileData/CoverageMappingWriter.h new file mode 100644 index 0000000..2e3b037 --- /dev/null +++ b/include/llvm/ProfileData/CoverageMappingWriter.h @@ -0,0 +1,63 @@ +//=-- CoverageMappingWriter.h - Code coverage mapping writer ------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing coverage mapping data for +// instrumentation based coverage. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H +#define LLVM_PROFILEDATA_COVERAGEMAPPINGWRITER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { +namespace coverage { + +/// \brief Writer of the filenames section for the instrumentation +/// based code coverage. +class CoverageFilenamesSectionWriter { + ArrayRef Filenames; + +public: + CoverageFilenamesSectionWriter(ArrayRef Filenames) + : Filenames(Filenames) {} + + /// \brief Write encoded filenames to the given output stream. + void write(raw_ostream &OS); +}; + +/// \brief Writer for instrumentation based coverage mapping data. +class CoverageMappingWriter { + ArrayRef VirtualFileMapping; + ArrayRef Expressions; + MutableArrayRef MappingRegions; + +public: + CoverageMappingWriter(ArrayRef VirtualFileMapping, + ArrayRef Expressions, + MutableArrayRef MappingRegions) + : VirtualFileMapping(VirtualFileMapping), Expressions(Expressions), + MappingRegions(MappingRegions) {} + + CoverageMappingWriter(ArrayRef Expressions, + MutableArrayRef MappingRegions) + : Expressions(Expressions), MappingRegions(MappingRegions) {} + + /// \brief Write encoded coverage mapping data to the given output stream. + void write(raw_ostream &OS); +}; + +} // end namespace coverage +} // end namespace llvm + +#endif diff --git a/include/llvm/ProfileData/InstrProfReader.h b/include/llvm/ProfileData/InstrProfReader.h index 7a5a71d..9655d66 100644 --- a/include/llvm/ProfileData/InstrProfReader.h +++ b/include/llvm/ProfileData/InstrProfReader.h @@ -12,17 +12,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_INSTRPROF_READER_H_ -#define LLVM_PROFILEDATA_INSTRPROF_READER_H_ +#ifndef LLVM_PROFILEDATA_INSTRPROFREADER_H +#define LLVM_PROFILEDATA_INSTRPROFREADER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/ErrorOr.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/EndianStream.h" #include "llvm/Support/OnDiskHashTable.h" - #include namespace llvm { @@ -94,8 +94,7 @@ public: /// Factory method to create an appropriately typed reader for the given /// instrprof file. - static std::error_code create(std::string Path, - std::unique_ptr &Result); + static ErrorOr> create(std::string Path); }; /// Reader for the simple text based instrprof format. @@ -120,7 +119,7 @@ private: LLVM_DELETED_FUNCTION; public: TextInstrProfReader(std::unique_ptr DataBuffer_) - : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, '#') {} + : DataBuffer(std::move(DataBuffer_)), Line(*DataBuffer, true, '#') {} /// Read the header. std::error_code readHeader() override { return success(); } @@ -206,12 +205,17 @@ enum class HashT : uint32_t; /// Trait for lookups into the on-disk hash table for the binary instrprof /// format. class InstrProfLookupTrait { - std::vector CountBuffer; + std::vector DataBuffer; IndexedInstrProf::HashT HashType; public: InstrProfLookupTrait(IndexedInstrProf::HashT HashType) : HashType(HashType) {} - typedef InstrProfRecord data_type; + struct data_type { + data_type(StringRef Name, ArrayRef Data) + : Name(Name), Data(Data) {} + StringRef Name; + ArrayRef Data; + }; typedef StringRef internal_key_type; typedef StringRef external_key_type; typedef uint64_t hash_value_type; @@ -234,25 +238,20 @@ public: return StringRef((const char *)D, N); } - InstrProfRecord ReadData(StringRef K, const unsigned char *D, offset_type N) { - if (N < 2 * sizeof(uint64_t) || N % sizeof(uint64_t)) { + data_type ReadData(StringRef K, const unsigned char *D, offset_type N) { + DataBuffer.clear(); + if (N % sizeof(uint64_t)) // The data is corrupt, don't try to read it. - CountBuffer.clear(); - return InstrProfRecord("", 0, CountBuffer); - } + return data_type("", DataBuffer); using namespace support; - - // The first stored value is the hash. - uint64_t Hash = endian::readNext(D); - // Each counter follows. - unsigned NumCounters = N / sizeof(uint64_t) - 1; - CountBuffer.clear(); - CountBuffer.reserve(NumCounters - 1); - for (unsigned I = 0; I < NumCounters; ++I) - CountBuffer.push_back(endian::readNext(D)); - - return InstrProfRecord(K, Hash, CountBuffer); + // We just treat the data as opaque here. It's simpler to handle in + // IndexedInstrProfReader. + unsigned NumEntries = N / sizeof(uint64_t); + DataBuffer.reserve(NumEntries); + for (unsigned I = 0; I < NumEntries; ++I) + DataBuffer.push_back(endian::readNext(D)); + return data_type(K, DataBuffer); } }; typedef OnDiskIterableChainedHashTable @@ -267,7 +266,11 @@ private: std::unique_ptr Index; /// Iterator over the profile data. InstrProfReaderIndex::data_iterator RecordIterator; - /// The maximal execution count among all fucntions. + /// Offset into our current data set. + size_t CurrentOffset; + /// The file format version of the profile data. + uint64_t FormatVersion; + /// The maximal execution count among all functions. uint64_t MaxFunctionCount; IndexedInstrProfReader(const IndexedInstrProfReader &) LLVM_DELETED_FUNCTION; @@ -275,8 +278,7 @@ private: LLVM_DELETED_FUNCTION; public: IndexedInstrProfReader(std::unique_ptr DataBuffer) - : DataBuffer(std::move(DataBuffer)), Index(nullptr), - RecordIterator(InstrProfReaderIndex::data_iterator()) {} + : DataBuffer(std::move(DataBuffer)), Index(nullptr), CurrentOffset(0) {} /// Return true if the given buffer is in an indexed instrprof format. static bool hasFormat(const MemoryBuffer &DataBuffer); @@ -287,7 +289,7 @@ public: std::error_code readNextRecord(InstrProfRecord &Record) override; /// Fill Counts with the profile data for the given function name. - std::error_code getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, + std::error_code getFunctionCounts(StringRef FuncName, uint64_t FuncHash, std::vector &Counts); /// Return the maximum of all known function counts. uint64_t getMaximumFunctionCount() { return MaxFunctionCount; } @@ -299,4 +301,4 @@ public: } // end namespace llvm -#endif // LLVM_PROFILEDATA_INSTRPROF_READER_H_ +#endif diff --git a/include/llvm/ProfileData/InstrProfWriter.h b/include/llvm/ProfileData/InstrProfWriter.h index 6e68bee..a23c567 100644 --- a/include/llvm/ProfileData/InstrProfWriter.h +++ b/include/llvm/ProfileData/InstrProfWriter.h @@ -12,15 +12,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_INSTRPROF_WRITER_H_ -#define LLVM_PROFILEDATA_INSTRPROF_WRITER_H_ +#ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H +#define LLVM_PROFILEDATA_INSTRPROFWRITER_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/raw_ostream.h" - #include namespace llvm { @@ -28,13 +28,13 @@ namespace llvm { /// Writer for instrumentation based profile data. class InstrProfWriter { public: - struct CounterData { - uint64_t Hash; - std::vector Counts; - }; + typedef SmallDenseMap, 1> CounterData; private: StringMap FunctionData; + uint64_t MaxFunctionCount; public: + InstrProfWriter() : MaxFunctionCount(0) {} + /// Add function counts for the given function. If there are already counts /// for this function and the hash and number of counts match, each counter is /// summed. @@ -47,4 +47,4 @@ public: } // end namespace llvm -#endif // LLVM_PROFILE_INSTRPROF_WRITER_H_ +#endif diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h new file mode 100644 index 0000000..df0a055 --- /dev/null +++ b/include/llvm/ProfileData/SampleProf.h @@ -0,0 +1,247 @@ +//=-- SampleProf.h - Sampling profiling format support --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains common definitions used in the reading and writing of +// sample profile data. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PROFILEDATA_SAMPLEPROF_H_ +#define LLVM_PROFILEDATA_SAMPLEPROF_H_ + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include + +namespace llvm { + +const std::error_category &sampleprof_category(); + +enum class sampleprof_error { + success = 0, + bad_magic, + unsupported_version, + too_large, + truncated, + malformed, + unrecognized_format +}; + +inline std::error_code make_error_code(sampleprof_error E) { + return std::error_code(static_cast(E), sampleprof_category()); +} + +} // end namespace llvm + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} + +namespace llvm { + +namespace sampleprof { + +static inline uint64_t SPMagic() { + return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) | + uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) | + uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) | + uint64_t('2') << (64 - 56) | uint64_t(0xff); +} + +static inline uint64_t SPVersion() { return 100; } + +/// \brief Represents the relative location of an instruction. +/// +/// Instruction locations are specified by the line offset from the +/// beginning of the function (marked by the line where the function +/// header is) and the discriminator value within that line. +/// +/// The discriminator value is useful to distinguish instructions +/// that are on the same line but belong to different basic blocks +/// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). +struct LineLocation { + LineLocation(int L, unsigned D) : LineOffset(L), Discriminator(D) {} + int LineOffset; + unsigned Discriminator; +}; + +} // End namespace sampleprof + +template <> struct DenseMapInfo { + typedef DenseMapInfo OffsetInfo; + typedef DenseMapInfo DiscriminatorInfo; + static inline sampleprof::LineLocation getEmptyKey() { + return sampleprof::LineLocation(OffsetInfo::getEmptyKey(), + DiscriminatorInfo::getEmptyKey()); + } + static inline sampleprof::LineLocation getTombstoneKey() { + return sampleprof::LineLocation(OffsetInfo::getTombstoneKey(), + DiscriminatorInfo::getTombstoneKey()); + } + static inline unsigned getHashValue(sampleprof::LineLocation Val) { + return DenseMapInfo>::getHashValue( + std::pair(Val.LineOffset, Val.Discriminator)); + } + static inline bool isEqual(sampleprof::LineLocation LHS, + sampleprof::LineLocation RHS) { + return LHS.LineOffset == RHS.LineOffset && + LHS.Discriminator == RHS.Discriminator; + } +}; + +namespace sampleprof { + +/// \brief Representation of a single sample record. +/// +/// A sample record is represented by a positive integer value, which +/// indicates how frequently was the associated line location executed. +/// +/// Additionally, if the associated location contains a function call, +/// the record will hold a list of all the possible called targets. For +/// direct calls, this will be the exact function being invoked. For +/// indirect calls (function pointers, virtual table dispatch), this +/// will be a list of one or more functions. +class SampleRecord { +public: + typedef StringMap CallTargetMap; + + SampleRecord() : NumSamples(0), CallTargets() {} + + /// \brief Increment the number of samples for this record by \p S. + /// + /// Sample counts accumulate using saturating arithmetic, to avoid wrapping + /// around unsigned integers. + void addSamples(unsigned S) { + if (NumSamples <= std::numeric_limits::max() - S) + NumSamples += S; + else + NumSamples = std::numeric_limits::max(); + } + + /// \brief Add called function \p F with samples \p S. + /// + /// Sample counts accumulate using saturating arithmetic, to avoid wrapping + /// around unsigned integers. + void addCalledTarget(StringRef F, unsigned S) { + unsigned &TargetSamples = CallTargets[F]; + if (TargetSamples <= std::numeric_limits::max() - S) + TargetSamples += S; + else + TargetSamples = std::numeric_limits::max(); + } + + /// \brief Return true if this sample record contains function calls. + bool hasCalls() const { return CallTargets.size() > 0; } + + unsigned getSamples() const { return NumSamples; } + const CallTargetMap &getCallTargets() const { return CallTargets; } + + /// \brief Merge the samples in \p Other into this record. + void merge(const SampleRecord &Other) { + addSamples(Other.getSamples()); + for (const auto &I : Other.getCallTargets()) + addCalledTarget(I.first(), I.second); + } + +private: + unsigned NumSamples; + CallTargetMap CallTargets; +}; + +typedef DenseMap BodySampleMap; + +/// \brief Representation of the samples collected for a function. +/// +/// This data structure contains all the collected samples for the body +/// of a function. Each sample corresponds to a LineLocation instance +/// within the body of the function. +class FunctionSamples { +public: + FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {} + void print(raw_ostream &OS = dbgs()); + void addTotalSamples(unsigned Num) { TotalSamples += Num; } + void addHeadSamples(unsigned Num) { TotalHeadSamples += Num; } + void addBodySamples(int LineOffset, unsigned Discriminator, unsigned Num) { + assert(LineOffset >= 0); + // When dealing with instruction weights, we use the value + // zero to indicate the absence of a sample. If we read an + // actual zero from the profile file, use the value 1 to + // avoid the confusion later on. + if (Num == 0) + Num = 1; + BodySamples[LineLocation(LineOffset, Discriminator)].addSamples(Num); + } + void addCalledTargetSamples(int LineOffset, unsigned Discriminator, + std::string FName, unsigned Num) { + assert(LineOffset >= 0); + BodySamples[LineLocation(LineOffset, Discriminator)].addCalledTarget(FName, + Num); + } + + /// \brief Return the sample record at the given location. + /// Each location is specified by \p LineOffset and \p Discriminator. + SampleRecord &sampleRecordAt(const LineLocation &Loc) { + return BodySamples[Loc]; + } + + /// \brief Return the number of samples collected at the given location. + /// Each location is specified by \p LineOffset and \p Discriminator. + unsigned samplesAt(int LineOffset, unsigned Discriminator) { + return sampleRecordAt(LineLocation(LineOffset, Discriminator)).getSamples(); + } + + bool empty() const { return BodySamples.empty(); } + + /// \brief Return the total number of samples collected inside the function. + unsigned getTotalSamples() const { return TotalSamples; } + + /// \brief Return the total number of samples collected at the head of the + /// function. + unsigned getHeadSamples() const { return TotalHeadSamples; } + + /// \brief Return all the samples collected in the body of the function. + const BodySampleMap &getBodySamples() const { return BodySamples; } + + /// \brief Merge the samples in \p Other into this one. + void merge(const FunctionSamples &Other) { + addTotalSamples(Other.getTotalSamples()); + addHeadSamples(Other.getHeadSamples()); + for (const auto &I : Other.getBodySamples()) { + const LineLocation &Loc = I.first; + const SampleRecord &Rec = I.second; + sampleRecordAt(Loc).merge(Rec); + } + } + +private: + /// \brief Total number of samples collected inside this function. + /// + /// Samples are cumulative, they include all the samples collected + /// inside this function and all its inlined callees. + unsigned TotalSamples; + + /// \brief Total number of samples collected at the head of the function. + unsigned TotalHeadSamples; + + /// \brief Map instruction locations to collected samples. + /// + /// Each entry in this map contains the number of samples + /// collected at the corresponding line offset. All line locations + /// are an offset from the start of the function. + BodySampleMap BodySamples; +}; + +} // End namespace sampleprof + +} // End namespace llvm + +#endif // LLVM_PROFILEDATA_SAMPLEPROF_H_ diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h new file mode 100644 index 0000000..c082a1a --- /dev/null +++ b/include/llvm/ProfileData/SampleProfReader.h @@ -0,0 +1,170 @@ +//===- SampleProfReader.h - Read LLVM sample profile data -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions needed for reading sample profiles. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PROFILEDATA_SAMPLEPROFREADER_H +#define LLVM_PROFILEDATA_SAMPLEPROFREADER_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +namespace sampleprof { + +/// \brief Sample-based profile reader. +/// +/// Each profile contains sample counts for all the functions +/// executed. Inside each function, statements are annotated with the +/// collected samples on all the instructions associated with that +/// statement. +/// +/// For this to produce meaningful data, the program needs to be +/// compiled with some debug information (at minimum, line numbers: +/// -gline-tables-only). Otherwise, it will be impossible to match IR +/// instructions to the line numbers collected by the profiler. +/// +/// From the profile file, we are interested in collecting the +/// following information: +/// +/// * A list of functions included in the profile (mangled names). +/// +/// * For each function F: +/// 1. The total number of samples collected in F. +/// +/// 2. The samples collected at each line in F. To provide some +/// protection against source code shuffling, line numbers should +/// be relative to the start of the function. +/// +/// The reader supports two file formats: text and binary. The text format +/// is useful for debugging and testing, while the binary format is more +/// compact. They can both be used interchangeably. +class SampleProfileReader { +public: + SampleProfileReader(std::unique_ptr B, LLVMContext &C) + : Profiles(0), Ctx(C), Buffer(std::move(B)) {} + + virtual ~SampleProfileReader() {} + + /// \brief Read and validate the file header. + virtual std::error_code readHeader() = 0; + + /// \brief Read sample profiles from the associated file. + virtual std::error_code read() = 0; + + /// \brief Print the profile for \p FName on stream \p OS. + void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs()); + + /// \brief Print all the profiles on stream \p OS. + void dump(raw_ostream &OS = dbgs()); + + /// \brief Return the samples collected for function \p F. + FunctionSamples *getSamplesFor(const Function &F) { + return &Profiles[F.getName()]; + } + + /// \brief Return all the profiles. + StringMap &getProfiles() { return Profiles; } + + /// \brief Report a parse error message. + void reportParseError(int64_t LineNumber, Twine Msg) const { + Ctx.diagnose(DiagnosticInfoSampleProfile(Buffer->getBufferIdentifier(), + LineNumber, Msg)); + } + + /// \brief Create a sample profile reader appropriate to the file format. + static ErrorOr> + create(StringRef Filename, LLVMContext &C); + +protected: + /// \brief Map every function to its associated profile. + /// + /// The profile of every function executed at runtime is collected + /// in the structure FunctionSamples. This maps function objects + /// to their corresponding profiles. + StringMap Profiles; + + /// \brief LLVM context used to emit diagnostics. + LLVMContext &Ctx; + + /// \brief Memory buffer holding the profile file. + std::unique_ptr Buffer; +}; + +class SampleProfileReaderText : public SampleProfileReader { +public: + SampleProfileReaderText(std::unique_ptr B, LLVMContext &C) + : SampleProfileReader(std::move(B), C) {} + + /// \brief Read and validate the file header. + std::error_code readHeader() override { return sampleprof_error::success; } + + /// \brief Read sample profiles from the associated file. + std::error_code read() override; +}; + +class SampleProfileReaderBinary : public SampleProfileReader { +public: + SampleProfileReaderBinary(std::unique_ptr B, LLVMContext &C) + : SampleProfileReader(std::move(B), C), Data(nullptr), End(nullptr) {} + + /// \brief Read and validate the file header. + std::error_code readHeader() override; + + /// \brief Read sample profiles from the associated file. + std::error_code read() override; + + /// \brief Return true if \p Buffer is in the format supported by this class. + static bool hasFormat(const MemoryBuffer &Buffer); + +protected: + /// \brief Read a numeric value of type T from the profile. + /// + /// If an error occurs during decoding, a diagnostic message is emitted and + /// EC is set. + /// + /// \returns the read value. + template ErrorOr readNumber(); + + /// \brief Read a string from the profile. + /// + /// If an error occurs during decoding, a diagnostic message is emitted and + /// EC is set. + /// + /// \returns the read value. + ErrorOr readString(); + + /// \brief Return true if we've reached the end of file. + bool at_eof() const { return Data >= End; } + + /// \brief Points to the current location in the buffer. + const uint8_t *Data; + + /// \brief Points to the end of the buffer. + const uint8_t *End; +}; + +} // End namespace sampleprof + +} // End namespace llvm + +#endif // LLVM_PROFILEDATA_SAMPLEPROFREADER_H diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h new file mode 100644 index 0000000..302a82d --- /dev/null +++ b/include/llvm/ProfileData/SampleProfWriter.h @@ -0,0 +1,110 @@ +//===- SampleProfWriter.h - Write LLVM sample profile data ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions needed for writing sample profiles. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H +#define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Module.h" +#include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/raw_ostream.h" + +namespace llvm { + +namespace sampleprof { + +enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC }; + +/// \brief Sample-based profile writer. Base class. +class SampleProfileWriter { +public: + SampleProfileWriter(StringRef Filename, std::error_code &EC, + sys::fs::OpenFlags Flags) + : OS(Filename, EC, Flags) {} + virtual ~SampleProfileWriter() {} + + /// \brief Write sample profiles in \p S for function \p FName. + /// + /// \returns true if the file was updated successfully. False, otherwise. + virtual bool write(StringRef FName, const FunctionSamples &S) = 0; + + /// \brief Write sample profiles in \p S for function \p F. + bool write(const Function &F, const FunctionSamples &S) { + return write(F.getName(), S); + } + + /// \brief Write all the sample profiles for all the functions in \p M. + /// + /// \returns true if the file was updated successfully. False, otherwise. + bool write(const Module &M, StringMap &P) { + for (const auto &F : M) { + StringRef Name = F.getName(); + if (!write(Name, P[Name])) + return false; + } + return true; + } + + /// \brief Write all the sample profiles in the given map of samples. + /// + /// \returns true if the file was updated successfully. False, otherwise. + bool write(StringMap &ProfileMap) { + for (auto &I : ProfileMap) { + StringRef FName = I.first(); + FunctionSamples &Profile = I.second; + if (!write(FName, Profile)) + return false; + } + return true; + } + + /// \brief Profile writer factory. Create a new writer based on the value of + /// \p Format. + static ErrorOr> + create(StringRef Filename, SampleProfileFormat Format); + +protected: + /// \brief Output stream where to emit the profile to. + raw_fd_ostream OS; +}; + +/// \brief Sample-based profile writer (text format). +class SampleProfileWriterText : public SampleProfileWriter { +public: + SampleProfileWriterText(StringRef F, std::error_code &EC) + : SampleProfileWriter(F, EC, sys::fs::F_Text) {} + + bool write(StringRef FName, const FunctionSamples &S) override; + bool write(const Module &M, StringMap &P) { + return SampleProfileWriter::write(M, P); + } +}; + +/// \brief Sample-based profile writer (binary format). +class SampleProfileWriterBinary : public SampleProfileWriter { +public: + SampleProfileWriterBinary(StringRef F, std::error_code &EC); + + bool write(StringRef F, const FunctionSamples &S) override; + bool write(const Module &M, StringMap &P) { + return SampleProfileWriter::write(M, P); + } +}; + +} // End namespace sampleprof + +} // End namespace llvm + +#endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index f63e0a6..96a8219 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H -#define LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H +#ifndef LLVM_SUPPORT_ARMBUILDATTRIBUTES_H +#define LLVM_SUPPORT_ARMBUILDATTRIBUTES_H namespace llvm { class StringRef; @@ -146,6 +146,12 @@ enum { AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations) AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted + // Tag_ABI_PCS_R9_use, (=14), uleb128 + R9IsGPR = 0, // R9 used as v6 (just another callee-saved register) + R9IsSB = 1, // R9 used as a global static base rgister + R9IsTLSPointer = 2, // R9 used as a thread local storage pointer + R9Reserved = 3, // R9 not used by code associated with attributed entity + // Tag_ABI_PCS_RW_data, (=15), uleb128 AddressRWPCRel = 1, // Address RW static data PC-relative AddressRWSBRel = 2, // Address RW static data SB-relative @@ -165,6 +171,8 @@ enum { WCharWidth4Bytes = 4, // sizeof(wchar_t) == 4 // Tag_ABI_FP_denormal, (=20), uleb128 + PositiveZero = 0, + IEEEDenormals = 1, PreserveFPSign = 2, // sign when flushed-to-zero is preserved // Tag_ABI_FP_number_model, (=23), uleb128 @@ -192,6 +200,9 @@ enum { // Tag_FP_HP_extension, (=36), uleb128 AllowHPFP = 1, // Allow use of Half Precision FP + // Tag_FP_16bit_format, (=38), uleb128 + FP16FormatIEEE = 1, + // Tag_MPextension_use, (=42), uleb128 AllowMP = 1, // Allow use of MP extensions @@ -214,4 +225,4 @@ enum { } // namespace ARMBuildAttrs } // namespace llvm -#endif // LLVM_SUPPORT_ARM_BUILD_ATTRIBUTES_H +#endif diff --git a/include/llvm/Support/ARMEHABI.h b/include/llvm/Support/ARMEHABI.h index c7ac54a..9b052df 100644 --- a/include/llvm/Support/ARMEHABI.h +++ b/include/llvm/Support/ARMEHABI.h @@ -19,8 +19,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_ARM_EHABI_H -#define LLVM_SUPPORT_ARM_EHABI_H +#ifndef LLVM_SUPPORT_ARMEHABI_H +#define LLVM_SUPPORT_ARMEHABI_H namespace llvm { namespace ARM { @@ -131,4 +131,4 @@ namespace EHABI { } } -#endif // ARM_UNWIND_OP_H +#endif diff --git a/include/llvm/Support/ARMWinEH.h b/include/llvm/Support/ARMWinEH.h index 78deb8d..1463629 100644 --- a/include/llvm/Support/ARMWinEH.h +++ b/include/llvm/Support/ARMWinEH.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SUPPORT_WINARMEH_H -#define LLVM_SUPPORT_WINARMEH_H +#ifndef LLVM_SUPPORT_ARMWINEH_H +#define LLVM_SUPPORT_ARMWINEH_H #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Endian.h" @@ -350,16 +350,15 @@ struct ExceptionDataRecord { ArrayRef EpilogueScopes() const { assert(E() == 0 && "epilogue scopes are only present when the E bit is 0"); size_t Offset = HeaderWords(*this); - return ArrayRef(&Data[Offset], EpilogueCount()); + return makeArrayRef(&Data[Offset], EpilogueCount()); } - ArrayRef UnwindByteCode() const { + ArrayRef UnwindByteCode() const { const size_t Offset = HeaderWords(*this) + (E() ? 0 : EpilogueCount()); - const support::ulittle8_t *ByteCode = - reinterpret_cast(&Data[Offset]); - return ArrayRef(ByteCode, - CodeWords() * sizeof(uint32_t)); + const uint8_t *ByteCode = + reinterpret_cast(&Data[Offset]); + return makeArrayRef(ByteCode, CodeWords() * sizeof(uint32_t)); } uint32_t ExceptionHandlerRVA() const { @@ -381,4 +380,3 @@ inline size_t HeaderWords(const ExceptionDataRecord &XR) { } #endif - diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index 7a7e4c0..de31771 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -90,7 +90,10 @@ class MallocAllocator : public AllocatorBase { public: void Reset() {} - void *Allocate(size_t Size, size_t /*Alignment*/) { return malloc(Size); } + LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, + size_t /*Alignment*/) { + return malloc(Size); + } // Pull in base class overloads. using AllocatorBase::Allocate; @@ -116,8 +119,8 @@ void printBumpPtrAllocatorStats(unsigned NumSlabs, size_t BytesAllocated, /// \brief Allocate memory in an ever growing pool, as if by bump-pointer. /// /// This isn't strictly a bump-pointer allocator as it uses backing slabs of -/// memory rather than relying on boundless contiguous heap. However, it has -/// bump-pointer semantics in that is a monotonically growing pool of memory +/// memory rather than relying on a boundless contiguous heap. However, it has +/// bump-pointer semantics in that it is a monotonically growing pool of memory /// where every allocation is found by merely allocating the next N bytes in /// the slab, or the next N bytes in the next slab. /// @@ -200,28 +203,24 @@ public: } /// \brief Allocate space at the specified alignment. - void *Allocate(size_t Size, size_t Alignment) { - if (!CurPtr) // Start a new slab if we haven't allocated one already. - StartNewSlab(); + LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { + assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); // Keep track of how many bytes we've allocated. BytesAllocated += Size; - // 0-byte alignment means 1-byte alignment. - if (Alignment == 0) - Alignment = 1; - - // Allocate the aligned space, going forwards from CurPtr. - char *Ptr = alignPtr(CurPtr, Alignment); + size_t Adjustment = alignmentAdjustment(CurPtr, Alignment); + assert(Adjustment + Size >= Size && "Adjustment + Size must not overflow"); - // Check if we can hold it. - if (Ptr + Size <= End) { - CurPtr = Ptr + Size; + // Check if we have enough space. + if (Adjustment + Size <= size_t(End - CurPtr)) { + char *AlignedPtr = CurPtr + Adjustment; + CurPtr = AlignedPtr + Size; // Update the allocation point of this memory block in MemorySanitizer. // Without this, MemorySanitizer messages for values originated from here // will point to the allocation of the entire slab. - __msan_allocated_memory(Ptr, Size); - return Ptr; + __msan_allocated_memory(AlignedPtr, Size); + return AlignedPtr; } // If Size is really big, allocate a separate slab for it. @@ -230,19 +229,22 @@ public: void *NewSlab = Allocator.Allocate(PaddedSize, 0); CustomSizedSlabs.push_back(std::make_pair(NewSlab, PaddedSize)); - Ptr = alignPtr((char *)NewSlab, Alignment); - assert((uintptr_t)Ptr + Size <= (uintptr_t)NewSlab + PaddedSize); - __msan_allocated_memory(Ptr, Size); - return Ptr; + uintptr_t AlignedAddr = alignAddr(NewSlab, Alignment); + assert(AlignedAddr + Size <= (uintptr_t)NewSlab + PaddedSize); + char *AlignedPtr = (char*)AlignedAddr; + __msan_allocated_memory(AlignedPtr, Size); + return AlignedPtr; } // Otherwise, start a new slab and try again. StartNewSlab(); - Ptr = alignPtr(CurPtr, Alignment); - CurPtr = Ptr + Size; - assert(CurPtr <= End && "Unable to allocate memory!"); - __msan_allocated_memory(Ptr, Size); - return Ptr; + uintptr_t AlignedAddr = alignAddr(CurPtr, Alignment); + assert(AlignedAddr + Size <= (uintptr_t)End && + "Unable to allocate memory!"); + char *AlignedPtr = (char*)AlignedAddr; + CurPtr = AlignedPtr + Size; + __msan_allocated_memory(AlignedPtr, Size); + return AlignedPtr; } // Pull in base class overloads. @@ -320,8 +322,10 @@ private: #ifndef NDEBUG // Poison the memory so stale pointers crash sooner. Note we must // preserve the Size and NextPtr fields at the beginning. - sys::Memory::setRangeWritable(*I, AllocatedSlabSize); - memset(*I, 0xCD, AllocatedSlabSize); + if (AllocatedSlabSize != 0) { + sys::Memory::setRangeWritable(*I, AllocatedSlabSize); + memset(*I, 0xCD, AllocatedSlabSize); + } #endif Allocator.Deallocate(*I, AllocatedSlabSize); } @@ -373,7 +377,7 @@ public: /// all memory allocated so far. void DestroyAll() { auto DestroyElements = [](char *Begin, char *End) { - assert(Begin == alignPtr(Begin, alignOf())); + assert(Begin == (char*)alignAddr(Begin, alignOf())); for (char *Ptr = Begin; Ptr + sizeof(T) <= End; Ptr += sizeof(T)) reinterpret_cast(Ptr)->~T(); }; @@ -382,7 +386,7 @@ public: ++I) { size_t AllocatedSlabSize = BumpPtrAllocator::computeSlabSize( std::distance(Allocator.Slabs.begin(), I)); - char *Begin = alignPtr((char *)*I, alignOf()); + char *Begin = (char*)alignAddr(*I, alignOf()); char *End = *I == Allocator.Slabs.back() ? Allocator.CurPtr : (char *)*I + AllocatedSlabSize; @@ -392,7 +396,7 @@ public: for (auto &PtrAndSize : Allocator.CustomSizedSlabs) { void *Ptr = PtrAndSize.first; size_t Size = PtrAndSize.second; - DestroyElements(alignPtr((char *)Ptr, alignOf()), (char *)Ptr + Size); + DestroyElements((char*)alignAddr(Ptr, alignOf()), (char *)Ptr + Size); } Allocator.Reset(); diff --git a/include/llvm/Support/CBindingWrapping.h b/include/llvm/Support/CBindingWrapping.h index 51097b8..786ba18 100644 --- a/include/llvm/Support/CBindingWrapping.h +++ b/include/llvm/Support/CBindingWrapping.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_C_BINDING_WRAPPING_H -#define LLVM_C_BINDING_WRAPPING_H +#ifndef LLVM_SUPPORT_CBINDINGWRAPPING_H +#define LLVM_SUPPORT_CBINDINGWRAPPING_H #include "llvm/Support/Casting.h" diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index e09ef07..150bce5 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -31,23 +31,30 @@ namespace llvm { namespace COFF { // The maximum number of sections that a COFF object can have (inclusive). - const int MaxNumberOfSections = 65299; + const int32_t MaxNumberOfSections16 = 65279; // The PE signature bytes that follows the DOS stub header. static const char PEMagic[] = { 'P', 'E', '\0', '\0' }; + static const char BigObjMagic[] = { + '\xc7', '\xa1', '\xba', '\xd1', '\xee', '\xba', '\xa9', '\x4b', + '\xaf', '\x20', '\xfa', '\xf6', '\x6a', '\xa4', '\xdc', '\xb8', + }; + // Sizes in bytes of various things in the COFF format. enum { - HeaderSize = 20, + Header16Size = 20, + Header32Size = 56, NameSize = 8, - SymbolSize = 18, + Symbol16Size = 18, + Symbol32Size = 20, SectionSize = 40, RelocationSize = 10 }; struct header { uint16_t Machine; - uint16_t NumberOfSections; + int32_t NumberOfSections; uint32_t TimeDateStamp; uint32_t PointerToSymbolTable; uint32_t NumberOfSymbols; @@ -55,6 +62,24 @@ namespace COFF { uint16_t Characteristics; }; + struct BigObjHeader { + enum : uint16_t { MinBigObjectVersion = 2 }; + + uint16_t Sig1; ///< Must be IMAGE_FILE_MACHINE_UNKNOWN (0). + uint16_t Sig2; ///< Must be 0xFFFF. + uint16_t Version; + uint16_t Machine; + uint32_t TimeDateStamp; + uint8_t UUID[16]; + uint32_t unused1; + uint32_t unused2; + uint32_t unused3; + uint32_t unused4; + uint32_t NumberOfSections; + uint32_t PointerToSymbolTable; + uint32_t NumberOfSymbols; + }; + enum MachineTypes { MT_Invalid = 0xffff, @@ -124,7 +149,7 @@ namespace COFF { struct symbol { char Name[NameSize]; uint32_t Value; - uint16_t SectionNumber; + int32_t SectionNumber; uint16_t Type; uint8_t StorageClass; uint8_t NumberOfAuxSymbols; @@ -140,9 +165,9 @@ namespace COFF { SF_WeakExternal = 0x01000000 }; - enum SymbolSectionNumber { - IMAGE_SYM_DEBUG = 0xFFFE, - IMAGE_SYM_ABSOLUTE = 0xFFFF, + enum SymbolSectionNumber : int32_t { + IMAGE_SYM_DEBUG = -2, + IMAGE_SYM_ABSOLUTE = -1, IMAGE_SYM_UNDEFINED = 0 }; @@ -367,18 +392,14 @@ namespace COFF { IMAGE_WEAK_EXTERN_SEARCH_ALIAS = 3 }; - struct AuxiliaryFile { - uint8_t FileName[18]; - }; - struct AuxiliarySectionDefinition { uint32_t Length; uint16_t NumberOfRelocations; uint16_t NumberOfLinenumbers; uint32_t CheckSum; - uint16_t Number; + uint32_t Number; uint8_t Selection; - char unused[3]; + char unused; }; struct AuxiliaryCLRToken { @@ -392,7 +413,6 @@ namespace COFF { AuxiliaryFunctionDefinition FunctionDefinition; AuxiliarybfAndefSymbol bfAndefSymbol; AuxiliaryWeakExternal WeakExternal; - AuxiliaryFile File; AuxiliarySectionDefinition SectionDefinition; }; @@ -495,12 +515,14 @@ namespace COFF { uint32_t SizeOfHeaders; uint32_t CheckSum; uint16_t Subsystem; + // FIXME: This should be DllCharacteristics to match the COFF spec. uint16_t DLLCharacteristics; uint32_t SizeOfStackReserve; uint32_t SizeOfStackCommit; uint32_t SizeOfHeapReserve; uint32_t SizeOfHeapCommit; uint32_t LoaderFlags; + // FIXME: This should be NumberOfRvaAndSizes to match the COFF spec. uint32_t NumberOfRvaAndSize; }; @@ -524,7 +546,9 @@ namespace COFF { BOUND_IMPORT, IAT, DELAY_IMPORT_DESCRIPTOR, - CLR_RUNTIME_HEADER + CLR_RUNTIME_HEADER, + + NUM_DATA_DIRECTORIES }; enum WindowsSubsystem { @@ -642,13 +666,18 @@ namespace COFF { enum CodeViewLineTableIdentifiers { DEBUG_SECTION_MAGIC = 0x4, + DEBUG_SYMBOL_SUBSECTION = 0xF1, DEBUG_LINE_TABLE_SUBSECTION = 0xF2, DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4 + DEBUG_INDEX_SUBSECTION = 0xF4, + + // Symbol subsections are split into records of different types. + DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, + DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; - inline bool isReservedSectionNumber(int N) { - return N == IMAGE_SYM_UNDEFINED || N > MaxNumberOfSections; + inline bool isReservedSectionNumber(int32_t SectionNumber) { + return SectionNumber <= 0; } } // End namespace COFF. diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index beed31a..6ba5efa 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -243,6 +243,26 @@ inline typename cast_retty::ret_type cast(Y *Val) { // accepted. // template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +cast_or_null(const Y &Val) { + if (!Val) + return nullptr; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + +template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +cast_or_null(Y &Val) { + if (!Val) + return nullptr; + assert(isa(Val) && "cast_or_null() argument of incompatible type!"); + return cast(Val); +} + +template LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type cast_or_null(Y *Val) { if (!Val) return nullptr; @@ -282,6 +302,20 @@ dyn_cast(Y *Val) { // value is accepted. // template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +dyn_cast_or_null(const Y &Val) { + return (Val && isa(Val)) ? cast(Val) : nullptr; +} + +template +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if< + !is_simple_type::value, typename cast_retty::ret_type>::type +dyn_cast_or_null(Y &Val) { + return (Val && isa(Val)) ? cast(Val) : nullptr; +} + +template LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty::ret_type dyn_cast_or_null(Y *Val) { return (Val && isa(Val)) ? cast(Val) : nullptr; diff --git a/include/llvm/Support/CodeGen.h b/include/llvm/Support/CodeGen.h index 240eba6..243f2dd 100644 --- a/include/llvm/Support/CodeGen.h +++ b/include/llvm/Support/CodeGen.h @@ -30,6 +30,10 @@ namespace llvm { enum Model { Default, JITDefault, Small, Kernel, Medium, Large }; } + namespace PICLevel { + enum Level { Default=0, Small=1, Large=2 }; + } + // TLS models. namespace TLSModel { enum Model { diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index fdd90120..1c06bf5 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -40,7 +40,7 @@ namespace cl { //===----------------------------------------------------------------------===// // ParseCommandLineOptions - Command line option processing entry point. // -void ParseCommandLineOptions(int argc, const char * const *argv, +void ParseCommandLineOptions(int argc, const char *const *argv, const char *Overview = nullptr); //===----------------------------------------------------------------------===// @@ -66,7 +66,6 @@ void SetVersionPrinter(void (*func)()); /// information specific to the tool. void AddExtraVersionPrinter(void (*func)()); - // PrintOptionValues - Print option values. // With -print-options print the difference between option values and defaults. // With -print-all-options print all option values. @@ -80,11 +79,11 @@ void MarkOptionsChanged(); // Flags permitted to be passed to command line arguments // -enum NumOccurrencesFlag { // Flags for the number of occurrences allowed - Optional = 0x00, // Zero or One occurrence - ZeroOrMore = 0x01, // Zero or more occurrences allowed - Required = 0x02, // One occurrence required - OneOrMore = 0x03, // One or more occurrences required +enum NumOccurrencesFlag { // Flags for the number of occurrences allowed + Optional = 0x00, // Zero or One occurrence + ZeroOrMore = 0x01, // Zero or more occurrences allowed + Required = 0x02, // One occurrence required + OneOrMore = 0x03, // One or more occurrences required // ConsumeAfter - Indicates that this option is fed anything that follows the // last positional argument required by the application (it is an error if @@ -93,20 +92,20 @@ enum NumOccurrencesFlag { // Flags for the number of occurrences allowed // found. Once a filename is found, all of the succeeding arguments are // passed, unprocessed, to the ConsumeAfter option. // - ConsumeAfter = 0x04 + ConsumeAfter = 0x04 }; -enum ValueExpected { // Is a value required for the option? +enum ValueExpected { // Is a value required for the option? // zero reserved for the unspecified value - ValueOptional = 0x01, // The value can appear... or not - ValueRequired = 0x02, // The value is required to appear! - ValueDisallowed = 0x03 // A value may not be specified (for flags) + ValueOptional = 0x01, // The value can appear... or not + ValueRequired = 0x02, // The value is required to appear! + ValueDisallowed = 0x03 // A value may not be specified (for flags) }; -enum OptionHidden { // Control whether -help shows this option - NotHidden = 0x00, // Option included in -help & -help-hidden - Hidden = 0x01, // -help doesn't, but -help-hidden does - ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x00, // Option included in -help & -help-hidden + Hidden = 0x01, // -help doesn't, but -help-hidden does + ReallyHidden = 0x02 // Neither -help nor -help-hidden show this arg }; // Formatting flags - This controls special features that the option might have @@ -125,16 +124,16 @@ enum OptionHidden { // Control whether -help shows this option // enum FormattingFlags { - NormalFormatting = 0x00, // Nothing special - Positional = 0x01, // Is a positional argument, no '-' required - Prefix = 0x02, // Can this option directly prefix its value? - Grouping = 0x03 // Can this option group with other options? + NormalFormatting = 0x00, // Nothing special + Positional = 0x01, // Is a positional argument, no '-' required + Prefix = 0x02, // Can this option directly prefix its value? + Grouping = 0x03 // Can this option group with other options? }; -enum MiscFlags { // Miscellaneous flags to adjust argument - CommaSeparated = 0x01, // Should this cl::list split between commas? - PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? - Sink = 0x04 // Should this cl::list eat all unknown options? +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x01, // Should this cl::list split between commas? + PositionalEatsArgs = 0x02, // Should this positional cl::list eat -args? + Sink = 0x04 // Should this cl::list eat all unknown options? }; //===----------------------------------------------------------------------===// @@ -145,9 +144,13 @@ private: const char *const Name; const char *const Description; void registerCategory(); + public: - OptionCategory(const char *const Name, const char *const Description = nullptr) - : Name(Name), Description(Description) { registerCategory(); } + OptionCategory(const char *const Name, + const char *const Description = nullptr) + : Name(Name), Description(Description) { + registerCategory(); + } const char *getName() const { return Name; } const char *getDescription() const { return Description; } }; @@ -176,7 +179,7 @@ class Option { // Out of line virtual function to provide home for the class. virtual void anchor(); - int NumOccurrences; // The number of times specified + int NumOccurrences; // The number of times specified // Occurrences, HiddenFlag, and Formatting are all enum types but to avoid // problems with signed enums in bitfields. unsigned Occurrences : 3; // enum NumOccurrencesFlag @@ -186,9 +189,9 @@ class Option { unsigned HiddenFlag : 2; // enum OptionHidden unsigned Formatting : 2; // enum FormattingFlags unsigned Misc : 3; - unsigned Position; // Position of last occurrence of the option - unsigned AdditionalVals;// Greater than 0 for multi-valued option. - Option *NextRegistered; // Singly linked list of registered options. + unsigned Position; // Position of last occurrence of the option + unsigned AdditionalVals; // Greater than 0 for multi-valued option. + Option *NextRegistered; // Singly linked list of registered options. public: const char *ArgStr; // The argument string itself (ex: "help", "o") @@ -200,8 +203,7 @@ public: return (enum NumOccurrencesFlag)Occurrences; } inline enum ValueExpected getValueExpectedFlag() const { - return Value ? ((enum ValueExpected)Value) - : getValueExpectedFlagDefault(); + return Value ? ((enum ValueExpected)Value) : getValueExpectedFlagDefault(); } inline enum OptionHidden getOptionHiddenFlag() const { return (enum OptionHidden)HiddenFlag; @@ -209,9 +211,7 @@ public: inline enum FormattingFlags getFormattingFlag() const { return (enum FormattingFlags)Formatting; } - inline unsigned getMiscFlags() const { - return Misc; - } + inline unsigned getMiscFlags() const { return Misc; } inline unsigned getPosition() const { return Position; } inline unsigned getNumAdditionalVals() const { return AdditionalVals; } @@ -224,25 +224,24 @@ public: void setArgStr(const char *S) { ArgStr = S; } void setDescription(const char *S) { HelpStr = S; } void setValueStr(const char *S) { ValueStr = S; } - void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { - Occurrences = Val; - } + void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } void setValueExpectedFlag(enum ValueExpected Val) { Value = Val; } void setHiddenFlag(enum OptionHidden Val) { HiddenFlag = Val; } void setFormattingFlag(enum FormattingFlags V) { Formatting = V; } void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } void setCategory(OptionCategory &C) { Category = &C; } + protected: explicit Option(enum NumOccurrencesFlag OccurrencesFlag, enum OptionHidden Hidden) - : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), - HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), - Position(0), AdditionalVals(0), NextRegistered(nullptr), - ArgStr(""), HelpStr(""), ValueStr(""), Category(&GeneralCategory) { - } + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), + AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""), + ValueStr(""), Category(&GeneralCategory) {} inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } + public: // addArgument - Register this argument with the commandline system. // @@ -266,12 +265,12 @@ public: virtual void printOptionValue(size_t GlobalWidth, bool Force) const = 0; - virtual void getExtraOptionNames(SmallVectorImpl &) {} + virtual void getExtraOptionNames(SmallVectorImpl &) {} // addOccurrence - Wrapper around handleOccurrence that enforces Flags. // - virtual bool addOccurrence(unsigned pos, StringRef ArgName, - StringRef Value, bool MultiArg = false); + virtual bool addOccurrence(unsigned pos, StringRef ArgName, StringRef Value, + bool MultiArg = false); // Prints option name followed by message. Always returns true. bool error(const Twine &Message, StringRef ArgName = StringRef()); @@ -281,7 +280,6 @@ public: virtual ~Option() {} }; - //===----------------------------------------------------------------------===// // Command line option modifiers that can be used to modify the behavior of // command line option parsers... @@ -306,36 +304,31 @@ struct value_desc { // the default constructor for the argument type does not give you what you // want. This is only valid on "opt" arguments, not on "list" arguments. // -template -struct initializer { +template struct initializer { const Ty &Init; initializer(const Ty &Val) : Init(Val) {} - template - void apply(Opt &O) const { O.setInitialValue(Init); } + template void apply(Opt &O) const { O.setInitialValue(Init); } }; -template -initializer init(const Ty &Val) { +template initializer init(const Ty &Val) { return initializer(Val); } - // location - Allow the user to specify which external variable they want to // store the results of the command line argument processing into, if they don't // want to store it in the option itself. // -template -struct LocationClass { +template struct LocationClass { Ty &Loc; LocationClass(Ty &L) : Loc(L) {} - template - void apply(Opt &O) const { O.setLocation(O, Loc); } + template void apply(Opt &O) const { O.setLocation(O, Loc); } }; -template -LocationClass location(Ty &L) { return LocationClass(L); } +template LocationClass location(Ty &L) { + return LocationClass(L); +} // cat - Specifiy the Option category for the command line argument to belong // to. @@ -343,11 +336,9 @@ struct cat { OptionCategory &Category; cat(OptionCategory &c) : Category(c) {} - template - void apply(Opt &O) const { O.setCategory(Category); } + template void apply(Opt &O) const { O.setCategory(Category); } }; - //===----------------------------------------------------------------------===// // OptionValue class @@ -360,11 +351,11 @@ private: virtual void anchor(); }; -template struct OptionValue; +template struct OptionValue; // The default value safely does nothing. Option value printing is only // best-effort. -template +template struct OptionValueBase : public GenericOptionValue { // Temporary storage for argument passing. typedef OptionValue WrapperType; @@ -374,21 +365,20 @@ struct OptionValueBase : public GenericOptionValue { const DataType &getValue() const { llvm_unreachable("no default value"); } // Some options may take their value from a different data type. - template - void setValue(const DT& /*V*/) {} + template void setValue(const DT & /*V*/) {} - bool compare(const DataType &/*V*/) const { return false; } + bool compare(const DataType & /*V*/) const { return false; } - bool compare(const GenericOptionValue& /*V*/) const override { + bool compare(const GenericOptionValue & /*V*/) const override { return false; } }; // Simple copy of the option value. -template -class OptionValueCopy : public GenericOptionValue { +template class OptionValueCopy : public GenericOptionValue { DataType Value; bool Valid; + public: OptionValueCopy() : Valid(false) {} @@ -399,37 +389,36 @@ public: return Value; } - void setValue(const DataType &V) { Valid = true; Value = V; } - - bool compare(const DataType &V) const { - return Valid && (Value != V); + void setValue(const DataType &V) { + Valid = true; + Value = V; } + bool compare(const DataType &V) const { return Valid && (Value != V); } + bool compare(const GenericOptionValue &V) const override { const OptionValueCopy &VC = - static_cast< const OptionValueCopy& >(V); - if (!VC.hasValue()) return false; + static_cast &>(V); + if (!VC.hasValue()) + return false; return compare(VC.getValue()); } }; // Non-class option values. -template +template struct OptionValueBase : OptionValueCopy { typedef DataType WrapperType; }; // Top-level option class. -template +template struct OptionValue : OptionValueBase::value> { OptionValue() {} - OptionValue(const DataType& V) { - this->setValue(V); - } + OptionValue(const DataType &V) { this->setValue(V); } // Some options may take their value from a different data type. - template - OptionValue &operator=(const DT& V) { + template OptionValue &operator=(const DT &V) { this->setValue(V); return *this; } @@ -437,36 +426,33 @@ struct OptionValue : OptionValueBase::value> { // Other safe-to-copy-by-value common option types. enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; -template<> +template <> struct OptionValue : OptionValueCopy { typedef cl::boolOrDefault WrapperType; OptionValue() {} - OptionValue(const cl::boolOrDefault& V) { - this->setValue(V); - } - OptionValue &operator=(const cl::boolOrDefault& V) { + OptionValue(const cl::boolOrDefault &V) { this->setValue(V); } + OptionValue &operator=(const cl::boolOrDefault &V) { setValue(V); return *this; } + private: void anchor() override; }; -template<> -struct OptionValue : OptionValueCopy { +template <> struct OptionValue : OptionValueCopy { typedef StringRef WrapperType; OptionValue() {} - OptionValue(const std::string& V) { - this->setValue(V); - } - OptionValue &operator=(const std::string& V) { + OptionValue(const std::string &V) { this->setValue(V); } + OptionValue &operator=(const std::string &V) { setValue(V); return *this; } + private: void anchor() override; }; @@ -476,20 +462,20 @@ private: // #define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC #define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC -#define clEnumValEnd (reinterpret_cast(0)) +#define clEnumValEnd (reinterpret_cast(0)) // values - For custom data types, allow specifying a group of values together // as the values that go into the mapping that the option handler uses. Note // that the values list must always have a 0 at the end of the list to indicate // that the list has ended. // -template -class ValuesClass { +template class ValuesClass { // Use a vector instead of a map, because the lists should be short, // the overhead is less, and most importantly, it keeps them in the order // inserted so we can print our option out nicely. - SmallVector >,4> Values; + SmallVector>, 4> Values; void processValues(va_list Vals); + public: ValuesClass(const char *EnumName, DataType Val, const char *Desc, va_list ValueArgs) { @@ -500,27 +486,26 @@ public: while (const char *enumName = va_arg(ValueArgs, const char *)) { DataType EnumVal = static_cast(va_arg(ValueArgs, int)); const char *EnumDesc = va_arg(ValueArgs, const char *); - Values.push_back(std::make_pair(enumName, // Add value to value map + Values.push_back(std::make_pair(enumName, // Add value to value map std::make_pair(EnumVal, EnumDesc))); } } - template - void apply(Opt &O) const { + template void apply(Opt &O) const { for (size_t i = 0, e = Values.size(); i != e; ++i) O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, Values[i].second.second); } }; -template -ValuesClass END_WITH_NULL values(const char *Arg, DataType Val, - const char *Desc, ...) { - va_list ValueArgs; - va_start(ValueArgs, Desc); - ValuesClass Vals(Arg, Val, Desc, ValueArgs); - va_end(ValueArgs); - return Vals; +template +ValuesClass LLVM_END_WITH_NULL +values(const char *Arg, DataType Val, const char *Desc, ...) { + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; } //===----------------------------------------------------------------------===// @@ -539,13 +524,14 @@ class generic_parser_base { protected: class GenericOptionInfo { public: - GenericOptionInfo(const char *name, const char *helpStr) : - Name(name), HelpStr(helpStr) {} + GenericOptionInfo(const char *name, const char *helpStr) + : Name(name), HelpStr(helpStr) {} const char *Name; const char *HelpStr; }; + public: - virtual ~generic_parser_base() {} // Base class should have virtual-dtor + virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to // indicate how many entries are in Values. @@ -576,7 +562,7 @@ public: // // Template definition ensures that the option and default have the same // DataType (via the same AnyOptionValue). - template + template void printOptionDiff(const Option &O, const AnyOptionValue &V, const AnyOptionValue &Default, size_t GlobalWidth) const { @@ -590,7 +576,7 @@ public: hasArgStr = O.hasArgStr(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) { + void getExtraOptionNames(SmallVectorImpl &OptionNames) { // If there has been no argstr specified, that means that we need to add an // argument for every possible option. This ensures that our options are // vectored to us. @@ -599,7 +585,6 @@ public: OptionNames.push_back(getOption(i)); } - enum ValueExpected getValueExpectedFlagDefault() const { // If there is an ArgStr specified, then we are of the form: // @@ -633,16 +618,16 @@ protected: // command line option for -help. Because this is a simple mapping parser, the // data type can be any unsupported type. // -template -class parser : public generic_parser_base { +template class parser : public generic_parser_base { protected: class OptionInfo : public GenericOptionInfo { public: - OptionInfo(const char *name, DataType v, const char *helpStr) : - GenericOptionInfo(name, helpStr), V(v) {} + OptionInfo(const char *name, DataType v, const char *helpStr) + : GenericOptionInfo(name, helpStr), V(v) {} OptionValue V; }; SmallVector Values; + public: typedef DataType parser_data_type; @@ -690,14 +675,14 @@ public: void removeLiteralOption(const char *Name) { unsigned N = findOption(Name); assert(N != Values.size() && "Option not found!"); - Values.erase(Values.begin()+N); + Values.erase(Values.begin() + N); } }; //-------------------------------------------------- // basic_parser - Super class of parsers to provide boilerplate code // -class basic_parser_impl { // non-template implementation of basic_parser +class basic_parser_impl { // non-template implementation of basic_parser public: virtual ~basic_parser_impl() {} @@ -705,7 +690,7 @@ public: return ValueRequired; } - void getExtraOptionNames(SmallVectorImpl &) {} + void getExtraOptionNames(SmallVectorImpl &) {} void initialize(Option &) {} @@ -735,8 +720,7 @@ protected: // basic_parser - The real basic parser is just a template wrapper that provides // a typedef for the provided data type. // -template -class basic_parser : public basic_parser_impl { +template class basic_parser : public basic_parser_impl { public: typedef DataType parser_data_type; typedef OptionValue OptVal; @@ -745,18 +729,14 @@ public: //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { const char *ArgStr; -public: +public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); - template - void initialize(Opt &O) { - ArgStr = O.ArgStr; - } + template void initialize(Opt &O) { ArgStr = O.ArgStr; } enum ValueExpected getValueExpectedFlagDefault() const { return ValueOptional; @@ -776,8 +756,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); @@ -801,8 +780,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); @@ -819,12 +797,10 @@ public: EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); - //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); @@ -844,7 +820,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> +template <> class parser : public basic_parser { public: // parse - Return true on error. @@ -866,8 +842,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); @@ -887,8 +862,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); @@ -908,8 +882,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { @@ -932,8 +905,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); //-------------------------------------------------- // parser // -template<> -class parser : public basic_parser { +template <> class parser : public basic_parser { public: // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, char &Value) { @@ -960,7 +932,7 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser); // parser to handle all the template nastiness. // This overloaded function is selected by the generic parser. -template +template void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, const OptionValue
&Default, size_t GlobalWidth) { OptionValue
OV = V; @@ -969,18 +941,16 @@ void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, // This is instantiated for basic parsers when the parsed value has a different // type than the option value. e.g. HelpPrinter. -template -struct OptionDiffPrinter { - void print(const Option &O, const parser P, const ValDT &/*V*/, - const OptionValue &/*Default*/, size_t GlobalWidth) { +template struct OptionDiffPrinter { + void print(const Option &O, const parser P, const ValDT & /*V*/, + const OptionValue & /*Default*/, size_t GlobalWidth) { P.printOptionNoValue(O, GlobalWidth); } }; // This is instantiated for basic parsers when the parsed value has the same // type as the option value. -template -struct OptionDiffPrinter { +template struct OptionDiffPrinter { void print(const Option &O, const parser
P, const DT &V, const OptionValue
&Default, size_t GlobalWidth) { P.printOptionDiff(O, V, Default, GlobalWidth); @@ -989,15 +959,14 @@ struct OptionDiffPrinter { // This overloaded function is selected by the basic parser, which may parse a // different type than the option type. -template +template void printOptionDiff( - const Option &O, - const basic_parser &P, - const ValDT &V, const OptionValue &Default, - size_t GlobalWidth) { + const Option &O, + const basic_parser &P, + const ValDT &V, const OptionValue &Default, size_t GlobalWidth) { OptionDiffPrinter printer; - printer.print(O, static_cast(P), V, Default, + printer.print(O, static_cast(P), V, Default, GlobalWidth); } @@ -1007,46 +976,47 @@ void printOptionDiff( // not correctly respond to the apply method). Because the syntax to use this // is a pain, we have the 'apply' method below to handle the nastiness... // -template struct applicator { - template - static void opt(const Mod &M, Opt &O) { M.apply(O); } +template struct applicator { + template static void opt(const Mod &M, Opt &O) { M.apply(O); } }; // Handle const char* as a special case... -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { - template - static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +template <> struct applicator { + template static void opt(const char *Str, Opt &O) { + O.setArgStr(Str); + } }; -template<> struct applicator { +template <> struct applicator { static void opt(NumOccurrencesFlag N, Option &O) { O.setNumOccurrencesFlag(N); } }; -template<> struct applicator { +template <> struct applicator { static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } }; -template<> struct applicator { +template <> struct applicator { static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } }; -template<> struct applicator { +template <> struct applicator { static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } }; -template<> struct applicator { +template <> struct applicator { static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } }; // apply method - Apply a modifier to an option in a type safe way. -template -void apply(const Mod &M, Opt *O) { +template void apply(const Mod &M, Opt *O) { applicator::opt(M, *O); } @@ -1057,16 +1027,17 @@ void apply(const Mod &M, Opt *O) { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template +template class opt_storage { - DataType *Location; // Where to store the object... + DataType *Location; // Where to store the object... OptionValue Default; void check_location() const { assert(Location && "cl::location(...) not specified for a command " - "line option with external storage, " - "or cl::init specified before cl::location()!!"); + "line option with external storage, " + "or cl::init specified before cl::location()!!"); } + public: opt_storage() : Location(nullptr) {} @@ -1078,16 +1049,21 @@ public: return false; } - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { check_location(); *Location = V; if (initial) Default = V; } - DataType &getValue() { check_location(); return *Location; } - const DataType &getValue() const { check_location(); return *Location; } + DataType &getValue() { + check_location(); + return *Location; + } + const DataType &getValue() const { + check_location(); + return *Location; + } operator DataType() const { return this->getValue(); } @@ -1098,13 +1074,12 @@ public: // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template -class opt_storage : public DataType { +template +class opt_storage : public DataType { public: OptionValue Default; - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { DataType::operator=(V); if (initial) Default = V; @@ -1120,8 +1095,7 @@ public: // this case, we store an instance through containment, and overload operators // to get at the value. // -template -class opt_storage { +template class opt_storage { public: DataType Value; OptionValue Default; @@ -1130,8 +1104,7 @@ public: // type. opt_storage() : Value(DataType()), Default(DataType()) {} - template - void setValue(const T &V, bool initial = false) { + template void setValue(const T &V, bool initial = false) { Value = V; if (initial) Default = V; @@ -1147,12 +1120,11 @@ public: DataType operator->() const { return Value; } }; - //===----------------------------------------------------------------------===// // opt - A scalar command line option. // template > + class ParserClass = parser> class opt : public Option, public opt_storage::value> { @@ -1161,9 +1133,9 @@ class opt : public Option, bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse error! + return true; // Parse error! this->setValue(Val); this->setPosition(pos); return false; @@ -1172,20 +1144,23 @@ class opt : public Option, enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } void printOptionValue(size_t GlobalWidth, bool Force) const override { if (Force || this->getDefault().compare(this->getValue())) { - cl::printOptionDiff( - *this, Parser, this->getValue(), this->getDefault(), GlobalWidth); + cl::printOptionDiff(*this, Parser, this->getValue(), + this->getDefault(), GlobalWidth); } } @@ -1193,81 +1168,107 @@ class opt : public Option, addArgument(); Parser.initialize(*this); } + public: // setInitialValue - Used by the cl::init modifier... void setInitialValue(const DataType &V) { this->setValue(V, true); } ParserClass &getParser() { return Parser; } - template - DataType &operator=(const T &Val) { + template DataType &operator=(const T &Val) { this->setValue(Val); return this->getValue(); } // One option... - template - explicit opt(const M0t &M0) : Option(Optional, NotHidden) { + template + explicit opt(const M0t &M0) + : Option(Optional, NotHidden) { apply(M0, this); done(); } // Two options... - template - opt(const M0t &M0, const M1t &M1) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); + template + opt(const M0t &M0, const M1t &M1) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template - opt(const M0t &M0, const M1t &M1, - const M2t &M2) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); + template + opt(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, - const M3t &M3) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } // Five options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); apply(M4, this); done(); } // Six options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, + const M5t &M5) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); done(); } // Seven options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, - const M6t &M6) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, + const M5t &M5, const M6t &M6) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); done(); } // Eight options... - template - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(Optional, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + template + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, + const M5t &M5, const M6t &M6, const M7t &M7) + : Option(Optional, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); + apply(M7, this); done(); } }; @@ -1285,9 +1286,8 @@ EXTERN_TEMPLATE_INSTANTIATION(class opt); // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class list_storage { - StorageClass *Location; // Where to store the object... +template class list_storage { + StorageClass *Location; // Where to store the object... public: list_storage() : Location(0) {} @@ -1299,32 +1299,30 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); Location->push_back(V); } }; - // Define how to hold a class type object, such as a string. Since we can // inherit from a class, we do so. This makes us exactly compatible with the // object in all cases that it is used. // -template +template class list_storage : public std::vector { public: - template - void addValue(const T &V) { std::vector::push_back(V); } + template void addValue(const T &V) { + std::vector::push_back(V); + } }; - //===----------------------------------------------------------------------===// // list - A list of command line options. // template > + class ParserClass = parser> class list : public Option, public list_storage { std::vector Positions; ParserClass Parser; @@ -1332,16 +1330,17 @@ class list : public Option, public list_storage { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! list_storage::addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1349,19 +1348,22 @@ class list : public Option, public list_storage { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: list options don't currently store their default value. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); Parser.initialize(*this); } + public: ParserClass &getParser() { return Parser; } @@ -1370,71 +1372,96 @@ public: return Positions[optnum]; } - void setNumAdditionalVals(unsigned n) { - Option::setNumAdditionalVals(n); - } + void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } // One option... - template - explicit list(const M0t &M0) : Option(ZeroOrMore, NotHidden) { + template + explicit list(const M0t &M0) + : Option(ZeroOrMore, NotHidden) { apply(M0, this); done(); } // Two options... - template - list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); + template + list(const M0t &M0, const M1t &M1) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template + template list(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template + template list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } // Five options... - template + template list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + const M4t &M4) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); apply(M4, this); done(); } // Six options... - template + template list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); + const M4t &M4, const M5t &M5) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); done(); } // Seven options... - template + template list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); done(); } // Eight options... - template + template list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); + apply(M7, this); done(); } }; @@ -1445,10 +1472,11 @@ struct multi_val { explicit multi_val(unsigned N) : AdditionalVals(N) {} template - void apply(list &L) const { L.setNumAdditionalVals(AdditionalVals); } + void apply(list &L) const { + L.setNumAdditionalVals(AdditionalVals); + } }; - //===----------------------------------------------------------------------===// // bits_storage class @@ -1456,15 +1484,13 @@ struct multi_val { // assumes the user will specify a variable to store the data into with the // cl::location(x) modifier. // -template -class bits_storage { - unsigned *Location; // Where to store the bits... +template class bits_storage { + unsigned *Location; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = reinterpret_cast(V); assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } @@ -1478,57 +1504,45 @@ public: return false; } - template - void addValue(const T &V) { + template void addValue(const T &V) { assert(Location != 0 && "cl::location(...) not specified for a command " - "line option with external storage!"); + "line option with external storage!"); *Location |= Bit(V); } unsigned getBits() { return *Location; } - template - bool isSet(const T &V) { + template bool isSet(const T &V) { return (*Location & Bit(V)) != 0; } }; - // Define how to hold bits. Since we can inherit from a class, we do so. // This makes us exactly compatible with the bits in all cases that it is used. // -template -class bits_storage { - unsigned Bits; // Where to store the bits... +template class bits_storage { + unsigned Bits; // Where to store the bits... - template - static unsigned Bit(const T &V) { + template static unsigned Bit(const T &V) { unsigned BitPos = (unsigned)V; assert(BitPos < sizeof(unsigned) * CHAR_BIT && - "enum exceeds width of bit vector!"); + "enum exceeds width of bit vector!"); return 1 << BitPos; } public: - template - void addValue(const T &V) { - Bits |= Bit(V); - } + template void addValue(const T &V) { Bits |= Bit(V); } unsigned getBits() { return Bits; } - template - bool isSet(const T &V) { - return (Bits & Bit(V)) != 0; - } + template bool isSet(const T &V) { return (Bits & Bit(V)) != 0; } }; - //===----------------------------------------------------------------------===// // bits - A bit vector of command options. // template > + class ParserClass = parser> class bits : public Option, public bits_storage { std::vector Positions; ParserClass Parser; @@ -1536,16 +1550,17 @@ class bits : public Option, public bits_storage { enum ValueExpected getValueExpectedFlagDefault() const override { return Parser.getValueExpectedFlagDefault(); } - void getExtraOptionNames(SmallVectorImpl &OptionNames) override { + void + getExtraOptionNames(SmallVectorImpl &OptionNames) override { return Parser.getExtraOptionNames(OptionNames); } bool handleOccurrence(unsigned pos, StringRef ArgName, StringRef Arg) override { typename ParserClass::parser_data_type Val = - typename ParserClass::parser_data_type(); + typename ParserClass::parser_data_type(); if (Parser.parse(*this, ArgName, Arg, Val)) - return true; // Parse Error! + return true; // Parse Error! this->addValue(Val); setPosition(pos); Positions.push_back(pos); @@ -1553,19 +1568,22 @@ class bits : public Option, public bits_storage { } // Forward printing stuff to the parser... - size_t getOptionWidth() const override {return Parser.getOptionWidth(*this);} + size_t getOptionWidth() const override { + return Parser.getOptionWidth(*this); + } void printOptionInfo(size_t GlobalWidth) const override { Parser.printOptionInfo(*this, GlobalWidth); } // Unimplemented: bits options don't currently store their default values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } void done() { addArgument(); Parser.initialize(*this); } + public: ParserClass &getParser() { return Parser; } @@ -1575,66 +1593,93 @@ public: } // One option... - template - explicit bits(const M0t &M0) : Option(ZeroOrMore, NotHidden) { + template + explicit bits(const M0t &M0) + : Option(ZeroOrMore, NotHidden) { apply(M0, this); done(); } // Two options... - template - bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); + template + bits(const M0t &M0, const M1t &M1) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template + template bits(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template + template bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } // Five options... - template + template bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + const M4t &M4) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); apply(M4, this); done(); } // Six options... - template + template bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); + const M4t &M4, const M5t &M5) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); done(); } // Seven options... - template + template bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); done(); } // Eight options... - template + template bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, - const M7t &M7) : Option(ZeroOrMore, NotHidden) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); - apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) + : Option(ZeroOrMore, NotHidden) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); + apply(M4, this); + apply(M5, this); + apply(M6, this); + apply(M7, this); done(); } }; @@ -1646,11 +1691,11 @@ public: class alias : public Option { Option *AliasFor; bool handleOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Arg) override { + StringRef Arg) override { return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); } - bool addOccurrence(unsigned pos, StringRef /*ArgName*/, - StringRef Value, bool MultiArg = false) override { + bool addOccurrence(unsigned pos, StringRef /*ArgName*/, StringRef Value, + bool MultiArg = false) override { return AliasFor->addOccurrence(pos, AliasFor->ArgStr, Value, MultiArg); } // Handle printing stuff... @@ -1658,8 +1703,8 @@ class alias : public Option { void printOptionInfo(size_t GlobalWidth) const override; // Aliases do not need to print their values. - void printOptionValue(size_t /*GlobalWidth*/, - bool /*Force*/) const override {} + void printOptionValue(size_t /*GlobalWidth*/, bool /*Force*/) const override { + } ValueExpected getValueExpectedFlagDefault() const override { return AliasFor->getValueExpectedFlag(); @@ -1670,8 +1715,9 @@ class alias : public Option { error("cl::alias must have argument name specified!"); if (!AliasFor) error("cl::alias must have an cl::aliasopt(option) specified!"); - addArgument(); + addArgument(); } + public: void setAliasFor(Option &O) { if (AliasFor) @@ -1680,30 +1726,37 @@ public: } // One option... - template - explicit alias(const M0t &M0) : Option(Optional, Hidden), AliasFor(nullptr) { + template + explicit alias(const M0t &M0) + : Option(Optional, Hidden), AliasFor(nullptr) { apply(M0, this); done(); } // Two options... - template + template alias(const M0t &M0, const M1t &M1) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(M0, this); + apply(M1, this); done(); } // Three options... - template + template alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(M0, this); + apply(M1, this); + apply(M2, this); done(); } // Four options... - template + template alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + : Option(Optional, Hidden), AliasFor(nullptr) { + apply(M0, this); + apply(M1, this); + apply(M2, this); + apply(M3, this); done(); } }; @@ -1720,8 +1773,8 @@ struct aliasopt { // printed to stderr at the end of the regular help, just before // exit is called. struct extrahelp { - const char * morehelp; - explicit extrahelp(const char* help); + const char *morehelp; + explicit extrahelp(const char *help); }; void PrintVersionMessage(); @@ -1733,8 +1786,7 @@ void PrintVersionMessage(); /// /// \param Hidden if true will print hidden options /// \param Categorized if true print options in categories -void PrintHelpMessage(bool Hidden=false, bool Categorized=false); - +void PrintHelpMessage(bool Hidden = false, bool Categorized = false); //===----------------------------------------------------------------------===// // Public interface for accessing registered options. @@ -1766,7 +1818,7 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). -void getRegisteredOptions(StringMap &Map); +void getRegisteredOptions(StringMap
\n"; + return; + } + + const unsigned ColsPerRow = 16; + + uint8_t *DataAddr = S.Address; + uint64_t LoadAddr = S.LoadAddress; + + unsigned StartPadding = LoadAddr & (ColsPerRow - 1); + unsigned BytesRemaining = S.Size; + + if (StartPadding) { + dbgs() << "\n" << format("0x%016" PRIx64, LoadAddr & ~(ColsPerRow - 1)) << ":"; + while (StartPadding--) + dbgs() << " "; + } + + while (BytesRemaining > 0) { + if ((LoadAddr & (ColsPerRow - 1)) == 0) + dbgs() << "\n" << format("0x%016" PRIx64, LoadAddr) << ":"; + + dbgs() << " " << format("%02x", *DataAddr); + + ++DataAddr; + ++LoadAddr; + --BytesRemaining; + } + + dbgs() << "\n"; +} +#endif + // Resolve the relocations for all symbols we currently know about. void RuntimeDyldImpl::resolveRelocations() { MutexGuard locked(lock); @@ -55,8 +90,10 @@ void RuntimeDyldImpl::resolveRelocations() { // entry provides the section to which the relocation will be applied. uint64_t Addr = Sections[i].LoadAddress; DEBUG(dbgs() << "Resolving relocations Section #" << i << "\t" - << format("%p", (uint8_t *)Addr) << "\n"); + << format("0x%x", Addr) << "\n"); + DEBUG(dumpSectionMemory(Sections[i], "before relocations")); resolveRelocationList(Relocations[i], Addr); + DEBUG(dumpSectionMemory(Sections[i], "after relocations")); Relocations.erase(i); } } @@ -88,40 +125,36 @@ static std::error_code getOffset(const SymbolRef &Sym, uint64_t &Result) { if (std::error_code EC = Sym.getSection(SecI)) return EC; - if (SecI == Obj->section_end()) { - Result = UnknownAddressOrSize; - return object_error::success; - } - - uint64_t SectionAddress; - if (std::error_code EC = SecI->getAddress(SectionAddress)) - return EC; + if (SecI == Obj->section_end()) { + Result = UnknownAddressOrSize; + return object_error::success; + } + uint64_t SectionAddress = SecI->getAddress(); Result = Address - SectionAddress; return object_error::success; } -ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { +std::pair +RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) { MutexGuard locked(lock); - std::unique_ptr Obj(InputObject); - if (!Obj) - return nullptr; + // Grab the first Section ID. We'll use this later to construct the underlying + // range for the returned LoadedObjectInfo. + unsigned SectionsAddedBeginIdx = Sections.size(); // Save information about our target - Arch = (Triple::ArchType)Obj->getArch(); - IsTargetLittleEndian = Obj->getObjectFile()->isLittleEndian(); + Arch = (Triple::ArchType)Obj.getArch(); + IsTargetLittleEndian = Obj.isLittleEndian(); // Compute the memory size required to load all sections to be loaded // and pass this information to the memory manager if (MemMgr->needsToReserveAllocationSpace()) { uint64_t CodeSize = 0, DataSizeRO = 0, DataSizeRW = 0; - computeTotalAllocSize(*Obj, CodeSize, DataSizeRO, DataSizeRW); + computeTotalAllocSize(Obj, CodeSize, DataSizeRO, DataSizeRW); MemMgr->reserveAllocationSpace(CodeSize, DataSizeRO, DataSizeRW); } - // Symbols found in this object - StringMap LocalSymbols; // Used sections from the object file ObjSectionToIDMap LocalSections; @@ -132,7 +165,7 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); - for (symbol_iterator I = Obj->begin_symbols(), E = Obj->end_symbols(); I != E; + for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { object::SymbolRef::Type SymType; StringRef Name; @@ -158,17 +191,15 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { SymType == object::SymbolRef::ST_Unknown) { uint64_t SectOffset; StringRef SectionData; - bool IsCode; - section_iterator SI = Obj->end_sections(); + section_iterator SI = Obj.section_end(); Check(getOffset(*I, SectOffset)); Check(I->getSection(SI)); - if (SI == Obj->end_sections()) + if (SI == Obj.section_end()) continue; Check(SI->getContents(SectionData)); - Check(SI->isText(IsCode)); + bool IsCode = SI->isText(); unsigned SectionID = - findOrEmitSection(*Obj, *SI, IsCode, LocalSections); - LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); + findOrEmitSection(Obj, *SI, IsCode, LocalSections); DEBUG(dbgs() << "\tOffset: " << format("%p", (uintptr_t)SectOffset) << " flags: " << Flags << " SID: " << SectionID); GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); @@ -179,11 +210,11 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { // Allocate common symbols if (CommonSize != 0) - emitCommonSymbols(*Obj, CommonSymbols, CommonSize, GlobalSymbolTable); + emitCommonSymbols(Obj, CommonSymbols, CommonSize, GlobalSymbolTable); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); - for (section_iterator SI = Obj->begin_sections(), SE = Obj->end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { unsigned SectionID = 0; StubMap Stubs; @@ -195,21 +226,26 @@ ObjectImage *RuntimeDyldImpl::loadObject(ObjectImage *InputObject) { if (I == E && !ProcessAllSections) continue; - bool IsCode = false; - Check(RelocatedSection->isText(IsCode)); + bool IsCode = RelocatedSection->isText(); SectionID = - findOrEmitSection(*Obj, *RelocatedSection, IsCode, LocalSections); + findOrEmitSection(Obj, *RelocatedSection, IsCode, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); for (; I != E;) - I = processRelocationRef(SectionID, I, *Obj, LocalSections, LocalSymbols, - Stubs); + I = processRelocationRef(SectionID, I, Obj, LocalSections, Stubs); + + // If there is an attached checker, notify it about the stubs for this + // section so that they can be verified. + if (Checker) + Checker->registerStubMap(Obj.getFileName(), SectionID, Stubs); } // Give the subclasses a chance to tie-up any loose ends. - finalizeLoad(*Obj, LocalSections); + finalizeLoad(Obj, LocalSections); - return Obj.release(); + unsigned SectionsAddedEndIdx = Sections.size(); + + return std::make_pair(SectionsAddedBeginIdx, SectionsAddedEndIdx); } // A helper method for computeTotalAllocSize. @@ -227,9 +263,37 @@ computeAllocationSizeForSections(std::vector &SectionSizes, return TotalSize; } +static bool isRequiredForExecution(const SectionRef &Section) { + const ObjectFile *Obj = Section.getObject(); + if (auto *ELFObj = dyn_cast(Obj)) + return ELFObj->getSectionFlags(Section) & ELF::SHF_ALLOC; + assert(isa(Obj)); + return true; + } + +static bool isReadOnlyData(const SectionRef &Section) { + const ObjectFile *Obj = Section.getObject(); + if (auto *ELFObj = dyn_cast(Obj)) + return !(ELFObj->getSectionFlags(Section) & + (ELF::SHF_WRITE | ELF::SHF_EXECINSTR)); + assert(isa(Obj)); + return false; +} + +static bool isZeroInit(const SectionRef &Section) { + const ObjectFile *Obj = Section.getObject(); + if (auto *ELFObj = dyn_cast(Obj)) + return ELFObj->getSectionType(Section) == ELF::SHT_NOBITS; + + auto *MachO = cast(Obj); + unsigned SectionType = MachO->getSectionType(Section); + return SectionType == MachO::S_ZEROFILL || + SectionType == MachO::S_GB_ZEROFILL; +} + // Compute an upper bound of the memory size that is required to load all // sections -void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, +void RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, uint64_t &DataSizeRO, uint64_t &DataSizeRW) { @@ -241,24 +305,19 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, // Collect sizes of all sections to be loaded; // also determine the max alignment of all sections - for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { const SectionRef &Section = *SI; - bool IsRequired; - Check(Section.isRequiredForExecution(IsRequired)); + bool IsRequired = isRequiredForExecution(Section); // Consider only the sections that are required to be loaded for execution if (IsRequired) { - uint64_t DataSize = 0; - uint64_t Alignment64 = 0; - bool IsCode = false; - bool IsReadOnly = false; StringRef Name; - Check(Section.getSize(DataSize)); - Check(Section.getAlignment(Alignment64)); - Check(Section.isText(IsCode)); - Check(Section.isReadOnlyData(IsReadOnly)); + uint64_t DataSize = Section.getSize(); + uint64_t Alignment64 = Section.getAlignment(); + bool IsCode = Section.isText(); + bool IsReadOnly = isReadOnlyData(Section); Check(Section.getName(Name)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; @@ -292,7 +351,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, // Compute the size of all common symbols uint64_t CommonSize = 0; - for (symbol_iterator I = Obj.begin_symbols(), E = Obj.end_symbols(); I != E; + for (symbol_iterator I = Obj.symbol_begin(), E = Obj.symbol_end(); I != E; ++I) { uint32_t Flags = I->getFlags(); if (Flags & SymbolRef::SF_Common) { @@ -317,7 +376,7 @@ void RuntimeDyldImpl::computeTotalAllocSize(ObjectImage &Obj, } // compute stub buffer size for the given section -unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, +unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section) { unsigned StubSize = getMaxStubSize(); if (StubSize == 0) { @@ -327,7 +386,7 @@ unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, // necessary section allocation size in loadObject by walking all the sections // once. unsigned StubBufSize = 0; - for (section_iterator SI = Obj.begin_sections(), SE = Obj.end_sections(); + for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end(); SI != SE; ++SI) { section_iterator RelSecI = SI->getRelocatedSection(); if (!(RelSecI == Section)) @@ -340,10 +399,8 @@ unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, } // Get section data size and alignment - uint64_t Alignment64; - uint64_t DataSize; - Check(Section.getSize(DataSize)); - Check(Section.getAlignment(Alignment64)); + uint64_t DataSize = Section.getSize(); + uint64_t Alignment64 = Section.getAlignment(); // Add stubbuf size alignment unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; @@ -354,7 +411,37 @@ unsigned RuntimeDyldImpl::computeSectionStubBufSize(ObjectImage &Obj, return StubBufSize; } -void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, +uint64_t RuntimeDyldImpl::readBytesUnaligned(uint8_t *Src, + unsigned Size) const { + uint64_t Result = 0; + if (IsTargetLittleEndian) { + Src += Size - 1; + while (Size--) + Result = (Result << 8) | *Src--; + } else + while (Size--) + Result = (Result << 8) | *Src++; + + return Result; +} + +void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst, + unsigned Size) const { + if (IsTargetLittleEndian) { + while (Size--) { + *Dst++ = Value & 0xFF; + Value >>= 8; + } + } else { + Dst += Size - 1; + while (Size--) { + *Dst-- = Value & 0xFF; + Value >>= 8; + } + } +} + +void RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj, const CommonSymbolMap &CommonSymbols, uint64_t TotalSize, SymbolTableMap &SymbolTable) { @@ -365,7 +452,7 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, if (!Addr) report_fatal_error("Unable to allocate memory for common symbols!"); uint64_t Offset = 0; - Sections.push_back(SectionEntry(StringRef(), Addr, TotalSize, 0)); + Sections.push_back(SectionEntry("", Addr, TotalSize, 0)); memset(Addr, 0, TotalSize); DEBUG(dbgs() << "emitCommonSection SectionID: " << SectionID << " new addr: " @@ -386,35 +473,28 @@ void RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj, DEBUG(dbgs() << "Allocating common symbol " << Name << " address " << format("%p\n", Addr)); } - Obj.updateSymbolAddress(it->first, (uint64_t)Addr); SymbolTable[Name.data()] = SymbolLoc(SectionID, Offset); Offset += Size; Addr += Size; } } -unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, +unsigned RuntimeDyldImpl::emitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode) { StringRef data; - uint64_t Alignment64; Check(Section.getContents(data)); - Check(Section.getAlignment(Alignment64)); + uint64_t Alignment64 = Section.getAlignment(); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; - bool IsRequired; - bool IsVirtual; - bool IsZeroInit; - bool IsReadOnly; - uint64_t DataSize; unsigned PaddingSize = 0; unsigned StubBufSize = 0; StringRef Name; - Check(Section.isRequiredForExecution(IsRequired)); - Check(Section.isVirtual(IsVirtual)); - Check(Section.isZeroInit(IsZeroInit)); - Check(Section.isReadOnlyData(IsReadOnly)); - Check(Section.getSize(DataSize)); + bool IsRequired = isRequiredForExecution(Section); + bool IsVirtual = Section.isVirtual(); + bool IsZeroInit = isZeroInit(Section); + bool IsReadOnly = isReadOnlyData(Section); + uint64_t DataSize = Section.getSize(); Check(Section.getName(Name)); StubBufSize = computeSectionStubBufSize(Obj, Section); @@ -463,7 +543,6 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); - Obj.updateSectionAddress(Section, (uint64_t)Addr); } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything @@ -477,10 +556,14 @@ unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, } Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData)); + + if (Checker) + Checker->registerSection(Obj.getFileName(), SectionID); + return SectionID; } -unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj, +unsigned RuntimeDyldImpl::findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections) { @@ -519,33 +602,24 @@ void RuntimeDyldImpl::addRelocationForSymbol(const RelocationEntry &RE, uint8_t *RuntimeDyldImpl::createStubFunction(uint8_t *Addr, unsigned AbiVariant) { - if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be || - Arch == Triple::arm64 || Arch == Triple::arm64_be) { + if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) { // This stub has to be able to access the full address space, // since symbol lookup won't necessarily find a handy, in-range, // PLT stub for functions which could be anywhere. - uint32_t *StubAddr = (uint32_t *)Addr; - // Stub can use ip0 (== x16) to calculate address - *StubAddr = 0xd2e00010; // movz ip0, #:abs_g3: - StubAddr++; - *StubAddr = 0xf2c00010; // movk ip0, #:abs_g2_nc: - StubAddr++; - *StubAddr = 0xf2a00010; // movk ip0, #:abs_g1_nc: - StubAddr++; - *StubAddr = 0xf2800010; // movk ip0, #:abs_g0_nc: - StubAddr++; - *StubAddr = 0xd61f0200; // br ip0 + writeBytesUnaligned(0xd2e00010, Addr, 4); // movz ip0, #:abs_g3: + writeBytesUnaligned(0xf2c00010, Addr+4, 4); // movk ip0, #:abs_g2_nc: + writeBytesUnaligned(0xf2a00010, Addr+8, 4); // movk ip0, #:abs_g1_nc: + writeBytesUnaligned(0xf2800010, Addr+12, 4); // movk ip0, #:abs_g0_nc: + writeBytesUnaligned(0xd61f0200, Addr+16, 4); // br ip0 return Addr; } else if (Arch == Triple::arm || Arch == Triple::armeb) { // TODO: There is only ARM far stub now. We should add the Thumb stub, // and stubs for branches Thumb - ARM and ARM - Thumb. - uint32_t *StubAddr = (uint32_t *)Addr; - *StubAddr = 0xe51ff004; // ldr pc,
, ) tuple. + // On success, returns a pair containing the stub address, plus the expression + // remaining to be evaluated. + std::pair evalStubAddr(StringRef Expr, + ParseContext PCtx) const { + if (!Expr.startswith("(")) + return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); + StringRef RemainingExpr = Expr.substr(1).ltrim(); + + // Handle file-name specially, as it may contain characters that aren't + // legal for symbols. + StringRef FileName; + size_t ComaIdx = RemainingExpr.find(','); + FileName = RemainingExpr.substr(0, ComaIdx).rtrim(); + RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim(); + + if (!RemainingExpr.startswith(",")) + return std::make_pair( + unexpectedToken(RemainingExpr, Expr, "expected ','"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); - // Read symbol. - StringRef Symbol; - std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); + StringRef SectionName; + std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr); - if (!Checker.isSymbolValid(Symbol)) - return std::make_pair(EvalResult(("Cannot dereference unknown symbol '" - + Symbol + "'").str()), - ""); + if (!RemainingExpr.startswith(",")) + return std::make_pair( + unexpectedToken(RemainingExpr, Expr, "expected ','"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); - // Set up defaut offset. - int64_t Offset = 0; + StringRef Symbol; + std::tie(Symbol, RemainingExpr) = parseSymbol(RemainingExpr); - // Handle "+/- constant)" portion if necessary. - if (SymbolPlusConstant) { - char OpChar = RemainingExpr[0]; - if (OpChar != '+' && OpChar != '-') - return std::make_pair(EvalResult("Invalid operator in load address."), - ""); - RemainingExpr = RemainingExpr.substr(1).ltrim(); + if (!RemainingExpr.startswith(")")) + return std::make_pair( + unexpectedToken(RemainingExpr, Expr, "expected ')'"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); - EvalResult OffsetExpr; - std::tie(OffsetExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); + uint64_t StubAddr; + std::string ErrorMsg = ""; + std::tie(StubAddr, ErrorMsg) = Checker.getStubAddrFor( + FileName, SectionName, Symbol, PCtx.IsInsideLoad); - Offset = (OpChar == '+') ? - OffsetExpr.getValue() : -1 * OffsetExpr.getValue(); + if (ErrorMsg != "") + return std::make_pair(EvalResult(ErrorMsg), ""); - if (!RemainingExpr.startswith(")")) - return std::make_pair(EvalResult("Missing ')' in load address."), - ""); + return std::make_pair(EvalResult(StubAddr), RemainingExpr); + } - RemainingExpr = RemainingExpr.substr(1).ltrim(); - } + std::pair evalSectionAddr(StringRef Expr, + ParseContext PCtx) const { + if (!Expr.startswith("(")) + return std::make_pair(unexpectedToken(Expr, Expr, "expected '('"), ""); + StringRef RemainingExpr = Expr.substr(1).ltrim(); + // Handle file-name specially, as it may contain characters that aren't + // legal for symbols. + StringRef FileName; + size_t ComaIdx = RemainingExpr.find(','); + FileName = RemainingExpr.substr(0, ComaIdx).rtrim(); + RemainingExpr = RemainingExpr.substr(ComaIdx).ltrim(); + + if (!RemainingExpr.startswith(",")) return std::make_pair( - EvalResult(Checker.readMemoryAtSymbol(Symbol, Offset, ReadSize)), - RemainingExpr); + unexpectedToken(RemainingExpr, Expr, "expected ','"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + + StringRef SectionName; + std::tie(SectionName, RemainingExpr) = parseSymbol(RemainingExpr); + + if (!RemainingExpr.startswith(")")) + return std::make_pair( + unexpectedToken(RemainingExpr, Expr, "expected ')'"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + + uint64_t StubAddr; + std::string ErrorMsg = ""; + std::tie(StubAddr, ErrorMsg) = Checker.getSectionAddr( + FileName, SectionName, PCtx.IsInsideLoad); + + if (ErrorMsg != "") + return std::make_pair(EvalResult(ErrorMsg), ""); + + return std::make_pair(EvalResult(StubAddr), RemainingExpr); + } + + // Evaluate an identiefer expr, which may be a symbol, or a call to + // one of the builtin functions: get_insn_opcode or get_insn_length. + // Return the result, plus the expression remaining to be parsed. + std::pair evalIdentifierExpr(StringRef Expr, + ParseContext PCtx) const { + StringRef Symbol; + StringRef RemainingExpr; + std::tie(Symbol, RemainingExpr) = parseSymbol(Expr); + + // Check for builtin function calls. + if (Symbol == "decode_operand") + return evalDecodeOperand(RemainingExpr); + else if (Symbol == "next_pc") + return evalNextPC(RemainingExpr, PCtx); + else if (Symbol == "stub_addr") + return evalStubAddr(RemainingExpr, PCtx); + else if (Symbol == "section_addr") + return evalSectionAddr(RemainingExpr, PCtx); + + if (!Checker.isSymbolValid(Symbol)) { + std::string ErrMsg("No known address for symbol '"); + ErrMsg += Symbol; + ErrMsg += "'"; + if (Symbol.startswith("L")) + ErrMsg += " (this appears to be an assembler local label - " + " perhaps drop the 'L'?)"; + + return std::make_pair(EvalResult(ErrMsg), ""); } - // Evaluate a "simple" expression. This is any expression that _isn't_ an - // un-parenthesized binary expression. - // - // "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr. - // - // Returns a pair containing the result of the evaluation, plus the - // expression remaining to be parsed. - std::pair evalSimpleExpr(StringRef Expr) const { - EvalResult SubExprResult; - StringRef RemainingExpr; - - if (Expr.empty()) - return std::make_pair(EvalResult("Unexpected end of expression"), ""); - - if (Expr[0] == '(') - std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr); - else if (Expr[0] == '*') - std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr); - else if (isalpha(Expr[0])) - std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr); - else if (isdigit(Expr[0])) - std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr); - - if (SubExprResult.hasError()) - return std::make_pair(SubExprResult, RemainingExpr); - - // Evaluate bit-slice if present. - if (RemainingExpr.startswith("[")) - std::tie(SubExprResult, RemainingExpr) = - evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr)); + // The value for the symbol depends on the context we're evaluating in: + // Inside a load this is the address in the linker's memory, outside a + // load it's the address in the target processes memory. + uint64_t Value = PCtx.IsInsideLoad ? Checker.getSymbolLinkerAddr(Symbol) + : Checker.getSymbolRemoteAddr(Symbol); - return std::make_pair(SubExprResult, RemainingExpr); + // Looks like a plain symbol reference. + return std::make_pair(EvalResult(Value), RemainingExpr); + } + + // Parse a number (hexadecimal or decimal) and return a (string, string) + // pair representing the number and the expression remaining to be parsed. + std::pair parseNumberString(StringRef Expr) const { + size_t FirstNonDigit = StringRef::npos; + if (Expr.startswith("0x")) { + FirstNonDigit = Expr.find_first_not_of("0123456789abcdefABCDEF", 2); + if (FirstNonDigit == StringRef::npos) + FirstNonDigit = Expr.size(); + } else { + FirstNonDigit = Expr.find_first_not_of("0123456789"); + if (FirstNonDigit == StringRef::npos) + FirstNonDigit = Expr.size(); } + return std::make_pair(Expr.substr(0, FirstNonDigit), + Expr.substr(FirstNonDigit)); + } + + // Evaluate a constant numeric expression (hexidecimal or decimal) and + // return a pair containing the result, and the expression remaining to be + // evaluated. + std::pair evalNumberExpr(StringRef Expr) const { + StringRef ValueStr; + StringRef RemainingExpr; + std::tie(ValueStr, RemainingExpr) = parseNumberString(Expr); + + if (ValueStr.empty() || !isdigit(ValueStr[0])) + return std::make_pair( + unexpectedToken(RemainingExpr, RemainingExpr, "expected number"), ""); + uint64_t Value; + ValueStr.getAsInteger(0, Value); + return std::make_pair(EvalResult(Value), RemainingExpr); + } + + // Evaluate an expression of the form "()" and return a pair + // containing the result of evaluating , plus the expression + // remaining to be parsed. + std::pair evalParensExpr(StringRef Expr, + ParseContext PCtx) const { + assert(Expr.startswith("(") && "Not a parenthesized expression"); + EvalResult SubExprResult; + StringRef RemainingExpr; + std::tie(SubExprResult, RemainingExpr) = + evalComplexExpr(evalSimpleExpr(Expr.substr(1).ltrim(), PCtx), PCtx); + if (SubExprResult.hasError()) + return std::make_pair(SubExprResult, ""); + if (!RemainingExpr.startswith(")")) + return std::make_pair( + unexpectedToken(RemainingExpr, Expr, "expected ')'"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + return std::make_pair(SubExprResult, RemainingExpr); + } + + // Evaluate an expression in one of the following forms: + // *{} + // Return a pair containing the result, plus the expression remaining to be + // parsed. + std::pair evalLoadExpr(StringRef Expr) const { + assert(Expr.startswith("*") && "Not a load expression"); + StringRef RemainingExpr = Expr.substr(1).ltrim(); + + // Parse read size. + if (!RemainingExpr.startswith("{")) + return std::make_pair(EvalResult("Expected '{' following '*'."), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + EvalResult ReadSizeExpr; + std::tie(ReadSizeExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); + if (ReadSizeExpr.hasError()) + return std::make_pair(ReadSizeExpr, RemainingExpr); + uint64_t ReadSize = ReadSizeExpr.getValue(); + if (ReadSize < 1 || ReadSize > 8) + return std::make_pair(EvalResult("Invalid size for dereference."), ""); + if (!RemainingExpr.startswith("}")) + return std::make_pair(EvalResult("Missing '}' for dereference."), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + + // Evaluate the expression representing the load address. + ParseContext LoadCtx(true); + EvalResult LoadAddrExprResult; + std::tie(LoadAddrExprResult, RemainingExpr) = + evalComplexExpr(evalSimpleExpr(RemainingExpr, LoadCtx), LoadCtx); + + if (LoadAddrExprResult.hasError()) + return std::make_pair(LoadAddrExprResult, ""); + + uint64_t LoadAddr = LoadAddrExprResult.getValue(); + + return std::make_pair( + EvalResult(Checker.readMemoryAtAddr(LoadAddr, ReadSize)), + RemainingExpr); + } + + // Evaluate a "simple" expression. This is any expression that _isn't_ an + // un-parenthesized binary expression. + // + // "Simple" expressions can be optionally bit-sliced. See evalSlicedExpr. + // + // Returns a pair containing the result of the evaluation, plus the + // expression remaining to be parsed. + std::pair evalSimpleExpr(StringRef Expr, + ParseContext PCtx) const { + EvalResult SubExprResult; + StringRef RemainingExpr; + + if (Expr.empty()) + return std::make_pair(EvalResult("Unexpected end of expression"), ""); + + if (Expr[0] == '(') + std::tie(SubExprResult, RemainingExpr) = evalParensExpr(Expr, PCtx); + else if (Expr[0] == '*') + std::tie(SubExprResult, RemainingExpr) = evalLoadExpr(Expr); + else if (isalpha(Expr[0]) || Expr[0] == '_') + std::tie(SubExprResult, RemainingExpr) = evalIdentifierExpr(Expr, PCtx); + else if (isdigit(Expr[0])) + std::tie(SubExprResult, RemainingExpr) = evalNumberExpr(Expr); + else + return std::make_pair( + unexpectedToken(Expr, Expr, + "expected '(', '*', identifier, or number"), ""); + + if (SubExprResult.hasError()) + return std::make_pair(SubExprResult, RemainingExpr); + + // Evaluate bit-slice if present. + if (RemainingExpr.startswith("[")) + std::tie(SubExprResult, RemainingExpr) = + evalSliceExpr(std::make_pair(SubExprResult, RemainingExpr)); - // Evaluate a bit-slice of an expression. - // A bit-slice has the form "[high:low]". The result of evaluating a - // slice is the bits between high and low (inclusive) in the original - // expression, right shifted so that the "low" bit is in position 0 in the + return std::make_pair(SubExprResult, RemainingExpr); + } + + // Evaluate a bit-slice of an expression. + // A bit-slice has the form "[high:low]". The result of evaluating a + // slice is the bits between high and low (inclusive) in the original + // expression, right shifted so that the "low" bit is in position 0 in the + // result. + // Returns a pair containing the result of the slice operation, plus the + // expression remaining to be parsed. + std::pair + evalSliceExpr(std::pair Ctx) const { + EvalResult SubExprResult; + StringRef RemainingExpr; + std::tie(SubExprResult, RemainingExpr) = Ctx; + + assert(RemainingExpr.startswith("[") && "Not a slice expr."); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + + EvalResult HighBitExpr; + std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); + + if (HighBitExpr.hasError()) + return std::make_pair(HighBitExpr, RemainingExpr); + + if (!RemainingExpr.startswith(":")) + return std::make_pair( + unexpectedToken(RemainingExpr, RemainingExpr, "expected ':'"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + + EvalResult LowBitExpr; + std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); + + if (LowBitExpr.hasError()) + return std::make_pair(LowBitExpr, RemainingExpr); + + if (!RemainingExpr.startswith("]")) + return std::make_pair( + unexpectedToken(RemainingExpr, RemainingExpr, "expected ']'"), ""); + RemainingExpr = RemainingExpr.substr(1).ltrim(); + + unsigned HighBit = HighBitExpr.getValue(); + unsigned LowBit = LowBitExpr.getValue(); + uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1; + uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask; + return std::make_pair(EvalResult(SlicedValue), RemainingExpr); + } + + // Evaluate a "complex" expression. + // Takes an already evaluated subexpression and checks for the presence of a + // binary operator, computing the result of the binary operation if one is + // found. Used to make arithmetic expressions left-associative. + // Returns a pair containing the ultimate result of evaluating the + // expression, plus the expression remaining to be evaluated. + std::pair + evalComplexExpr(std::pair LHSAndRemaining, + ParseContext PCtx) const { + EvalResult LHSResult; + StringRef RemainingExpr; + std::tie(LHSResult, RemainingExpr) = LHSAndRemaining; + + // If there was an error, or there's nothing left to evaluate, return the // result. - // Returns a pair containing the result of the slice operation, plus the - // expression remaining to be parsed. - std::pair evalSliceExpr( - std::pair Ctx) const{ - EvalResult SubExprResult; - StringRef RemainingExpr; - std::tie(SubExprResult, RemainingExpr) = Ctx; - - assert(RemainingExpr.startswith("[") && "Not a slice expr."); - RemainingExpr = RemainingExpr.substr(1).ltrim(); - - EvalResult HighBitExpr; - std::tie(HighBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); - - if (HighBitExpr.hasError()) - return std::make_pair(HighBitExpr, RemainingExpr); - - if (!RemainingExpr.startswith(":")) - return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, - "expected ':'"), - ""); - RemainingExpr = RemainingExpr.substr(1).ltrim(); - - EvalResult LowBitExpr; - std::tie(LowBitExpr, RemainingExpr) = evalNumberExpr(RemainingExpr); - - if (LowBitExpr.hasError()) - return std::make_pair(LowBitExpr, RemainingExpr); - - if (!RemainingExpr.startswith("]")) - return std::make_pair(unexpectedToken(RemainingExpr, RemainingExpr, - "expected ']'"), - ""); - RemainingExpr = RemainingExpr.substr(1).ltrim(); - - unsigned HighBit = HighBitExpr.getValue(); - unsigned LowBit = LowBitExpr.getValue(); - uint64_t Mask = ((uint64_t)1 << (HighBit - LowBit + 1)) - 1; - uint64_t SlicedValue = (SubExprResult.getValue() >> LowBit) & Mask; - return std::make_pair(EvalResult(SlicedValue), RemainingExpr); - } + if (LHSResult.hasError() || RemainingExpr == "") + return std::make_pair(LHSResult, RemainingExpr); - // Evaluate a "complex" expression. - // Takes an already evaluated subexpression and checks for the presence of a - // binary operator, computing the result of the binary operation if one is - // found. Used to make arithmetic expressions left-associative. - // Returns a pair containing the ultimate result of evaluating the - // expression, plus the expression remaining to be evaluated. - std::pair evalComplexExpr( - std::pair Ctx) const { - EvalResult LHSResult; - StringRef RemainingExpr; - std::tie(LHSResult, RemainingExpr) = Ctx; - - // If there was an error, or there's nothing left to evaluate, return the - // result. - if (LHSResult.hasError() || RemainingExpr == "") - return std::make_pair(LHSResult, RemainingExpr); - - // Otherwise check if this is a binary expressioan. - BinOpToken BinOp; - std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr); - - // If this isn't a recognized expression just return. - if (BinOp == BinOpToken::Invalid) - return std::make_pair(LHSResult, RemainingExpr); - - // This is a recognized bin-op. Evaluate the RHS, then evaluate the binop. - EvalResult RHSResult; - std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr); - - // If there was an error evaluating the RHS, return it. - if (RHSResult.hasError()) - return std::make_pair(RHSResult, RemainingExpr); - - // This is a binary expression - evaluate and try to continue as a - // complex expr. - EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult)); - - return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr)); - } + // Otherwise check if this is a binary expressioan. + BinOpToken BinOp; + std::tie(BinOp, RemainingExpr) = parseBinOpToken(RemainingExpr); - bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const { - MCDisassembler *Dis = Checker.Disassembler; - StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol); - StringRefMemoryObject SectionBytes(SectionMem, 0); + // If this isn't a recognized expression just return. + if (BinOp == BinOpToken::Invalid) + return std::make_pair(LHSResult, RemainingExpr); - MCDisassembler::DecodeStatus S = - Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls()); + // This is a recognized bin-op. Evaluate the RHS, then evaluate the binop. + EvalResult RHSResult; + std::tie(RHSResult, RemainingExpr) = evalSimpleExpr(RemainingExpr, PCtx); - return (S == MCDisassembler::Success); - } + // If there was an error evaluating the RHS, return it. + if (RHSResult.hasError()) + return std::make_pair(RHSResult, RemainingExpr); - }; + // This is a binary expression - evaluate and try to continue as a + // complex expr. + EvalResult ThisResult(computeBinOpResult(BinOp, LHSResult, RHSResult)); + + return evalComplexExpr(std::make_pair(ThisResult, RemainingExpr), PCtx); + } + + bool decodeInst(StringRef Symbol, MCInst &Inst, uint64_t &Size) const { + MCDisassembler *Dis = Checker.Disassembler; + StringRef SectionMem = Checker.getSubsectionStartingAt(Symbol); + ArrayRef SectionBytes( + reinterpret_cast(SectionMem.data()), + SectionMem.size()); + + MCDisassembler::DecodeStatus S = + Dis->getInstruction(Inst, Size, SectionBytes, 0, nulls(), nulls()); + + return (S == MCDisassembler::Success); + } +}; +} +RuntimeDyldCheckerImpl::RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, + MCDisassembler *Disassembler, + MCInstPrinter *InstPrinter, + raw_ostream &ErrStream) + : RTDyld(RTDyld), Disassembler(Disassembler), InstPrinter(InstPrinter), + ErrStream(ErrStream) { + RTDyld.Checker = this; } -bool RuntimeDyldChecker::check(StringRef CheckExpr) const { +bool RuntimeDyldCheckerImpl::check(StringRef CheckExpr) const { CheckExpr = CheckExpr.trim(); - DEBUG(llvm::dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr - << "'...\n"); + DEBUG(dbgs() << "RuntimeDyldChecker: Checking '" << CheckExpr << "'...\n"); RuntimeDyldCheckerExprEval P(*this, ErrStream); bool Result = P.evaluate(CheckExpr); (void)Result; - DEBUG(llvm::dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' " - << (Result ? "passed" : "FAILED") << ".\n"); + DEBUG(dbgs() << "RuntimeDyldChecker: '" << CheckExpr << "' " + << (Result ? "passed" : "FAILED") << ".\n"); return Result; } -bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix, - MemoryBuffer* MemBuf) const { +bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix, + MemoryBuffer *MemBuf) const { bool DidAllTestsPass = true; unsigned NumRules = 0; const char *LineStart = MemBuf->getBufferStart(); // Eat whitespace. - while (LineStart != MemBuf->getBufferEnd() && - std::isspace(*LineStart)) + while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart)) ++LineStart; while (LineStart != MemBuf->getBufferEnd() && *LineStart != '\0') { const char *LineEnd = LineStart; - while (LineEnd != MemBuf->getBufferEnd() && - *LineEnd != '\r' && *LineEnd != '\n') + while (LineEnd != MemBuf->getBufferEnd() && *LineEnd != '\r' && + *LineEnd != '\n') ++LineEnd; StringRef Line(LineStart, LineEnd - LineStart); @@ -620,37 +724,212 @@ bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix, // Eat whitespace. LineStart = LineEnd; - while (LineStart != MemBuf->getBufferEnd() && - std::isspace(*LineStart)) + while (LineStart != MemBuf->getBufferEnd() && std::isspace(*LineStart)) ++LineStart; } return DidAllTestsPass && (NumRules != 0); } -bool RuntimeDyldChecker::isSymbolValid(StringRef Symbol) const { - return RTDyld.getSymbolAddress(Symbol) != nullptr; +bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const { + return getRTDyld().getSymbolAddress(Symbol) != nullptr; } -uint64_t RuntimeDyldChecker::getSymbolAddress(StringRef Symbol) const { - return RTDyld.getAnySymbolRemoteAddress(Symbol); +uint64_t RuntimeDyldCheckerImpl::getSymbolLinkerAddr(StringRef Symbol) const { + return static_cast( + reinterpret_cast(getRTDyld().getSymbolAddress(Symbol))); } -uint64_t RuntimeDyldChecker::readMemoryAtSymbol(StringRef Symbol, - int64_t Offset, - unsigned Size) const { - uint8_t *Src = RTDyld.getSymbolAddress(Symbol); - uint64_t Result = 0; - memcpy(&Result, Src + Offset, Size); - return Result; +uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const { + if (uint64_t InternalSymbolAddr = getRTDyld().getSymbolLoadAddress(Symbol)) + return InternalSymbolAddr; + return getRTDyld().MemMgr->getSymbolAddress(Symbol); +} + +uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr, + unsigned Size) const { + uintptr_t PtrSizedAddr = static_cast(SrcAddr); + assert(PtrSizedAddr == SrcAddr && "Linker memory pointer out-of-range."); + uint8_t *Src = reinterpret_cast(PtrSizedAddr); + return getRTDyld().readBytesUnaligned(Src, Size); +} + + +std::pair +RuntimeDyldCheckerImpl::findSectionAddrInfo(StringRef FileName, + StringRef SectionName) const { + + auto SectionMapItr = Stubs.find(FileName); + if (SectionMapItr == Stubs.end()) { + std::string ErrorMsg = "File '"; + ErrorMsg += FileName; + ErrorMsg += "' not found. "; + if (Stubs.empty()) + ErrorMsg += "No stubs registered."; + else { + ErrorMsg += "Available files are:"; + for (const auto& StubEntry : Stubs) { + ErrorMsg += " '"; + ErrorMsg += StubEntry.first; + ErrorMsg += "'"; + } + } + ErrorMsg += "\n"; + return std::make_pair(nullptr, ErrorMsg); + } + + auto SectionInfoItr = SectionMapItr->second.find(SectionName); + if (SectionInfoItr == SectionMapItr->second.end()) + return std::make_pair(nullptr, + ("Section '" + SectionName + "' not found in file '" + + FileName + "'\n").str()); + + return std::make_pair(&SectionInfoItr->second, std::string("")); +} + +std::pair RuntimeDyldCheckerImpl::getSectionAddr( + StringRef FileName, StringRef SectionName, bool IsInsideLoad) const { + + const SectionAddressInfo *SectionInfo = nullptr; + { + std::string ErrorMsg; + std::tie(SectionInfo, ErrorMsg) = + findSectionAddrInfo(FileName, SectionName); + if (ErrorMsg != "") + return std::make_pair(0, ErrorMsg); + } + + unsigned SectionID = SectionInfo->SectionID; + uint64_t Addr; + if (IsInsideLoad) + Addr = + static_cast( + reinterpret_cast(getRTDyld().Sections[SectionID].Address)); + else + Addr = getRTDyld().Sections[SectionID].LoadAddress; + + return std::make_pair(Addr, std::string("")); +} + +std::pair RuntimeDyldCheckerImpl::getStubAddrFor( + StringRef FileName, StringRef SectionName, StringRef SymbolName, + bool IsInsideLoad) const { + + const SectionAddressInfo *SectionInfo = nullptr; + { + std::string ErrorMsg; + std::tie(SectionInfo, ErrorMsg) = + findSectionAddrInfo(FileName, SectionName); + if (ErrorMsg != "") + return std::make_pair(0, ErrorMsg); + } + + unsigned SectionID = SectionInfo->SectionID; + const StubOffsetsMap &SymbolStubs = SectionInfo->StubOffsets; + auto StubOffsetItr = SymbolStubs.find(SymbolName); + if (StubOffsetItr == SymbolStubs.end()) + return std::make_pair(0, + ("Stub for symbol '" + SymbolName + "' not found. " + "If '" + SymbolName + "' is an internal symbol this " + "may indicate that the stub target offset is being " + "computed incorrectly.\n").str()); + + uint64_t StubOffset = StubOffsetItr->second; + + uint64_t Addr; + if (IsInsideLoad) { + uintptr_t SectionBase = + reinterpret_cast(getRTDyld().Sections[SectionID].Address); + Addr = static_cast(SectionBase) + StubOffset; + } else { + uint64_t SectionBase = getRTDyld().Sections[SectionID].LoadAddress; + Addr = SectionBase + StubOffset; + } + + return std::make_pair(Addr, std::string("")); } -StringRef RuntimeDyldChecker::getSubsectionStartingAt(StringRef Name) const { +StringRef +RuntimeDyldCheckerImpl::getSubsectionStartingAt(StringRef Name) const { RuntimeDyldImpl::SymbolTableMap::const_iterator pos = - RTDyld.GlobalSymbolTable.find(Name); - if (pos == RTDyld.GlobalSymbolTable.end()) + getRTDyld().GlobalSymbolTable.find(Name); + if (pos == getRTDyld().GlobalSymbolTable.end()) return StringRef(); RuntimeDyldImpl::SymbolLoc Loc = pos->second; - uint8_t *SectionAddr = RTDyld.getSectionAddress(Loc.first); - return StringRef(reinterpret_cast(SectionAddr) + Loc.second, - RTDyld.Sections[Loc.first].Size - Loc.second); + uint8_t *SectionAddr = getRTDyld().getSectionAddress(Loc.first); + return StringRef(reinterpret_cast(SectionAddr) + Loc.second, + getRTDyld().Sections[Loc.first].Size - Loc.second); +} + +void RuntimeDyldCheckerImpl::registerSection( + StringRef FilePath, unsigned SectionID) { + StringRef FileName = sys::path::filename(FilePath); + const SectionEntry &Section = getRTDyld().Sections[SectionID]; + StringRef SectionName = Section.Name; + + Stubs[FileName][SectionName].SectionID = SectionID; +} + +void RuntimeDyldCheckerImpl::registerStubMap( + StringRef FilePath, unsigned SectionID, + const RuntimeDyldImpl::StubMap &RTDyldStubs) { + StringRef FileName = sys::path::filename(FilePath); + const SectionEntry &Section = getRTDyld().Sections[SectionID]; + StringRef SectionName = Section.Name; + + Stubs[FileName][SectionName].SectionID = SectionID; + + for (auto &StubMapEntry : RTDyldStubs) { + std::string SymbolName = ""; + + if (StubMapEntry.first.SymbolName) + SymbolName = StubMapEntry.first.SymbolName; + else { + // If this is a (Section, Offset) pair, do a reverse lookup in the + // global symbol table to find the name. + for (auto &GSTEntry : getRTDyld().GlobalSymbolTable) { + if (GSTEntry.second.first == StubMapEntry.first.SectionID && + GSTEntry.second.second == + static_cast(StubMapEntry.first.Offset)) { + SymbolName = GSTEntry.first(); + break; + } + } + } + + if (SymbolName != "") + Stubs[FileName][SectionName].StubOffsets[SymbolName] = + StubMapEntry.second; + } +} + +RuntimeDyldChecker::RuntimeDyldChecker(RuntimeDyld &RTDyld, + MCDisassembler *Disassembler, + MCInstPrinter *InstPrinter, + raw_ostream &ErrStream) + : Impl(make_unique(RTDyld, Disassembler, + InstPrinter, ErrStream)) {} + +RuntimeDyldChecker::~RuntimeDyldChecker() {} + +RuntimeDyld& RuntimeDyldChecker::getRTDyld() { + return Impl->RTDyld; +} + +const RuntimeDyld& RuntimeDyldChecker::getRTDyld() const { + return Impl->RTDyld; +} + +bool RuntimeDyldChecker::check(StringRef CheckExpr) const { + return Impl->check(CheckExpr); +} + +bool RuntimeDyldChecker::checkAllRulesInBuffer(StringRef RulePrefix, + MemoryBuffer *MemBuf) const { + return Impl->checkAllRulesInBuffer(RulePrefix, MemBuf); +} + +std::pair +RuntimeDyldChecker::getSectionAddr(StringRef FileName, StringRef SectionName, + bool LinkerAddress) { + return Impl->getSectionAddr(FileName, SectionName, LinkerAddress); } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h new file mode 100644 index 0000000..de20c1e --- /dev/null +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldCheckerImpl.h @@ -0,0 +1,76 @@ +//===-- RuntimeDyldCheckerImpl.h -- RuntimeDyld test framework --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDCHECKERIMPL_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDCHECKERIMPL_H + +#include "RuntimeDyldImpl.h" +#include + +namespace llvm { + +class RuntimeDyldCheckerImpl { + friend class RuntimeDyldChecker; + friend class RuntimeDyldImpl; + friend class RuntimeDyldCheckerExprEval; + +public: + RuntimeDyldCheckerImpl(RuntimeDyld &RTDyld, MCDisassembler *Disassembler, + MCInstPrinter *InstPrinter, + llvm::raw_ostream &ErrStream); + + bool check(StringRef CheckExpr) const; + bool checkAllRulesInBuffer(StringRef RulePrefix, MemoryBuffer *MemBuf) const; + +private: + + // StubMap typedefs. + typedef std::map StubOffsetsMap; + struct SectionAddressInfo { + uint64_t SectionID; + StubOffsetsMap StubOffsets; + }; + typedef std::map SectionMap; + typedef std::map StubMap; + + RuntimeDyldImpl &getRTDyld() const { return *RTDyld.Dyld; } + + bool isSymbolValid(StringRef Symbol) const; + uint64_t getSymbolLinkerAddr(StringRef Symbol) const; + uint64_t getSymbolRemoteAddr(StringRef Symbol) const; + uint64_t readMemoryAtAddr(uint64_t Addr, unsigned Size) const; + + std::pair findSectionAddrInfo( + StringRef FileName, + StringRef SectionName) const; + + std::pair getSectionAddr(StringRef FileName, + StringRef SectionName, + bool IsInsideLoad) const; + + std::pair getStubAddrFor(StringRef FileName, + StringRef SectionName, + StringRef Symbol, + bool IsInsideLoad) const; + StringRef getSubsectionStartingAt(StringRef Name) const; + + void registerSection(StringRef FilePath, unsigned SectionID); + void registerStubMap(StringRef FilePath, unsigned SectionID, + const RuntimeDyldImpl::StubMap &RTDyldStubs); + + RuntimeDyld &RTDyld; + MCDisassembler *Disassembler; + MCInstPrinter *InstPrinter; + llvm::raw_ostream &ErrStream; + + StubMap Stubs; +}; +} + +#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index 728138e..2664a10 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -12,26 +12,23 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldELF.h" -#include "JITRegistrar.h" -#include "ObjectImageCommon.h" #include "llvm/ADT/IntervalMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/TargetRegistry.h" using namespace llvm; using namespace llvm::object; #define DEBUG_TYPE "dyld" -namespace { - static inline std::error_code check(std::error_code Err) { if (Err) { report_fatal_error(Err.message()); @@ -39,6 +36,8 @@ static inline std::error_code check(std::error_code Err) { return Err; } +namespace { + template class DyldELFObject : public ELFObjectFile { LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) @@ -51,16 +50,12 @@ template class DyldELFObject : public ELFObjectFile { typedef typename ELFDataTypeTypedefHelper::value_type addr_type; - std::unique_ptr UnderlyingFile; - public: - DyldELFObject(std::unique_ptr UnderlyingFile, - std::unique_ptr Wrapper, std::error_code &ec); - - DyldELFObject(std::unique_ptr Wrapper, std::error_code &ec); + DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec); void updateSectionAddress(const SectionRef &Sec, uint64_t Addr); - void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr); + + void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr); // Methods for type inquiry through isa, cast and dyn_cast static inline bool classof(const Binary *v) { @@ -70,57 +65,17 @@ public: static inline bool classof(const ELFObjectFile *v) { return v->isDyldType(); } -}; - -template class ELFObjectImage : public ObjectImageCommon { - bool Registered; - -public: - ELFObjectImage(ObjectBuffer *Input, std::unique_ptr> Obj) - : ObjectImageCommon(Input, std::move(Obj)), Registered(false) {} - - virtual ~ELFObjectImage() { - if (Registered) - deregisterWithDebugger(); - } - // Subclasses can override these methods to update the image with loaded - // addresses for sections and common symbols - void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) override { - static_cast*>(getObjectFile()) - ->updateSectionAddress(Sec, Addr); - } +}; - void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) override { - static_cast*>(getObjectFile()) - ->updateSymbolAddress(Sym, Addr); - } - void registerWithDebugger() override { - JITRegistrar::getGDBRegistrar().registerObject(*Buffer); - Registered = true; - } - void deregisterWithDebugger() override { - JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); - } -}; // The MemoryBuffer passed into this constructor is just a wrapper around the // actual memory. Ultimately, the Binary parent class will take ownership of // this MemoryBuffer object but not the underlying memory. template -DyldELFObject::DyldELFObject(std::unique_ptr Wrapper, - std::error_code &EC) - : ELFObjectFile(std::move(Wrapper), EC) { - this->isDyldELFObject = true; -} - -template -DyldELFObject::DyldELFObject(std::unique_ptr UnderlyingFile, - std::unique_ptr Wrapper, - std::error_code &EC) - : ELFObjectFile(std::move(Wrapper), EC), - UnderlyingFile(std::move(UnderlyingFile)) { +DyldELFObject::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC) + : ELFObjectFile(Wrapper, EC) { this->isDyldELFObject = true; } @@ -148,10 +103,89 @@ void DyldELFObject::updateSymbolAddress(const SymbolRef &SymRef, sym->st_value = static_cast(Addr); } +class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo { +public: + LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary + getObjectForDebug(const ObjectFile &Obj) const override; +}; + +template +std::unique_ptr> +createRTDyldELFObject(MemoryBufferRef Buffer, + const LoadedELFObjectInfo &L, + std::error_code &ec) { + typedef typename ELFFile::Elf_Shdr Elf_Shdr; + typedef typename ELFDataTypeTypedefHelper::value_type addr_type; + + std::unique_ptr> Obj = + llvm::make_unique>(Buffer, ec); + + // Iterate over all sections in the object. + for (const auto &Sec : Obj->sections()) { + StringRef SectionName; + Sec.getName(SectionName); + if (SectionName != "") { + DataRefImpl ShdrRef = Sec.getRawDataRefImpl(); + Elf_Shdr *shdr = const_cast( + reinterpret_cast(ShdrRef.p)); + + if (uint64_t SecLoadAddr = L.getSectionLoadAddress(SectionName)) { + // This assumes that the address passed in matches the target address + // bitness. The template-based type cast handles everything else. + shdr->sh_addr = static_cast(SecLoadAddr); + } + } + } + + return Obj; +} + +OwningBinary createELFDebugObject(const ObjectFile &Obj, + const LoadedELFObjectInfo &L) { + assert(Obj.isELF() && "Not an ELF object file."); + + std::unique_ptr Buffer = + MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName()); + + std::error_code ec; + + std::unique_ptr DebugObj; + if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) { + typedef ELFType ELF32LE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) { + typedef ELFType ELF32BE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) { + typedef ELFType ELF64BE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) { + typedef ELFType ELF64LE; + DebugObj = createRTDyldELFObject(Buffer->getMemBufferRef(), L, ec); + } else + llvm_unreachable("Unexpected ELF format"); + + assert(!ec && "Could not construct copy ELF object file"); + + return OwningBinary(std::move(DebugObj), std::move(Buffer)); +} + +OwningBinary +LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const { + return createELFDebugObject(Obj, *this); +} + } // namespace namespace llvm { +RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} +RuntimeDyldELF::~RuntimeDyldELF() {} + void RuntimeDyldELF::registerEHFrames() { if (!MemMgr) return; @@ -179,81 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() { RegisteredEHFrameSections.clear(); } -ObjectImage * -RuntimeDyldELF::createObjectImageFromFile(std::unique_ptr ObjFile) { - if (!ObjFile) - return nullptr; - - std::error_code ec; - std::unique_ptr Buffer( - MemoryBuffer::getMemBuffer(ObjFile->getData(), "", false)); - - if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique>>( - std::move(ObjFile), std::move(Buffer), ec); - return new ELFObjectImage>( - nullptr, std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique>>( - std::move(ObjFile), std::move(Buffer), ec); - return new ELFObjectImage>(nullptr, std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) { - auto Obj = llvm::make_unique>>( - std::move(ObjFile), std::move(Buffer), ec); - return new ELFObjectImage>(nullptr, - std::move(Obj)); - } else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) { - auto Obj = - llvm::make_unique>>( - std::move(ObjFile), std::move(Buffer), ec); - return new ELFObjectImage>( - nullptr, std::move(Obj)); - } else - llvm_unreachable("Unexpected ELF format"); -} - -ObjectImage *RuntimeDyldELF::createObjectImage(ObjectBuffer *Buffer) { - if (Buffer->getBufferSize() < ELF::EI_NIDENT) - llvm_unreachable("Unexpected ELF object size"); - std::pair Ident = - std::make_pair((uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS], - (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]); - std::error_code ec; - - std::unique_ptr Buf(Buffer->getMemBuffer()); - - if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) { - auto Obj = - llvm::make_unique>>( - std::move(Buf), ec); - return new ELFObjectImage>( - Buffer, std::move(Obj)); - } else if (Ident.first == ELF::ELFCLASS32 && - Ident.second == ELF::ELFDATA2MSB) { - auto Obj = - llvm::make_unique>>( - std::move(Buf), ec); - return new ELFObjectImage>(Buffer, - std::move(Obj)); - } else if (Ident.first == ELF::ELFCLASS64 && - Ident.second == ELF::ELFDATA2MSB) { - auto Obj = llvm::make_unique>>( - std::move(Buf), ec); - return new ELFObjectImage>(Buffer, std::move(Obj)); - } else if (Ident.first == ELF::ELFCLASS64 && - Ident.second == ELF::ELFDATA2LSB) { - auto Obj = - llvm::make_unique>>( - std::move(Buf), ec); - return new ELFObjectImage>(Buffer, std::move(Obj)); - } else - llvm_unreachable("Unexpected ELF format"); +std::unique_ptr +RuntimeDyldELF::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique(*this, SectionStartIdx, + SectionEndIdx); } -RuntimeDyldELF::~RuntimeDyldELF() {} - void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, @@ -263,10 +230,9 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, llvm_unreachable("Relocation type not implemented yet!"); break; case ELF::R_X86_64_64: { - uint64_t *Target = reinterpret_cast(Section.Address + Offset); - *Target = Value + Addend; + support::ulittle64_t::ref(Section.Address + Offset) = Value + Addend; DEBUG(dbgs() << "Writing " << format("%p", (Value + Addend)) << " at " - << format("%p\n", Target)); + << format("%p\n", Section.Address + Offset)); break; } case ELF::R_X86_64_32: @@ -276,17 +242,15 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, (Type == ELF::R_X86_64_32S && ((int64_t)Value <= INT32_MAX && (int64_t)Value >= INT32_MIN))); uint32_t TruncatedAddr = (Value & 0xFFFFFFFF); - uint32_t *Target = reinterpret_cast(Section.Address + Offset); - *Target = TruncatedAddr; + support::ulittle32_t::ref(Section.Address + Offset) = TruncatedAddr; DEBUG(dbgs() << "Writing " << format("%p", TruncatedAddr) << " at " - << format("%p\n", Target)); + << format("%p\n", Section.Address + Offset)); break; } case ELF::R_X86_64_GOTPCREL: { // findGOTEntry returns the 'G + GOT' part of the relocation calculation // based on the load/target address of the GOT (not the current/local addr). uint64_t GOTAddr = findGOTEntry(Value, SymOffset); - uint32_t *Target = reinterpret_cast(Section.Address + Offset); uint64_t FinalAddress = Section.LoadAddress + Offset; // The processRelocationRef method combines the symbol offset and the addend // and in most cases that's what we want. For this relocation type, we need @@ -294,30 +258,29 @@ void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section, int64_t RealOffset = GOTAddr + Addend - SymOffset - FinalAddress; assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); - *Target = TruncOffset; + support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset; break; } case ELF::R_X86_64_PC32: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint32_t *Placeholder = - reinterpret_cast(Section.ObjAddress + Offset); - uint32_t *Target = reinterpret_cast(Section.Address + Offset); + support::ulittle32_t::ref Placeholder( + (void *)(Section.ObjAddress + Offset)); uint64_t FinalAddress = Section.LoadAddress + Offset; - int64_t RealOffset = *Placeholder + Value + Addend - FinalAddress; + int64_t RealOffset = Placeholder + Value + Addend - FinalAddress; assert(RealOffset <= INT32_MAX && RealOffset >= INT32_MIN); int32_t TruncOffset = (RealOffset & 0xFFFFFFFF); - *Target = TruncOffset; + support::ulittle32_t::ref(Section.Address + Offset) = TruncOffset; break; } case ELF::R_X86_64_PC64: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint64_t *Placeholder = - reinterpret_cast(Section.ObjAddress + Offset); - uint64_t *Target = reinterpret_cast(Section.Address + Offset); + support::ulittle64_t::ref Placeholder( + (void *)(Section.ObjAddress + Offset)); uint64_t FinalAddress = Section.LoadAddress + Offset; - *Target = *Placeholder + Value + Addend - FinalAddress; + support::ulittle64_t::ref(Section.Address + Offset) = + Placeholder + Value + Addend - FinalAddress; break; } } @@ -330,21 +293,20 @@ void RuntimeDyldELF::resolveX86Relocation(const SectionEntry &Section, case ELF::R_386_32: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint32_t *Placeholder = - reinterpret_cast(Section.ObjAddress + Offset); - uint32_t *Target = reinterpret_cast(Section.Address + Offset); - *Target = *Placeholder + Value + Addend; + support::ulittle32_t::ref Placeholder( + (void *)(Section.ObjAddress + Offset)); + support::ulittle32_t::ref(Section.Address + Offset) = + Placeholder + Value + Addend; break; } case ELF::R_386_PC32: { // Get the placeholder value from the generated object since // a previous relocation attempt may have overwritten the loaded version - uint32_t *Placeholder = - reinterpret_cast(Section.ObjAddress + Offset); - uint32_t *Target = reinterpret_cast(Section.Address + Offset); + support::ulittle32_t::ref Placeholder( + (void *)(Section.ObjAddress + Offset)); uint32_t FinalAddress = ((Section.LoadAddress + Offset) & 0xFFFFFFFF); - uint32_t RealOffset = *Placeholder + Value + Addend - FinalAddress; - *Target = RealOffset; + uint32_t RealOffset = Placeholder + Value + Addend - FinalAddress; + support::ulittle32_t::ref(Section.Address + Offset) = RealOffset; break; } default: @@ -617,7 +579,7 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section, } // Return the .TOC. section and offset. -void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, +void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel) { // Set a default SectionID in case we do not find a TOC section below. @@ -630,7 +592,7 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, // The TOC consists of sections .got, .toc, .tocbss, .plt in that // order. The TOC starts where the first of these sections starts. - for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); + for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); si != se; ++si) { StringRef SectionName; @@ -652,15 +614,15 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj, // Returns the sections and offset associated with the ODP entry referenced // by Symbol. -void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, +void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &Obj, ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel) { // Get the ELF symbol value (st_value) to compare with Relocation offset in // .opd entries - for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections(); + for (section_iterator si = Obj.section_begin(), se = Obj.section_end(); si != se; ++si) { section_iterator RelSecI = si->getRelocatedSection(); - if (RelSecI == Obj.end_sections()) + if (RelSecI == Obj.section_end()) continue; StringRef RelSectionName; @@ -702,10 +664,9 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj, if (Rel.Addend != (int64_t)TargetSymbolOffset) continue; - section_iterator tsi(Obj.end_sections()); + section_iterator tsi(Obj.section_end()); check(TargetSymbol->getSection(tsi)); - bool IsCode = false; - tsi->isText(IsCode); + bool IsCode = tsi->isText(); Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections); Rel.Addend = (intptr_t)Addend; return; @@ -911,8 +872,6 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, break; case Triple::aarch64: case Triple::aarch64_be: - case Triple::arm64: - case Triple::arm64_be: resolveAArch64Relocation(Section, Offset, Value, Type, Addend); break; case Triple::arm: // Fall through. @@ -940,8 +899,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section, } relocation_iterator RuntimeDyldELF::processRelocationRef( - unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, - ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, + unsigned SectionID, relocation_iterator RelI, + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, StubMap &Stubs) { uint64_t RelType; Check(RelI->getType(RelType)); @@ -951,75 +911,65 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( // Obtain the symbol name which is referenced in the relocation StringRef TargetName; - if (Symbol != Obj.end_symbols()) + if (Symbol != Obj.symbol_end()) Symbol->getName(TargetName); DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend << " TargetName: " << TargetName << "\n"); RelocationValueRef Value; // First search for the symbol in the local symbol table - SymbolTableMap::const_iterator lsi = Symbols.end(); SymbolRef::Type SymType = SymbolRef::ST_Unknown; - if (Symbol != Obj.end_symbols()) { - lsi = Symbols.find(TargetName.data()); + + // Search for the symbol in the global symbol table + SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end(); + if (Symbol != Obj.symbol_end()) { + gsi = GlobalSymbolTable.find(TargetName.data()); Symbol->getType(SymType); } - if (lsi != Symbols.end()) { - Value.SectionID = lsi->second.first; - Value.Offset = lsi->second.second; - Value.Addend = lsi->second.second + Addend; + if (gsi != GlobalSymbolTable.end()) { + Value.SectionID = gsi->second.first; + Value.Offset = gsi->second.second; + Value.Addend = gsi->second.second + Addend; } else { - // Search for the symbol in the global symbol table - SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end(); - if (Symbol != Obj.end_symbols()) - gsi = GlobalSymbolTable.find(TargetName.data()); - if (gsi != GlobalSymbolTable.end()) { - Value.SectionID = gsi->second.first; - Value.Offset = gsi->second.second; - Value.Addend = gsi->second.second + Addend; - } else { - switch (SymType) { - case SymbolRef::ST_Debug: { - // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously - // and can be changed by another developers. Maybe best way is add - // a new symbol type ST_Section to SymbolRef and use it. - section_iterator si(Obj.end_sections()); - Symbol->getSection(si); - if (si == Obj.end_sections()) - llvm_unreachable("Symbol section not found, bad object file format!"); - DEBUG(dbgs() << "\t\tThis is section symbol\n"); - // Default to 'true' in case isText fails (though it never does). - bool isCode = true; - si->isText(isCode); - Value.SectionID = findOrEmitSection(Obj, (*si), isCode, ObjSectionToID); - Value.Addend = Addend; - break; - } - case SymbolRef::ST_Data: - case SymbolRef::ST_Unknown: { - Value.SymbolName = TargetName.data(); - Value.Addend = Addend; - - // Absolute relocations will have a zero symbol ID (STN_UNDEF), which - // will manifest here as a NULL symbol name. - // We can set this as a valid (but empty) symbol name, and rely - // on addRelocationForSymbol to handle this. - if (!Value.SymbolName) - Value.SymbolName = ""; - break; - } - default: - llvm_unreachable("Unresolved symbol type!"); - break; - } + switch (SymType) { + case SymbolRef::ST_Debug: { + // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously + // and can be changed by another developers. Maybe best way is add + // a new symbol type ST_Section to SymbolRef and use it. + section_iterator si(Obj.section_end()); + Symbol->getSection(si); + if (si == Obj.section_end()) + llvm_unreachable("Symbol section not found, bad object file format!"); + DEBUG(dbgs() << "\t\tThis is section symbol\n"); + bool isCode = si->isText(); + Value.SectionID = findOrEmitSection(Obj, (*si), isCode, ObjSectionToID); + Value.Addend = Addend; + break; + } + case SymbolRef::ST_Data: + case SymbolRef::ST_Unknown: { + Value.SymbolName = TargetName.data(); + Value.Addend = Addend; + + // Absolute relocations will have a zero symbol ID (STN_UNDEF), which + // will manifest here as a NULL symbol name. + // We can set this as a valid (but empty) symbol name, and rely + // on addRelocationForSymbol to handle this. + if (!Value.SymbolName) + Value.SymbolName = ""; + break; + } + default: + llvm_unreachable("Unresolved symbol type!"); + break; } } + uint64_t Offset; Check(RelI->getOffset(Offset)); DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset << "\n"); - if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be || - Arch == Triple::arm64 || Arch == Triple::arm64_be) && + if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be) && (RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26)) { // This is an AArch64 branch relocation, need to use a stub function. DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation."); @@ -1143,7 +1093,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( if (RelType == ELF::R_PPC64_REL24) { // Determine ABI variant in use for this object. unsigned AbiVariant; - Obj.getObjectFile()->getPlatformFlags(AbiVariant); + Obj.getPlatformFlags(AbiVariant); AbiVariant &= ELF::EF_PPC64_ABI; // A PPC branch relocation will need a stub function if the target is // an external symbol (Symbol::ST_Unknown) or if the target address @@ -1323,7 +1273,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef( Stubs[Value] = StubOffset; createStubFunction((uint8_t *)StubAddress); RelocationEntry RE(SectionID, StubOffset + 8, ELF::R_390_64, - Value.Addend - Addend); + Value.Offset); if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -1431,8 +1381,6 @@ size_t RuntimeDyldELF::getGOTEntrySize() { case Triple::x86_64: case Triple::aarch64: case Triple::aarch64_be: - case Triple::arm64: - case Triple::arm64_be: case Triple::ppc64: case Triple::ppc64le: case Triple::systemz: @@ -1505,7 +1453,7 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) { return 0; } -void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg, +void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) { // If necessary, allocate the global offset table if (MemMgr) { @@ -1543,15 +1491,8 @@ void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg, } } -bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const { - if (Buffer->getBufferSize() < strlen(ELF::ElfMagic)) - return false; - return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic, - strlen(ELF::ElfMagic))) == 0; -} - -bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const { - return Obj->isELF(); +bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isELF(); } } // namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 59fdfbe..b4414b0 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIME_DYLD_ELF_H -#define LLVM_RUNTIME_DYLD_ELF_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDELF_H #include "RuntimeDyldImpl.h" #include "llvm/ADT/DenseMap.h" @@ -28,9 +28,11 @@ std::error_code Check(std::error_code Err) { } return Err; } + } // end anonymous namespace class RuntimeDyldELF : public RuntimeDyldImpl { + void resolveRelocation(const SectionEntry &Section, uint64_t Offset, uint64_t Value, uint32_t Type, int64_t Addend, uint64_t SymOffset = 0); @@ -58,8 +60,7 @@ class RuntimeDyldELF : public RuntimeDyldImpl { uint64_t Value, uint32_t Type, int64_t Addend); unsigned getMaxStubSize() override { - if (Arch == Triple::aarch64 || Arch == Triple::arm64 || - Arch == Triple::aarch64_be || Arch == Triple::arm64_be) + if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be) return 20; // movz; movk; movk; movk; br if (Arch == Triple::arm || Arch == Triple::thumb) return 8; // 32-bit instruction and 32-bit address @@ -82,9 +83,11 @@ class RuntimeDyldELF : public RuntimeDyldImpl { return 1; } - void findPPC64TOCSection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, + void findPPC64TOCSection(const ObjectFile &Obj, + ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); - void findOPDEntrySection(ObjectImage &Obj, ObjSectionToIDMap &LocalSections, + void findOPDEntrySection(const ObjectFile &Obj, + ObjSectionToIDMap &LocalSections, RelocationValueRef &Rel); uint64_t findGOTEntry(uint64_t LoadAddr, uint64_t Offset); @@ -105,23 +108,23 @@ class RuntimeDyldELF : public RuntimeDyldImpl { SmallVector RegisteredEHFrameSections; public: - RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} + RuntimeDyldELF(RTDyldMemoryManager *mm); + virtual ~RuntimeDyldELF(); + + std::unique_ptr + loadObject(const object::ObjectFile &O) override; void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override; relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override; - bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; - bool isCompatibleFile(const object::ObjectFile *Buffer) const override; + const ObjectFile &Obj, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; void registerEHFrames() override; void deregisterEHFrames() override; - void finalizeLoad(ObjectImage &ObjImg, + void finalizeLoad(const ObjectFile &Obj, ObjSectionToIDMap &SectionMap) override; - virtual ~RuntimeDyldELF(); - - static ObjectImage *createObjectImage(ObjectBuffer *InputBuffer); - static ObjectImage *createObjectImageFromFile(std::unique_ptr Obj); }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h index 0211d2b..2f3e3a8 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h @@ -11,14 +11,13 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIME_DYLD_IMPL_H -#define LLVM_RUNTIME_DYLD_IMPL_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDIMPL_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Triple.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/Object/ObjectFile.h" @@ -37,7 +36,6 @@ using namespace llvm::object; namespace llvm { -class ObjectBuffer; class Twine; /// SectionEntry - represents a section emitted into memory by the dynamic @@ -70,7 +68,7 @@ public: SectionEntry(StringRef name, uint8_t *address, size_t size, uintptr_t objAddress) : Name(name), Address(address), Size(size), - LoadAddress((uintptr_t)address), StubOffset(size), + LoadAddress(reinterpret_cast(address)), StubOffset(size), ObjAddress(objAddress) {} }; @@ -159,19 +157,15 @@ public: }; class RuntimeDyldImpl { - friend class RuntimeDyldChecker; -private: - - uint64_t getAnySymbolRemoteAddress(StringRef Symbol) { - if (uint64_t InternalSymbolAddr = getSymbolLoadAddress(Symbol)) - return InternalSymbolAddr; - return MemMgr->getSymbolAddress(Symbol); - } - + friend class RuntimeDyld::LoadedObjectInfo; + friend class RuntimeDyldCheckerImpl; protected: // The MemoryManager to load objects into. RTDyldMemoryManager *MemMgr; + // Attached RuntimeDyldChecker instance. Null if no instance attached. + RuntimeDyldCheckerImpl *Checker; + // A list of all sections emitted by the dynamic linker. These sections are // referenced in the code by means of their index in this list - SectionID. typedef SmallVector SectionList; @@ -211,6 +205,7 @@ protected: // modules. This map is indexed by symbol name. StringMap ExternalSymbolRelocations; + typedef std::map StubMap; Triple::ArchType Arch; @@ -245,11 +240,11 @@ protected: return true; } - uint64_t getSectionLoadAddress(unsigned SectionID) { + uint64_t getSectionLoadAddress(unsigned SectionID) const { return Sections[SectionID].LoadAddress; } - uint8_t *getSectionAddress(unsigned SectionID) { + uint8_t *getSectionAddress(unsigned SectionID) const { return (uint8_t *)Sections[SectionID].Address; } @@ -282,17 +277,25 @@ protected: *(Addr + 7) = Value & 0xFF; } + /// Endian-aware read Read the least significant Size bytes from Src. + uint64_t readBytesUnaligned(uint8_t *Src, unsigned Size) const; + + /// Endian-aware write. Write the least significant Size bytes from Value to + /// Dst. + void writeBytesUnaligned(uint64_t Value, uint8_t *Dst, unsigned Size) const; + /// \brief Given the common symbols discovered in the object file, emit a /// new section for them and update the symbol mappings in the object and /// symbol table. - void emitCommonSymbols(ObjectImage &Obj, const CommonSymbolMap &CommonSymbols, + void emitCommonSymbols(const ObjectFile &Obj, + const CommonSymbolMap &CommonSymbols, uint64_t TotalSize, SymbolTableMap &SymbolTable); /// \brief Emits section data from the object file to the MemoryManager. /// \param IsCode if it's true then allocateCodeSection() will be /// used for emits, else allocateDataSection() will be used. /// \return SectionID. - unsigned emitSection(ObjectImage &Obj, const SectionRef &Section, + unsigned emitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode); /// \brief Find Section in LocalSections. If the secton is not found - emit @@ -300,7 +303,7 @@ protected: /// \param IsCode if it's true then allocateCodeSection() will be /// used for emmits, else allocateDataSection() will be used. /// \return SectionID. - unsigned findOrEmitSection(ObjectImage &Obj, const SectionRef &Section, + unsigned findOrEmitSection(const ObjectFile &Obj, const SectionRef &Section, bool IsCode, ObjSectionToIDMap &LocalSections); // \brief Add a relocation entry that uses the given section. @@ -328,8 +331,8 @@ protected: /// \return Iterator to the next relocation that needs to be parsed. virtual relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) = 0; + const ObjectFile &Obj, ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) = 0; /// \brief Resolve relocations to external symbols. void resolveExternalSymbols(); @@ -340,16 +343,19 @@ protected: // \brief Compute an upper bound of the memory that is required to load all // sections - void computeTotalAllocSize(ObjectImage &Obj, uint64_t &CodeSize, + void computeTotalAllocSize(const ObjectFile &Obj, uint64_t &CodeSize, uint64_t &DataSizeRO, uint64_t &DataSizeRW); // \brief Compute the stub buffer size required for a section - unsigned computeSectionStubBufSize(ObjectImage &Obj, + unsigned computeSectionStubBufSize(const ObjectFile &Obj, const SectionRef &Section); + // \brief Implementation of the generic part of the loadObject algorithm. + std::pair loadObjectImpl(const object::ObjectFile &Obj); + public: RuntimeDyldImpl(RTDyldMemoryManager *mm) - : MemMgr(mm), ProcessAllSections(false), HasError(false) { + : MemMgr(mm), Checker(nullptr), ProcessAllSections(false), HasError(false) { } virtual ~RuntimeDyldImpl(); @@ -358,9 +364,14 @@ public: this->ProcessAllSections = ProcessAllSections; } - ObjectImage *loadObject(ObjectImage *InputObject); + void setRuntimeDyldChecker(RuntimeDyldCheckerImpl *Checker) { + this->Checker = Checker; + } + + virtual std::unique_ptr + loadObject(const object::ObjectFile &Obj) = 0; - uint8_t* getSymbolAddress(StringRef Name) { + uint8_t* getSymbolAddress(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); @@ -370,7 +381,7 @@ public: return getSectionAddress(Loc.first) + Loc.second; } - uint64_t getSymbolLoadAddress(StringRef Name) { + uint64_t getSymbolLoadAddress(StringRef Name) const { // FIXME: Just look up as a function for now. Overly simple of course. // Work in progress. SymbolTableMap::const_iterator pos = GlobalSymbolTable.find(Name); @@ -395,14 +406,14 @@ public: // Get the error message. StringRef getErrorString() { return ErrorStr; } - virtual bool isCompatibleFormat(const ObjectBuffer *Buffer) const = 0; - virtual bool isCompatibleFile(const ObjectFile *Obj) const = 0; + virtual bool isCompatibleFile(const ObjectFile &Obj) const = 0; virtual void registerEHFrames(); virtual void deregisterEHFrames(); - virtual void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) {} + virtual void finalizeLoad(const ObjectFile &ObjImg, + ObjSectionToIDMap &SectionMap) {} }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp index 58fb515..21893d2 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp @@ -12,35 +12,49 @@ //===----------------------------------------------------------------------===// #include "RuntimeDyldMachO.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" - -#include "Targets/RuntimeDyldMachOARM.h" #include "Targets/RuntimeDyldMachOAArch64.h" +#include "Targets/RuntimeDyldMachOARM.h" #include "Targets/RuntimeDyldMachOI386.h" #include "Targets/RuntimeDyldMachOX86_64.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" using namespace llvm; using namespace llvm::object; #define DEBUG_TYPE "dyld" +namespace { + +class LoadedMachOObjectInfo : public RuntimeDyld::LoadedObjectInfo { +public: + LoadedMachOObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx, + unsigned EndIdx) + : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {} + + OwningBinary + getObjectForDebug(const ObjectFile &Obj) const override { + return OwningBinary(); + } +}; + +} + namespace llvm { -uint64_t RuntimeDyldMachO::decodeAddend(uint8_t *LocalAddress, unsigned NumBytes, - uint32_t RelType) const { - uint64_t Addend = 0; - memcpy(&Addend, LocalAddress, NumBytes); - return Addend; +int64_t RuntimeDyldMachO::memcpyAddend(const RelocationEntry &RE) const { + unsigned NumBytes = 1 << RE.Size; + uint8_t *Src = Sections[RE.SectionID].Address + RE.Offset; + + return static_cast(readBytesUnaligned(Src, NumBytes)); } RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( - ObjectImage &ObjImg, const relocation_iterator &RI, - const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols) { + const ObjectFile &BaseTObj, const relocation_iterator &RI, + const RelocationEntry &RE, ObjSectionToIDMap &ObjSectionToID) { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); RelocationValueRef Value; @@ -50,38 +64,32 @@ RelocationValueRef RuntimeDyldMachO::getRelocationValueRef( symbol_iterator Symbol = RI->getSymbol(); StringRef TargetName; Symbol->getName(TargetName); - SymbolTableMap::const_iterator SI = Symbols.find(TargetName.data()); - if (SI != Symbols.end()) { + SymbolTableMap::const_iterator SI = + GlobalSymbolTable.find(TargetName.data()); + if (SI != GlobalSymbolTable.end()) { Value.SectionID = SI->second.first; - Value.Addend = SI->second.second + RE.Addend; + Value.Offset = SI->second.second + RE.Addend; } else { - SI = GlobalSymbolTable.find(TargetName.data()); - if (SI != GlobalSymbolTable.end()) { - Value.SectionID = SI->second.first; - Value.Addend = SI->second.second + RE.Addend; - } else { - Value.SymbolName = TargetName.data(); - Value.Addend = RE.Addend; - } + Value.SymbolName = TargetName.data(); + Value.Offset = RE.Addend; } } else { SectionRef Sec = Obj.getRelocationSection(RelInfo); - bool IsCode = false; - Sec.isText(IsCode); - Value.SectionID = findOrEmitSection(ObjImg, Sec, IsCode, ObjSectionToID); - uint64_t Addr; - Sec.getAddress(Addr); - Value.Addend = RE.Addend - Addr; + bool IsCode = Sec.isText(); + Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); + uint64_t Addr = Sec.getAddress(); + Value.Offset = RE.Addend - Addr; } return Value; } void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, - ObjectImage &ObjImg, - const relocation_iterator &RI) { + const ObjectFile &BaseTObj, + const relocation_iterator &RI, + unsigned OffsetToNextPC) { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseTObj); MachO::any_relocation_info RelInfo = Obj.getRelocation(RI->getRawDataRefImpl()); @@ -89,8 +97,7 @@ void RuntimeDyldMachO::makeValueAddendPCRel(RelocationValueRef &Value, if (IsPCRel) { uint64_t RelocAddr = 0; RI->getAddress(RelocAddr); - unsigned RelocSize = Obj.getAnyRelocationLength(RelInfo); - Value.Addend += RelocAddr + (1ULL << RelocSize); + Value.Offset += RelocAddr + OffsetToNextPC; } } @@ -102,80 +109,142 @@ void RuntimeDyldMachO::dumpRelocationToResolve(const RelocationEntry &RE, dbgs() << "resolveRelocation Section: " << RE.SectionID << " LocalAddress: " << format("%p", LocalAddress) - << " FinalAddress: " << format("%p", FinalAddress) - << " Value: " << format("%p", Value) << " Addend: " << RE.Addend + << " FinalAddress: " << format("0x%016" PRIx64, FinalAddress) + << " Value: " << format("0x%016" PRIx64, Value) << " Addend: " << RE.Addend << " isPCRel: " << RE.IsPCRel << " MachoType: " << RE.RelType << " Size: " << (1 << RE.Size) << "\n"; } -bool RuntimeDyldMachO::writeBytesUnaligned(uint8_t *Addr, uint64_t Value, - unsigned Size) { - for (unsigned i = 0; i < Size; ++i) { - *Addr++ = (uint8_t)Value; - Value >>= 8; +section_iterator +RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, + uint64_t Addr) { + section_iterator SI = Obj.section_begin(); + section_iterator SE = Obj.section_end(); + + for (; SI != SE; ++SI) { + uint64_t SAddr = SI->getAddress(); + uint64_t SSize = SI->getSize(); + if ((Addr >= SAddr) && (Addr < SAddr + SSize)) + return SI; } - return false; + return SE; } -bool -RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { - if (InputBuffer->getBufferSize() < 4) - return false; - StringRef Magic(InputBuffer->getBufferStart(), 4); - if (Magic == "\xFE\xED\xFA\xCE") - return true; - if (Magic == "\xCE\xFA\xED\xFE") - return true; - if (Magic == "\xFE\xED\xFA\xCF") - return true; - if (Magic == "\xCF\xFA\xED\xFE") - return true; - return false; + +// Populate __pointers section. +void RuntimeDyldMachO::populateIndirectSymbolPointersSection( + const MachOObjectFile &Obj, + const SectionRef &PTSection, + unsigned PTSectionID) { + assert(!Obj.is64Bit() && + "Pointer table section not supported in 64-bit MachO."); + + MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); + MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); + uint32_t PTSectionSize = Sec32.size; + unsigned FirstIndirectSymbol = Sec32.reserved1; + const unsigned PTEntrySize = 4; + unsigned NumPTEntries = PTSectionSize / PTEntrySize; + unsigned PTEntryOffset = 0; + + assert((PTSectionSize % PTEntrySize) == 0 && + "Pointers section does not contain a whole number of stubs?"); + + DEBUG(dbgs() << "Populating pointer table section " + << Sections[PTSectionID].Name + << ", Section ID " << PTSectionID << ", " + << NumPTEntries << " entries, " << PTEntrySize + << " bytes each:\n"); + + for (unsigned i = 0; i < NumPTEntries; ++i) { + unsigned SymbolIndex = + Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); + symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); + StringRef IndirectSymbolName; + SI->getName(IndirectSymbolName); + DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex + << ", PT offset: " << PTEntryOffset << "\n"); + RelocationEntry RE(PTSectionID, PTEntryOffset, + MachO::GENERIC_RELOC_VANILLA, 0, false, 2); + addRelocationForSymbol(RE, IndirectSymbolName); + PTEntryOffset += PTEntrySize; + } +} + +bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile &Obj) const { + return Obj.isMachO(); } -bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { - return Obj->isMachO(); +template +void RuntimeDyldMachOCRTPBase::finalizeLoad(const ObjectFile &ObjImg, + ObjSectionToIDMap &SectionMap) { + unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; + unsigned TextSID = RTDYLD_INVALID_SECTION_ID; + unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; + ObjSectionToIDMap::iterator i, e; + + for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { + const SectionRef &Section = i->first; + StringRef Name; + Section.getName(Name); + if (Name == "__eh_frame") + EHFrameSID = i->second; + else if (Name == "__text") + TextSID = i->second; + else if (Name == "__gcc_except_tab") + ExceptTabSID = i->second; + else + impl().finalizeSection(ObjImg, i->second, Section); + } + UnregisteredEHFrameSections.push_back( + EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); } -static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, - intptr_t DeltaForEH) { +template +unsigned char *RuntimeDyldMachOCRTPBase::processFDE(unsigned char *P, + int64_t DeltaForText, + int64_t DeltaForEH) { + typedef typename Impl::TargetPtrT TargetPtrT; + DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText << ", Delta for EH: " << DeltaForEH << "\n"); - uint32_t Length = *((uint32_t *)P); + uint32_t Length = readBytesUnaligned(P, 4); P += 4; unsigned char *Ret = P + Length; - uint32_t Offset = *((uint32_t *)P); + uint32_t Offset = readBytesUnaligned(P, 4); if (Offset == 0) // is a CIE return Ret; P += 4; - intptr_t FDELocation = *((intptr_t *)P); - intptr_t NewLocation = FDELocation - DeltaForText; - *((intptr_t *)P) = NewLocation; - P += sizeof(intptr_t); + TargetPtrT FDELocation = readBytesUnaligned(P, sizeof(TargetPtrT)); + TargetPtrT NewLocation = FDELocation - DeltaForText; + writeBytesUnaligned(NewLocation, P, sizeof(TargetPtrT)); + + P += sizeof(TargetPtrT); // Skip the FDE address range - P += sizeof(intptr_t); + P += sizeof(TargetPtrT); uint8_t Augmentationsize = *P; P += 1; if (Augmentationsize != 0) { - intptr_t LSDA = *((intptr_t *)P); - intptr_t NewLSDA = LSDA - DeltaForEH; - *((intptr_t *)P) = NewLSDA; + TargetPtrT LSDA = readBytesUnaligned(P, sizeof(TargetPtrT)); + TargetPtrT NewLSDA = LSDA - DeltaForEH; + writeBytesUnaligned(NewLSDA, P, sizeof(TargetPtrT)); } return Ret; } -static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { - intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; - intptr_t MemDistance = A->LoadAddress - B->LoadAddress; +static int64_t computeDelta(SectionEntry *A, SectionEntry *B) { + int64_t ObjDistance = A->ObjAddress - B->ObjAddress; + int64_t MemDistance = A->LoadAddress - B->LoadAddress; return ObjDistance - MemDistance; } -void RuntimeDyldMachO::registerEHFrames() { +template +void RuntimeDyldMachOCRTPBase::registerEHFrames() { if (!MemMgr) return; @@ -190,8 +259,8 @@ void RuntimeDyldMachO::registerEHFrames() { if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) ExceptTab = &Sections[SectionInfo.ExceptTabSID]; - intptr_t DeltaForText = computeDelta(Text, EHFrame); - intptr_t DeltaForEH = 0; + int64_t DeltaForText = computeDelta(Text, EHFrame); + int64_t DeltaForEH = 0; if (ExceptTab) DeltaForEH = computeDelta(ExceptTab, EHFrame); @@ -208,16 +277,24 @@ void RuntimeDyldMachO::registerEHFrames() { } std::unique_ptr -llvm::RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { +RuntimeDyldMachO::create(Triple::ArchType Arch, RTDyldMemoryManager *MM) { switch (Arch) { default: llvm_unreachable("Unsupported target for RuntimeDyldMachO."); break; case Triple::arm: return make_unique(MM); - case Triple::arm64: return make_unique(MM); + case Triple::aarch64: return make_unique(MM); case Triple::x86: return make_unique(MM); case Triple::x86_64: return make_unique(MM); } } +std::unique_ptr +RuntimeDyldMachO::loadObject(const object::ObjectFile &O) { + unsigned SectionStartIdx, SectionEndIdx; + std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O); + return llvm::make_unique(*this, SectionStartIdx, + SectionEndIdx); +} + } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h index 7d1dc02..f8bfc03 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h @@ -11,10 +11,9 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIME_DYLD_MACHO_H -#define LLVM_RUNTIME_DYLD_MACHO_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_RUNTIMEDYLDMACHO_H -#include "ObjectImageCommon.h" #include "RuntimeDyldImpl.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Format.h" @@ -37,6 +36,7 @@ protected: : EHFrameSID(RTDYLD_INVALID_SECTION_ID), TextSID(RTDYLD_INVALID_SECTION_ID), ExceptTabSID(RTDYLD_INVALID_SECTION_ID) {} + EHFrameRelatedSections(SID EH, SID T, SID Ex) : EHFrameSID(EH), TextSID(T), ExceptTabSID(Ex) {} SID EHFrameSID; @@ -51,9 +51,32 @@ protected: RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {} - /// Extract the addend encoded in the instruction. - uint64_t decodeAddend(uint8_t *LocalAddress, unsigned NumBytes, - uint32_t RelType) const; + /// This convenience method uses memcpy to extract a contiguous addend (the + /// addend size and offset are taken from the corresponding fields of the RE). + int64_t memcpyAddend(const RelocationEntry &RE) const; + + /// Given a relocation_iterator for a non-scattered relocation, construct a + /// RelocationEntry and fill in the common fields. The 'Addend' field is *not* + /// filled in, since immediate encodings are highly target/opcode specific. + /// For targets/opcodes with simple, contiguous immediates (e.g. X86) the + /// memcpyAddend method can be used to read the immediate. + RelocationEntry getRelocationEntry(unsigned SectionID, + const ObjectFile &BaseTObj, + const relocation_iterator &RI) const { + const MachOObjectFile &Obj = + static_cast(BaseTObj); + MachO::any_relocation_info RelInfo = + Obj.getRelocation(RI->getRawDataRefImpl()); + + bool IsPCRel = Obj.getAnyRelocationPCRel(RelInfo); + unsigned Size = Obj.getAnyRelocationLength(RelInfo); + uint64_t Offset; + RI->getOffset(Offset); + MachO::RelocationInfoType RelType = + static_cast(Obj.getAnyRelocationType(RelInfo)); + + return RelocationEntry(SectionID, Offset, RelType, 0, IsPCRel, Size); + } /// Construct a RelocationValueRef representing the relocation target. /// For Symbols in known sections, this will return a RelocationValueRef @@ -64,44 +87,42 @@ protected: /// In both cases the Addend field is *NOT* fixed up to be PC-relative. That /// should be done by the caller where appropriate by calling makePCRel on /// the RelocationValueRef. - RelocationValueRef getRelocationValueRef(ObjectImage &ObjImg, + RelocationValueRef getRelocationValueRef(const ObjectFile &BaseTObj, const relocation_iterator &RI, const RelocationEntry &RE, - ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols); + ObjSectionToIDMap &ObjSectionToID); /// Make the RelocationValueRef addend PC-relative. - void makeValueAddendPCRel(RelocationValueRef &Value, ObjectImage &ObjImg, - const relocation_iterator &RI); + void makeValueAddendPCRel(RelocationValueRef &Value, + const ObjectFile &BaseTObj, + const relocation_iterator &RI, + unsigned OffsetToNextPC); /// Dump information about the relocation entry (RE) and resolved value. void dumpRelocationToResolve(const RelocationEntry &RE, uint64_t Value) const; -public: - /// Create an ObjectImage from the given ObjectBuffer. - static ObjectImage *createObjectImage(ObjectBuffer *InputBuffer) { - return new ObjectImageCommon(InputBuffer); - } + // Return a section iterator for the section containing the given address. + static section_iterator getSectionByAddress(const MachOObjectFile &Obj, + uint64_t Addr); - /// Create an ObjectImage from the given ObjectFile. - static ObjectImage * - createObjectImageFromFile(std::unique_ptr InputObject) { - return new ObjectImageCommon(std::move(InputObject)); - } + + // Populate __pointers section. + void populateIndirectSymbolPointersSection(const MachOObjectFile &Obj, + const SectionRef &PTSection, + unsigned PTSectionID); + +public: /// Create a RuntimeDyldMachO instance for the given target architecture. static std::unique_ptr create(Triple::ArchType Arch, RTDyldMemoryManager *mm); - /// Write the least significant 'Size' bytes in 'Value' out at the address - /// pointed to by Addr. Check for overflow. - bool writeBytesUnaligned(uint8_t *Addr, uint64_t Value, unsigned Size); + std::unique_ptr + loadObject(const object::ObjectFile &O) override; SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; } - bool isCompatibleFormat(const ObjectBuffer *Buffer) const override; - bool isCompatibleFile(const object::ObjectFile *Obj) const override; - void registerEHFrames() override; + bool isCompatibleFile(const object::ObjectFile &Obj) const override; }; /// RuntimeDyldMachOTarget - Templated base class for generic MachO linker @@ -117,57 +138,15 @@ private: Impl &impl() { return static_cast(*this); } const Impl &impl() const { return static_cast(*this); } -protected: - - /// Parse the given relocation, which must be a non-scattered, and - /// return a RelocationEntry representing the information. The 'Addend' field - /// will contain the unmodified instruction immediate. - RelocationEntry getBasicRelocationEntry(unsigned SectionID, - ObjectImage &ObjImg, - const relocation_iterator &RI) const { - const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); - MachO::any_relocation_info RelInfo = - Obj.getRelocation(RI->getRawDataRefImpl()); - - const SectionEntry &Section = Sections[SectionID]; - bool IsPCRel = Obj.getAnyRelocationPCRel(RelInfo); - unsigned Size = Obj.getAnyRelocationLength(RelInfo); - uint64_t Offset; - RI->getOffset(Offset); - uint8_t *LocalAddress = Section.Address + Offset; - unsigned NumBytes = 1 << Size; - uint32_t RelType = Obj.getAnyRelocationType(RelInfo); - uint64_t Addend = impl().decodeAddend(LocalAddress, NumBytes, RelType); - - return RelocationEntry(SectionID, Offset, RelType, Addend, IsPCRel, Size); - } + unsigned char *processFDE(unsigned char *P, int64_t DeltaForText, + int64_t DeltaForEH); public: RuntimeDyldMachOCRTPBase(RTDyldMemoryManager *mm) : RuntimeDyldMachO(mm) {} - void finalizeLoad(ObjectImage &ObjImg, ObjSectionToIDMap &SectionMap) { - unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; - unsigned TextSID = RTDYLD_INVALID_SECTION_ID; - unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; - ObjSectionToIDMap::iterator i, e; - - for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { - const SectionRef &Section = i->first; - StringRef Name; - Section.getName(Name); - if (Name == "__eh_frame") - EHFrameSID = i->second; - else if (Name == "__text") - TextSID = i->second; - else if (Name == "__gcc_except_tab") - ExceptTabSID = i->second; - else - impl().finalizeSection(ObjImg, i->second, Section); - } - UnregisteredEHFrameSections.push_back( - EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); - } + void finalizeLoad(const ObjectFile &Obj, + ObjSectionToIDMap &SectionMap) override; + void registerEHFrames() override; }; } // end namespace llvm diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h index 775ed9e..196fa62 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOAArch64.h @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIMEDYLDMACHOAARCH64_H -#define LLVM_RUNTIMEDYLDMACHOAARCH64_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOAARCH64_H #include "../RuntimeDyldMachO.h" +#include "llvm/Support/Endian.h" #define DEBUG_TYPE "dyld" @@ -19,6 +20,9 @@ namespace llvm { class RuntimeDyldMachOAArch64 : public RuntimeDyldMachOCRTPBase { public: + + typedef uint64_t TargetPtrT; + RuntimeDyldMachOAArch64(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} @@ -26,12 +30,224 @@ public: unsigned getStubAlignment() override { return 8; } + /// Extract the addend encoded in the instruction / memory location. + int64_t decodeAddend(const RelocationEntry &RE) const { + const SectionEntry &Section = Sections[RE.SectionID]; + uint8_t *LocalAddress = Section.Address + RE.Offset; + unsigned NumBytes = 1 << RE.Size; + int64_t Addend = 0; + // Verify that the relocation has the correct size and alignment. + switch (RE.RelType) { + default: + llvm_unreachable("Unsupported relocation type!"); + case MachO::ARM64_RELOC_UNSIGNED: + assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size."); + break; + case MachO::ARM64_RELOC_BRANCH26: + case MachO::ARM64_RELOC_PAGE21: + case MachO::ARM64_RELOC_PAGEOFF12: + case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: + case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: + assert(NumBytes == 4 && "Invalid relocation size."); + assert((((uintptr_t)LocalAddress & 0x3) == 0) && + "Instruction address is not aligned to 4 bytes."); + break; + } + + switch (RE.RelType) { + default: + llvm_unreachable("Unsupported relocation type!"); + case MachO::ARM64_RELOC_UNSIGNED: + // This could be an unaligned memory location. + if (NumBytes == 4) + Addend = *reinterpret_cast(LocalAddress); + else + Addend = *reinterpret_cast(LocalAddress); + break; + case MachO::ARM64_RELOC_BRANCH26: { + // Verify that the relocation points to the expected branch instruction. + auto *p = reinterpret_cast(LocalAddress); + assert((*p & 0xFC000000) == 0x14000000 && "Expected branch instruction."); + + // Get the 26 bit addend encoded in the branch instruction and sign-extend + // to 64 bit. The lower 2 bits are always zeros and are therefore implicit + // (<< 2). + Addend = (*p & 0x03FFFFFF) << 2; + Addend = SignExtend64(Addend, 28); + break; + } + case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: + case MachO::ARM64_RELOC_PAGE21: { + // Verify that the relocation points to the expected adrp instruction. + auto *p = reinterpret_cast(LocalAddress); + assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction."); + + // Get the 21 bit addend encoded in the adrp instruction and sign-extend + // to 64 bit. The lower 12 bits (4096 byte page) are always zeros and are + // therefore implicit (<< 12). + Addend = ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3) << 12; + Addend = SignExtend64(Addend, 33); + break; + } + case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: { + // Verify that the relocation points to one of the expected load / store + // instructions. + auto *p = reinterpret_cast(LocalAddress); + (void)p; + assert((*p & 0x3B000000) == 0x39000000 && + "Only expected load / store instructions."); + } // fall-through + case MachO::ARM64_RELOC_PAGEOFF12: { + // Verify that the relocation points to one of the expected load / store + // or add / sub instructions. + auto *p = reinterpret_cast(LocalAddress); + assert((((*p & 0x3B000000) == 0x39000000) || + ((*p & 0x11C00000) == 0x11000000) ) && + "Expected load / store or add/sub instruction."); + + // Get the 12 bit addend encoded in the instruction. + Addend = (*p & 0x003FFC00) >> 10; + + // Check which instruction we are decoding to obtain the implicit shift + // factor of the instruction. + int ImplicitShift = 0; + if ((*p & 0x3B000000) == 0x39000000) { // << load / store + // For load / store instructions the size is encoded in bits 31:30. + ImplicitShift = ((*p >> 30) & 0x3); + if (ImplicitShift == 0) { + // Check if this a vector op to get the correct shift value. + if ((*p & 0x04800000) == 0x04800000) + ImplicitShift = 4; + } + } + // Compensate for implicit shift. + Addend <<= ImplicitShift; + break; + } + } + return Addend; + } + + /// Extract the addend encoded in the instruction. + void encodeAddend(uint8_t *LocalAddress, unsigned NumBytes, + MachO::RelocationInfoType RelType, int64_t Addend) const { + // Verify that the relocation has the correct alignment. + switch (RelType) { + default: + llvm_unreachable("Unsupported relocation type!"); + case MachO::ARM64_RELOC_UNSIGNED: + assert((NumBytes == 4 || NumBytes == 8) && "Invalid relocation size."); + break; + case MachO::ARM64_RELOC_BRANCH26: + case MachO::ARM64_RELOC_PAGE21: + case MachO::ARM64_RELOC_PAGEOFF12: + case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: + case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: + assert(NumBytes == 4 && "Invalid relocation size."); + assert((((uintptr_t)LocalAddress & 0x3) == 0) && + "Instruction address is not aligned to 4 bytes."); + break; + } + + switch (RelType) { + default: + llvm_unreachable("Unsupported relocation type!"); + case MachO::ARM64_RELOC_UNSIGNED: + // This could be an unaligned memory location. + if (NumBytes == 4) + *reinterpret_cast(LocalAddress) = Addend; + else + *reinterpret_cast(LocalAddress) = Addend; + break; + case MachO::ARM64_RELOC_BRANCH26: { + auto *p = reinterpret_cast(LocalAddress); + // Verify that the relocation points to the expected branch instruction. + assert((*p & 0xFC000000) == 0x14000000 && "Expected branch instruction."); + + // Verify addend value. + assert((Addend & 0x3) == 0 && "Branch target is not aligned"); + assert(isInt<28>(Addend) && "Branch target is out of range."); + + // Encode the addend as 26 bit immediate in the branch instruction. + *p = (*p & 0xFC000000) | ((uint32_t)(Addend >> 2) & 0x03FFFFFF); + break; + } + case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: + case MachO::ARM64_RELOC_PAGE21: { + // Verify that the relocation points to the expected adrp instruction. + auto *p = reinterpret_cast(LocalAddress); + assert((*p & 0x9F000000) == 0x90000000 && "Expected adrp instruction."); + + // Check that the addend fits into 21 bits (+ 12 lower bits). + assert((Addend & 0xFFF) == 0 && "ADRP target is not page aligned."); + assert(isInt<33>(Addend) && "Invalid page reloc value."); + + // Encode the addend into the instruction. + uint32_t ImmLoValue = ((uint64_t)Addend << 17) & 0x60000000; + uint32_t ImmHiValue = ((uint64_t)Addend >> 9) & 0x00FFFFE0; + *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue; + break; + } + case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: { + // Verify that the relocation points to one of the expected load / store + // instructions. + auto *p = reinterpret_cast(LocalAddress); + assert((*p & 0x3B000000) == 0x39000000 && + "Only expected load / store instructions."); + (void)p; + } // fall-through + case MachO::ARM64_RELOC_PAGEOFF12: { + // Verify that the relocation points to one of the expected load / store + // or add / sub instructions. + auto *p = reinterpret_cast(LocalAddress); + assert((((*p & 0x3B000000) == 0x39000000) || + ((*p & 0x11C00000) == 0x11000000) ) && + "Expected load / store or add/sub instruction."); + + // Check which instruction we are decoding to obtain the implicit shift + // factor of the instruction and verify alignment. + int ImplicitShift = 0; + if ((*p & 0x3B000000) == 0x39000000) { // << load / store + // For load / store instructions the size is encoded in bits 31:30. + ImplicitShift = ((*p >> 30) & 0x3); + switch (ImplicitShift) { + case 0: + // Check if this a vector op to get the correct shift value. + if ((*p & 0x04800000) == 0x04800000) { + ImplicitShift = 4; + assert(((Addend & 0xF) == 0) && + "128-bit LDR/STR not 16-byte aligned."); + } + break; + case 1: + assert(((Addend & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned."); + break; + case 2: + assert(((Addend & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned."); + break; + case 3: + assert(((Addend & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned."); + break; + } + } + // Compensate for implicit shift. + Addend >>= ImplicitShift; + assert(isUInt<12>(Addend) && "Addend cannot be encoded."); + + // Encode the addend into the instruction. + *p = (*p & 0xFFC003FF) | ((uint32_t)(Addend << 10) & 0x003FFC00); + break; + } + } + } + relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); @@ -41,34 +257,35 @@ public: // addend for the following relocation. If found: (1) store the associated // addend, (2) consume the next relocation, and (3) use the stored addend to // override the addend. - bool HasExplicitAddend = false; int64_t ExplicitAddend = 0; if (Obj.getAnyRelocationType(RelInfo) == MachO::ARM64_RELOC_ADDEND) { assert(!Obj.getPlainRelocationExternal(RelInfo)); assert(!Obj.getAnyRelocationPCRel(RelInfo)); assert(Obj.getAnyRelocationLength(RelInfo) == 2); - HasExplicitAddend = true; int64_t RawAddend = Obj.getPlainRelocationSymbolNum(RelInfo); // Sign-extend the 24-bit to 64-bit. - ExplicitAddend = (RawAddend << 40) >> 40; + ExplicitAddend = SignExtend64(RawAddend, 24); ++RelI; RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); } - RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); + RE.Addend = decodeAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); - if (HasExplicitAddend) { + assert((ExplicitAddend == 0 || RE.Addend == 0) && "Relocation has "\ + "ARM64_RELOC_ADDEND and embedded addend in the instruction."); + if (ExplicitAddend) { RE.Addend = ExplicitAddend; - Value.Addend = ExplicitAddend; + Value.Offset = ExplicitAddend; } bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); - RE.Addend = Value.Addend; + RE.Addend = Value.Offset; if (RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGE21 || RE.RelType == MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12) @@ -83,13 +300,15 @@ public: return ++RelI; } - void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { DEBUG(dumpRelocationToResolve(RE, Value)); const SectionEntry &Section = Sections[RE.SectionID]; uint8_t *LocalAddress = Section.Address + RE.Offset; + MachO::RelocationInfoType RelType = + static_cast(RE.RelType); - switch (RE.RelType) { + switch (RelType) { default: llvm_unreachable("Invalid relocation type!"); case MachO::ARM64_RELOC_UNSIGNED: { @@ -99,117 +318,49 @@ public: if (RE.Size < 2) llvm_unreachable("Invalid size for ARM64_RELOC_UNSIGNED"); - writeBytesUnaligned(LocalAddress, Value + RE.Addend, 1 << RE.Size); + encodeAddend(LocalAddress, 1 << RE.Size, RelType, Value + RE.Addend); break; } case MachO::ARM64_RELOC_BRANCH26: { assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_BRANCH26 not supported"); - // Mask the value into the target address. We know instructions are - // 32-bit aligned, so we can do it all at once. - uint32_t *p = (uint32_t *)LocalAddress; - // Check if the addend is encoded in the instruction. - uint32_t EncodedAddend = *p & 0x03FFFFFF; - if (EncodedAddend != 0) { - if (RE.Addend == 0) - llvm_unreachable("branch26 instruction has embedded addend."); - else - llvm_unreachable("branch26 instruction has embedded addend and" - "ARM64_RELOC_ADDEND."); - } // Check if branch is in range. uint64_t FinalAddress = Section.LoadAddress + RE.Offset; - uint64_t PCRelVal = Value - FinalAddress + RE.Addend; - assert(isInt<26>(PCRelVal) && "Branch target out of range!"); - // Insert the value into the instruction. - *p = (*p & 0xFC000000) | ((uint32_t)(PCRelVal >> 2) & 0x03FFFFFF); + int64_t PCRelVal = Value - FinalAddress + RE.Addend; + encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal); break; } case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: case MachO::ARM64_RELOC_PAGE21: { assert(RE.IsPCRel && "not PCRel and ARM64_RELOC_PAGE21 not supported"); - // Mask the value into the target address. We know instructions are - // 32-bit aligned, so we can do it all at once. - uint32_t *p = (uint32_t *)LocalAddress; - // Check if the addend is encoded in the instruction. - uint32_t EncodedAddend = - ((*p & 0x60000000) >> 29) | ((*p & 0x01FFFFE0) >> 3); - if (EncodedAddend != 0) { - if (RE.Addend == 0) - llvm_unreachable("adrp instruction has embedded addend."); - else - llvm_unreachable("adrp instruction has embedded addend and" - "ARM64_RELOC_ADDEND."); - } // Adjust for PC-relative relocation and offset. uint64_t FinalAddress = Section.LoadAddress + RE.Offset; - uint64_t PCRelVal = - ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096)); - // Check that the value fits into 21 bits (+ 12 lower bits). - assert(isInt<33>(PCRelVal) && "Invalid page reloc value!"); - // Insert the value into the instruction. - uint32_t ImmLoValue = (uint32_t)(PCRelVal << 17) & 0x60000000; - uint32_t ImmHiValue = (uint32_t)(PCRelVal >> 9) & 0x00FFFFE0; - *p = (*p & 0x9F00001F) | ImmHiValue | ImmLoValue; + int64_t PCRelVal = + ((Value + RE.Addend) & (-4096)) - (FinalAddress & (-4096)); + encodeAddend(LocalAddress, /*Size=*/4, RelType, PCRelVal); break; } case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: case MachO::ARM64_RELOC_PAGEOFF12: { assert(!RE.IsPCRel && "PCRel and ARM64_RELOC_PAGEOFF21 not supported"); - // Mask the value into the target address. We know instructions are - // 32-bit aligned, so we can do it all at once. - uint32_t *p = (uint32_t *)LocalAddress; - // Check if the addend is encoded in the instruction. - uint32_t EncodedAddend = *p & 0x003FFC00; - if (EncodedAddend != 0) { - if (RE.Addend == 0) - llvm_unreachable("adrp instruction has embedded addend."); - else - llvm_unreachable("adrp instruction has embedded addend and" - "ARM64_RELOC_ADDEND."); - } // Add the offset from the symbol. Value += RE.Addend; // Mask out the page address and only use the lower 12 bits. Value &= 0xFFF; - // Check which instruction we are updating to obtain the implicit shift - // factor from LDR/STR instructions. - if (*p & 0x08000000) { - uint32_t ImplicitShift = ((*p >> 30) & 0x3); - switch (ImplicitShift) { - case 0: - // Check if this a vector op. - if ((*p & 0x04800000) == 0x04800000) { - ImplicitShift = 4; - assert(((Value & 0xF) == 0) && - "128-bit LDR/STR not 16-byte aligned."); - } - break; - case 1: - assert(((Value & 0x1) == 0) && "16-bit LDR/STR not 2-byte aligned."); - case 2: - assert(((Value & 0x3) == 0) && "32-bit LDR/STR not 4-byte aligned."); - case 3: - assert(((Value & 0x7) == 0) && "64-bit LDR/STR not 8-byte aligned."); - } - // Compensate for implicit shift. - Value >>= ImplicitShift; - } - // Insert the value into the instruction. - *p = (*p & 0xFFC003FF) | ((uint32_t)(Value << 10) & 0x003FFC00); + encodeAddend(LocalAddress, /*Size=*/4, RelType, Value); break; } case MachO::ARM64_RELOC_SUBTRACTOR: case MachO::ARM64_RELOC_POINTER_TO_GOT: case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: - llvm_unreachable("Relocation type not implemented yet!"); + llvm_unreachable("Relocation type not yet implemented!"); case MachO::ARM64_RELOC_ADDEND: llvm_unreachable("ARM64_RELOC_ADDEND should have been handeled by " "processRelocationRef!"); } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) {} private: @@ -218,9 +369,9 @@ private: assert(RE.Size == 2); SectionEntry &Section = Sections[RE.SectionID]; StubMap::const_iterator i = Stubs.find(Value); - uint8_t *Addr; + int64_t Offset; if (i != Stubs.end()) - Addr = Section.Address + i->second; + Offset = static_cast(i->second); else { // FIXME: There must be a better way to do this then to check and fix the // alignment every time!!! @@ -234,22 +385,22 @@ private: assert(((StubAddress % getStubAlignment()) == 0) && "GOT entry not aligned"); RelocationEntry GOTRE(RE.SectionID, StubOffset, - MachO::ARM64_RELOC_UNSIGNED, Value.Addend, + MachO::ARM64_RELOC_UNSIGNED, Value.Offset, /*IsPCRel=*/false, /*Size=*/3); if (Value.SymbolName) addRelocationForSymbol(GOTRE, Value.SymbolName); else addRelocationForSection(GOTRE, Value.SectionID); Section.StubOffset = StubOffset + getMaxStubSize(); - Addr = (uint8_t *)StubAddress; + Offset = static_cast(StubOffset); } - RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, /*Addend=*/0, + RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, Offset, RE.IsPCRel, RE.Size); - resolveRelocation(TargetRE, (uint64_t)Addr); + addRelocationForSection(TargetRE, RE.SectionID); } }; } #undef DEBUG_TYPE -#endif // LLVM_RUNTIMEDYLDMACHOAARCH64_H +#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h index 1de9942..09e430e 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOARM.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIMEDYLDMACHOARM_H -#define LLVM_RUNTIMEDYLDMACHOARM_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOARM_H #include "../RuntimeDyldMachO.h" @@ -18,37 +18,66 @@ namespace llvm { class RuntimeDyldMachOARM : public RuntimeDyldMachOCRTPBase { +private: + typedef RuntimeDyldMachOCRTPBase ParentT; + public: + + typedef uint32_t TargetPtrT; + RuntimeDyldMachOARM(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} unsigned getMaxStubSize() override { return 8; } unsigned getStubAlignment() override { return 4; } + int64_t decodeAddend(const RelocationEntry &RE) const { + const SectionEntry &Section = Sections[RE.SectionID]; + uint8_t *LocalAddress = Section.Address + RE.Offset; + + switch (RE.RelType) { + default: + return memcpyAddend(RE); + case MachO::ARM_RELOC_BR24: { + uint32_t Temp = readBytesUnaligned(LocalAddress, 4); + Temp &= 0x00ffffff; // Mask out the opcode. + // Now we've got the shifted immediate, shift by 2, sign extend and ret. + return SignExtend32<26>(Temp << 2); + } + } + } + relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); + uint32_t RelType = Obj.getAnyRelocationType(RelInfo); - if (Obj.isRelocationScattered(RelInfo)) - return ++++RelI; + if (Obj.isRelocationScattered(RelInfo)) { + if (RelType == MachO::ARM_RELOC_HALF_SECTDIFF) + return processHALFSECTDIFFRelocation(SectionID, RelI, Obj, + ObjSectionToID); + else + return ++++RelI; + } - RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); + RE.Addend = decodeAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); - bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); - if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + if (RE.IsPCRel) + makeValueAddendPCRel(Value, Obj, RelI, 8); if ((RE.RelType & 0xf) == MachO::ARM_RELOC_BR24) processBranchRelocation(RE, Value, Stubs); else { - RE.Addend = Value.Addend; + RE.Addend = Value.Offset; if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -58,7 +87,7 @@ public: return ++RelI; } - void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { DEBUG(dumpRelocationToResolve(RE, Value)); const SectionEntry &Section = Sections[RE.SectionID]; uint8_t *LocalAddress = Section.Address + RE.Offset; @@ -78,33 +107,45 @@ public: default: llvm_unreachable("Invalid relocation type!"); case MachO::ARM_RELOC_VANILLA: - writeBytesUnaligned(LocalAddress, Value, 1 << RE.Size); + writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); break; case MachO::ARM_RELOC_BR24: { // Mask the value into the target address. We know instructions are // 32-bit aligned, so we can do it all at once. - uint32_t *p = (uint32_t *)LocalAddress; + Value += RE.Addend; // The low two bits of the value are not encoded. Value >>= 2; // Mask the value to 24 bits. uint64_t FinalValue = Value & 0xffffff; - // Check for overflow. - if (Value != FinalValue) { - Error("ARM BR24 relocation out of range."); - return; - } // FIXME: If the destination is a Thumb function (and the instruction // is a non-predicated BL instruction), we need to change it to a BLX // instruction instead. // Insert the value into the instruction. - *p = (*p & ~0xffffff) | FinalValue; + uint32_t Temp = readBytesUnaligned(LocalAddress, 4); + writeBytesUnaligned((Temp & ~0xffffff) | FinalValue, LocalAddress, 4); + + break; + } + case MachO::ARM_RELOC_HALF_SECTDIFF: { + uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress; + uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress; + assert((Value == SectionABase || Value == SectionBBase) && + "Unexpected HALFSECTDIFF relocation value."); + Value = SectionABase - SectionBBase + RE.Addend; + if (RE.Size & 0x1) // :upper16: + Value = (Value >> 16); + Value &= 0xffff; + + uint32_t Insn = readBytesUnaligned(LocalAddress, 4); + Insn = (Insn & 0xfff0f000) | ((Value & 0xf000) << 4) | (Value & 0x0fff); + writeBytesUnaligned(Insn, LocalAddress, 4); break; } + case MachO::ARM_THUMB_RELOC_BR22: case MachO::ARM_THUMB_32BIT_BRANCH: case MachO::ARM_RELOC_HALF: - case MachO::ARM_RELOC_HALF_SECTDIFF: case MachO::ARM_RELOC_PAIR: case MachO::ARM_RELOC_SECTDIFF: case MachO::ARM_RELOC_LOCAL_SECTDIFF: @@ -114,10 +155,18 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, - const SectionRef &Section) {} + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, + const SectionRef &Section) { + StringRef Name; + Section.getName(Name); + + if (Name == "__nl_symbol_ptr") + populateIndirectSymbolPointersSection(cast(Obj), + Section, SectionID); + } private: + void processBranchRelocation(const RelocationEntry &RE, const RelocationValueRef &Value, StubMap &Stubs) { @@ -134,7 +183,8 @@ private: uint8_t *StubTargetAddr = createStubFunction(Section.Address + Section.StubOffset); RelocationEntry StubRE(RE.SectionID, StubTargetAddr - Section.Address, - MachO::GENERIC_RELOC_VANILLA, Value.Addend); + MachO::GENERIC_RELOC_VANILLA, Value.Offset, false, + 2); if (Value.SymbolName) addRelocationForSymbol(StubRE, Value.SymbolName); else @@ -142,13 +192,86 @@ private: Addr = Section.Address + Section.StubOffset; Section.StubOffset += getMaxStubSize(); } - RelocationEntry TargetRE(Value.SectionID, RE.Offset, RE.RelType, 0, + RelocationEntry TargetRE(RE.SectionID, RE.Offset, RE.RelType, 0, RE.IsPCRel, RE.Size); resolveRelocation(TargetRE, (uint64_t)Addr); } + + relocation_iterator + processHALFSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, + const ObjectFile &BaseTObj, + ObjSectionToIDMap &ObjSectionToID) { + const MachOObjectFile &MachO = + static_cast(BaseTObj); + MachO::any_relocation_info RE = + MachO.getRelocation(RelI->getRawDataRefImpl()); + + + // For a half-diff relocation the length bits actually record whether this + // is a movw/movt, and whether this is arm or thumb. + // Bit 0 indicates movw (b0 == 0) or movt (b0 == 1). + // Bit 1 indicates arm (b1 == 0) or thumb (b1 == 1). + unsigned HalfDiffKindBits = MachO.getAnyRelocationLength(RE); + if (HalfDiffKindBits & 0x2) + llvm_unreachable("Thumb not yet supported."); + + SectionEntry &Section = Sections[SectionID]; + uint32_t RelocType = MachO.getAnyRelocationType(RE); + bool IsPCRel = MachO.getAnyRelocationPCRel(RE); + uint64_t Offset; + RelI->getOffset(Offset); + uint8_t *LocalAddress = Section.Address + Offset; + int64_t Immediate = readBytesUnaligned(LocalAddress, 4); // Copy the whole instruction out. + Immediate = ((Immediate >> 4) & 0xf000) | (Immediate & 0xfff); + + ++RelI; + MachO::any_relocation_info RE2 = + MachO.getRelocation(RelI->getRawDataRefImpl()); + uint32_t AddrA = MachO.getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(MachO, AddrA); + assert(SAI != MachO.section_end() && "Can't find section for address A"); + uint64_t SectionABase = SAI->getAddress(); + uint64_t SectionAOffset = AddrA - SectionABase; + SectionRef SectionA = *SAI; + bool IsCode = SectionA.isText(); + uint32_t SectionAID = + findOrEmitSection(MachO, SectionA, IsCode, ObjSectionToID); + + uint32_t AddrB = MachO.getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(MachO, AddrB); + assert(SBI != MachO.section_end() && "Can't find section for address B"); + uint64_t SectionBBase = SBI->getAddress(); + uint64_t SectionBOffset = AddrB - SectionBBase; + SectionRef SectionB = *SBI; + uint32_t SectionBID = + findOrEmitSection(MachO, SectionB, IsCode, ObjSectionToID); + + uint32_t OtherHalf = MachO.getAnyRelocationAddress(RE2) & 0xffff; + unsigned Shift = (HalfDiffKindBits & 0x1) ? 16 : 0; + uint32_t FullImmVal = (Immediate << Shift) | (OtherHalf << (16 - Shift)); + int64_t Addend = FullImmVal - (AddrA - AddrB); + + // addend = Encoded - Expected + // = Encoded - (AddrA - AddrB) + + DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB + << ", Addend: " << Addend << ", SectionA ID: " << SectionAID + << ", SectionAOffset: " << SectionAOffset + << ", SectionB ID: " << SectionBID + << ", SectionBOffset: " << SectionBOffset << "\n"); + RelocationEntry R(SectionID, Offset, RelocType, Addend, SectionAID, + SectionAOffset, SectionBID, SectionBOffset, IsPCRel, + HalfDiffKindBits); + + addRelocationForSection(R, SectionAID); + addRelocationForSection(R, SectionBID); + + return ++RelI; + } + }; } #undef DEBUG_TYPE -#endif // LLVM_RUNTIMEDYLDMACHOARM_H +#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h index 856c6ca..67d7027 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOI386.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIMEDYLDMACHOI386_H -#define LLVM_RUNTIMEDYLDMACHOI386_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOI386_H #include "../RuntimeDyldMachO.h" @@ -19,6 +19,9 @@ namespace llvm { class RuntimeDyldMachOI386 : public RuntimeDyldMachOCRTPBase { public: + + typedef uint32_t TargetPtrT; + RuntimeDyldMachOI386(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} @@ -28,10 +31,11 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); uint32_t RelType = Obj.getAnyRelocationType(RelInfo); @@ -39,17 +43,18 @@ public: if (Obj.isRelocationScattered(RelInfo)) { if (RelType == MachO::GENERIC_RELOC_SECTDIFF || RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) - return processSECTDIFFRelocation(SectionID, RelI, ObjImg, + return processSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID); - else if (Arch == Triple::x86 && RelType == MachO::GENERIC_RELOC_VANILLA) - return processI386ScatteredVANILLA(SectionID, RelI, ObjImg, + else if (RelType == MachO::GENERIC_RELOC_VANILLA) + return processI386ScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); llvm_unreachable("Unhandled scattered relocation."); } - RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); + RE.Addend = memcpyAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); // Addends for external, PC-rel relocations on i386 point back to the zero // offset. Calculate the final offset from the relocation target instead. @@ -62,9 +67,9 @@ public: // Value.Addend += RelocAddr + 4; // } if (RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); - RE.Addend = Value.Addend; + RE.Addend = Value.Offset; if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); @@ -74,7 +79,7 @@ public: return ++RelI; } - void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { DEBUG(dumpRelocationToResolve(RE, Value)); const SectionEntry &Section = Sections[RE.SectionID]; @@ -89,7 +94,7 @@ public: default: llvm_unreachable("Invalid relocation type!"); case MachO::GENERIC_RELOC_VANILLA: - writeBytesUnaligned(LocalAddress, Value + RE.Addend, 1 << RE.Size); + writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); break; case MachO::GENERIC_RELOC_SECTDIFF: case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { @@ -98,7 +103,7 @@ public: assert((Value == SectionABase || Value == SectionBBase) && "Unexpected SECTDIFF relocation value."); Value = SectionABase - SectionBBase + RE.Addend; - writeBytesUnaligned(LocalAddress, Value, 1 << RE.Size); + writeBytesUnaligned(Value, LocalAddress, 1 << RE.Size); break; } case MachO::GENERIC_RELOC_PB_LA_PTR: @@ -106,61 +111,56 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) { StringRef Name; Section.getName(Name); if (Name == "__jump_table") - populateJumpTable(cast(*ObjImg.getObjectFile()), Section, - SectionID); + populateJumpTable(cast(Obj), Section, SectionID); else if (Name == "__pointers") - populatePointersSection(cast(*ObjImg.getObjectFile()), - Section, SectionID); + populateIndirectSymbolPointersSection(cast(Obj), + Section, SectionID); } private: relocation_iterator processSECTDIFFRelocation(unsigned SectionID, relocation_iterator RelI, - ObjectImage &Obj, + const ObjectFile &BaseObjT, ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast(Obj.getObjectFile()); + const MachOObjectFile &Obj = + static_cast(BaseObjT); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); - unsigned Size = MachO->getAnyRelocationLength(RE); + uint32_t RelocType = Obj.getAnyRelocationType(RE); + bool IsPCRel = Obj.getAnyRelocationPCRel(RE); + unsigned Size = Obj.getAnyRelocationLength(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; unsigned NumBytes = 1 << Size; - int64_t Addend = 0; - memcpy(&Addend, LocalAddress, NumBytes); + uint64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); ++RelI; MachO::any_relocation_info RE2 = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); - uint32_t AddrA = MachO->getScatteredRelocationValue(RE); - section_iterator SAI = getSectionByAddress(*MachO, AddrA); - assert(SAI != MachO->section_end() && "Can't find section for address A"); - uint64_t SectionABase; - SAI->getAddress(SectionABase); + uint32_t AddrA = Obj.getScatteredRelocationValue(RE); + section_iterator SAI = getSectionByAddress(Obj, AddrA); + assert(SAI != Obj.section_end() && "Can't find section for address A"); + uint64_t SectionABase = SAI->getAddress(); uint64_t SectionAOffset = AddrA - SectionABase; SectionRef SectionA = *SAI; - bool IsCode; - SectionA.isText(IsCode); + bool IsCode = SectionA.isText(); uint32_t SectionAID = findOrEmitSection(Obj, SectionA, IsCode, ObjSectionToID); - uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); - section_iterator SBI = getSectionByAddress(*MachO, AddrB); - assert(SBI != MachO->section_end() && "Can't find section for address B"); - uint64_t SectionBBase; - SBI->getAddress(SectionBBase); + uint32_t AddrB = Obj.getScatteredRelocationValue(RE2); + section_iterator SBI = getSectionByAddress(Obj, AddrB); + assert(SBI != Obj.section_end() && "Can't find section for address B"); + uint64_t SectionBBase = SBI->getAddress(); uint64_t SectionBOffset = AddrB - SectionBBase; SectionRef SectionB = *SBI; uint32_t SectionBID = @@ -185,32 +185,30 @@ private: } relocation_iterator processI386ScatteredVANILLA( - unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, + unsigned SectionID, relocation_iterator RelI, + const ObjectFile &BaseObjT, RuntimeDyldMachO::ObjSectionToIDMap &ObjSectionToID) { - const MachOObjectFile *MachO = - static_cast(Obj.getObjectFile()); + const MachOObjectFile &Obj = + static_cast(BaseObjT); MachO::any_relocation_info RE = - MachO->getRelocation(RelI->getRawDataRefImpl()); + Obj.getRelocation(RelI->getRawDataRefImpl()); SectionEntry &Section = Sections[SectionID]; - uint32_t RelocType = MachO->getAnyRelocationType(RE); - bool IsPCRel = MachO->getAnyRelocationPCRel(RE); - unsigned Size = MachO->getAnyRelocationLength(RE); + uint32_t RelocType = Obj.getAnyRelocationType(RE); + bool IsPCRel = Obj.getAnyRelocationPCRel(RE); + unsigned Size = Obj.getAnyRelocationLength(RE); uint64_t Offset; RelI->getOffset(Offset); uint8_t *LocalAddress = Section.Address + Offset; unsigned NumBytes = 1 << Size; - int64_t Addend = 0; - memcpy(&Addend, LocalAddress, NumBytes); - - unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE); - section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr); - assert(TargetSI != MachO->section_end() && "Can't find section for symbol"); - uint64_t SectionBaseAddr; - TargetSI->getAddress(SectionBaseAddr); + int64_t Addend = readBytesUnaligned(LocalAddress, NumBytes); + + unsigned SymbolBaseAddr = Obj.getScatteredRelocationValue(RE); + section_iterator TargetSI = getSectionByAddress(Obj, SymbolBaseAddr); + assert(TargetSI != Obj.section_end() && "Can't find section for symbol"); + uint64_t SectionBaseAddr = TargetSI->getAddress(); SectionRef TargetSection = *TargetSI; - bool IsCode; - TargetSection.isText(IsCode); + bool IsCode = TargetSection.isText(); uint32_t TargetSectionID = findOrEmitSection(Obj, TargetSection, IsCode, ObjSectionToID); @@ -223,7 +221,7 @@ private: } // Populate stubs in __jump_table section. - void populateJumpTable(MachOObjectFile &Obj, const SectionRef &JTSection, + void populateJumpTable(const MachOObjectFile &Obj, const SectionRef &JTSection, unsigned JTSectionID) { assert(!Obj.is64Bit() && "__jump_table section not supported in 64-bit MachO."); @@ -255,61 +253,9 @@ private: } } - // Populate __pointers section. - void populatePointersSection(MachOObjectFile &Obj, - const SectionRef &PTSection, - unsigned PTSectionID) { - assert(!Obj.is64Bit() && - "__pointers section not supported in 64-bit MachO."); - - MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); - MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); - uint32_t PTSectionSize = Sec32.size; - unsigned FirstIndirectSymbol = Sec32.reserved1; - const unsigned PTEntrySize = 4; - unsigned NumPTEntries = PTSectionSize / PTEntrySize; - unsigned PTEntryOffset = 0; - - assert((PTSectionSize % PTEntrySize) == 0 && - "Pointers section does not contain a whole number of stubs?"); - - DEBUG(dbgs() << "Populating __pointers, Section ID " << PTSectionID << ", " - << NumPTEntries << " entries, " << PTEntrySize - << " bytes each:\n"); - - for (unsigned i = 0; i < NumPTEntries; ++i) { - unsigned SymbolIndex = - Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); - symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); - StringRef IndirectSymbolName; - SI->getName(IndirectSymbolName); - DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex - << ", PT offset: " << PTEntryOffset << "\n"); - RelocationEntry RE(PTSectionID, PTEntryOffset, - MachO::GENERIC_RELOC_VANILLA, 0, false, 2); - addRelocationForSymbol(RE, IndirectSymbolName); - PTEntryOffset += PTEntrySize; - } - } - - static section_iterator getSectionByAddress(const MachOObjectFile &Obj, - uint64_t Addr) { - section_iterator SI = Obj.section_begin(); - section_iterator SE = Obj.section_end(); - - for (; SI != SE; ++SI) { - uint64_t SAddr, SSize; - SI->getAddress(SAddr); - SI->getSize(SSize); - if ((Addr >= SAddr) && (Addr < SAddr + SSize)) - return SI; - } - - return SE; - } }; } #undef DEBUG_TYPE -#endif // LLVM_RUNTIMEDYLDMACHOI386_H +#endif diff --git a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h index 99efe9d..0734017 100644 --- a/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h +++ b/lib/ExecutionEngine/RuntimeDyld/Targets/RuntimeDyldMachOX86_64.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_RUNTIMEDYLDMACHOX86_64_H -#define LLVM_RUNTIMEDYLDMACHOX86_64_H +#ifndef LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H +#define LLVM_LIB_EXECUTIONENGINE_RUNTIMEDYLD_TARGETS_RUNTIMEDYLDMACHOX86_64_H #include "../RuntimeDyldMachO.h" @@ -19,6 +19,9 @@ namespace llvm { class RuntimeDyldMachOX86_64 : public RuntimeDyldMachOCRTPBase { public: + + typedef uint64_t TargetPtrT; + RuntimeDyldMachOX86_64(RTDyldMemoryManager *MM) : RuntimeDyldMachOCRTPBase(MM) {} @@ -28,29 +31,31 @@ public: relocation_iterator processRelocationRef(unsigned SectionID, relocation_iterator RelI, - ObjectImage &ObjImg, ObjSectionToIDMap &ObjSectionToID, - const SymbolTableMap &Symbols, StubMap &Stubs) override { + const ObjectFile &BaseObjT, + ObjSectionToIDMap &ObjSectionToID, + StubMap &Stubs) override { const MachOObjectFile &Obj = - static_cast(*ObjImg.getObjectFile()); + static_cast(BaseObjT); MachO::any_relocation_info RelInfo = Obj.getRelocation(RelI->getRawDataRefImpl()); assert(!Obj.isRelocationScattered(RelInfo) && "Scattered relocations not supported on X86_64"); - RelocationEntry RE(getBasicRelocationEntry(SectionID, ObjImg, RelI)); + RelocationEntry RE(getRelocationEntry(SectionID, Obj, RelI)); + RE.Addend = memcpyAddend(RE); RelocationValueRef Value( - getRelocationValueRef(ObjImg, RelI, RE, ObjSectionToID, Symbols)); + getRelocationValueRef(Obj, RelI, RE, ObjSectionToID)); bool IsExtern = Obj.getPlainRelocationExternal(RelInfo); if (!IsExtern && RE.IsPCRel) - makeValueAddendPCRel(Value, ObjImg, RelI); + makeValueAddendPCRel(Value, Obj, RelI, 1 << RE.Size); if (RE.RelType == MachO::X86_64_RELOC_GOT || RE.RelType == MachO::X86_64_RELOC_GOT_LOAD) processGOTRelocation(RE, Value, Stubs); else { - RE.Addend = Value.Addend; + RE.Addend = Value.Offset; if (Value.SymbolName) addRelocationForSymbol(RE, Value.SymbolName); else @@ -60,7 +65,7 @@ public: return ++RelI; } - void resolveRelocation(const RelocationEntry &RE, uint64_t Value) { + void resolveRelocation(const RelocationEntry &RE, uint64_t Value) override { DEBUG(dumpRelocationToResolve(RE, Value)); const SectionEntry &Section = Sections[RE.SectionID]; uint8_t *LocalAddress = Section.Address + RE.Offset; @@ -83,7 +88,7 @@ public: case MachO::X86_64_RELOC_SIGNED: case MachO::X86_64_RELOC_UNSIGNED: case MachO::X86_64_RELOC_BRANCH: - writeBytesUnaligned(LocalAddress, Value + RE.Addend, 1 << RE.Size); + writeBytesUnaligned(Value + RE.Addend, LocalAddress, 1 << RE.Size); break; case MachO::X86_64_RELOC_GOT_LOAD: case MachO::X86_64_RELOC_GOT: @@ -93,7 +98,7 @@ public: } } - void finalizeSection(ObjectImage &ObjImg, unsigned SectionID, + void finalizeSection(const ObjectFile &Obj, unsigned SectionID, const SectionRef &Section) {} private: @@ -102,7 +107,7 @@ private: SectionEntry &Section = Sections[RE.SectionID]; assert(RE.IsPCRel); assert(RE.Size == 2); - Value.Addend -= RE.Addend; + Value.Offset -= RE.Addend; RuntimeDyldMachO::StubMap::const_iterator i = Stubs.find(Value); uint8_t *Addr; if (i != Stubs.end()) { @@ -111,7 +116,7 @@ private: Stubs[Value] = Section.StubOffset; uint8_t *GOTEntry = Section.Address + Section.StubOffset; RelocationEntry GOTRE(RE.SectionID, Section.StubOffset, - MachO::X86_64_RELOC_UNSIGNED, Value.Addend, false, + MachO::X86_64_RELOC_UNSIGNED, Value.Offset, false, 3); if (Value.SymbolName) addRelocationForSymbol(GOTRE, Value.SymbolName); @@ -129,4 +134,4 @@ private: #undef DEBUG_TYPE -#endif // LLVM_RUNTIMEDYLDMACHOX86_64_H +#endif diff --git a/lib/ExecutionEngine/TargetSelect.cpp b/lib/ExecutionEngine/TargetSelect.cpp index b10d51f..e6679cf 100644 --- a/lib/ExecutionEngine/TargetSelect.cpp +++ b/lib/ExecutionEngine/TargetSelect.cpp @@ -30,7 +30,7 @@ TargetMachine *EngineBuilder::selectTarget() { // MCJIT can generate code for remote targets, but the old JIT and Interpreter // must use the host architecture. - if (UseMCJIT && WhichEngine != EngineKind::Interpreter && M) + if (WhichEngine != EngineKind::Interpreter && M) TT.setTriple(M->getTargetTriple()); return selectTarget(TT, MArch, MCPU, MAttrs); @@ -89,8 +89,7 @@ TargetMachine *EngineBuilder::selectTarget(const Triple &TargetTriple, } // FIXME: non-iOS ARM FastISel is broken with MCJIT. - if (UseMCJIT && - TheTriple.getArch() == Triple::arm && + if (TheTriple.getArch() == Triple::arm && !TheTriple.isiOS() && OptLevel == CodeGenOpt::None) { OptLevel = CodeGenOpt::Less; diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index a7499bc..c494d6c 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -49,6 +49,218 @@ AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {} // Helper Functions //===----------------------------------------------------------------------===// +namespace { +struct OrderMap { + DenseMap> IDs; + + unsigned size() const { return IDs.size(); } + std::pair &operator[](const Value *V) { return IDs[V]; } + std::pair lookup(const Value *V) const { + return IDs.lookup(V); + } + void index(const Value *V) { + // Explicitly sequence get-size and insert-value operations to avoid UB. + unsigned ID = IDs.size() + 1; + IDs[V].first = ID; + } +}; +} + +static void orderValue(const Value *V, OrderMap &OM) { + if (OM.lookup(V).first) + return; + + if (const Constant *C = dyn_cast(V)) + if (C->getNumOperands() && !isa(C)) + for (const Value *Op : C->operands()) + if (!isa(Op) && !isa(Op)) + orderValue(Op, OM); + + // Note: we cannot cache this lookup above, since inserting into the map + // changes the map's size, and thus affects the other IDs. + OM.index(V); +} + +static OrderMap orderModule(const Module *M) { + // This needs to match the order used by ValueEnumerator::ValueEnumerator() + // and ValueEnumerator::incorporateFunction(). + OrderMap OM; + + for (const GlobalVariable &G : M->globals()) { + if (G.hasInitializer()) + if (!isa(G.getInitializer())) + orderValue(G.getInitializer(), OM); + orderValue(&G, OM); + } + for (const GlobalAlias &A : M->aliases()) { + if (!isa(A.getAliasee())) + orderValue(A.getAliasee(), OM); + orderValue(&A, OM); + } + for (const Function &F : *M) { + if (F.hasPrefixData()) + if (!isa(F.getPrefixData())) + orderValue(F.getPrefixData(), OM); + + if (F.hasPrologueData()) + if (!isa(F.getPrologueData())) + orderValue(F.getPrologueData(), OM); + + orderValue(&F, OM); + + if (F.isDeclaration()) + continue; + + for (const Argument &A : F.args()) + orderValue(&A, OM); + for (const BasicBlock &BB : F) { + orderValue(&BB, OM); + for (const Instruction &I : BB) { + for (const Value *Op : I.operands()) + if ((isa(*Op) && !isa(*Op)) || + isa(*Op)) + orderValue(Op, OM); + orderValue(&I, OM); + } + } + } + return OM; +} + +static void predictValueUseListOrderImpl(const Value *V, const Function *F, + unsigned ID, const OrderMap &OM, + UseListOrderStack &Stack) { + // Predict use-list order for this one. + typedef std::pair Entry; + SmallVector List; + for (const Use &U : V->uses()) + // Check if this user will be serialized. + if (OM.lookup(U.getUser()).first) + List.push_back(std::make_pair(&U, List.size())); + + if (List.size() < 2) + // We may have lost some users. + return; + + bool GetsReversed = + !isa(V) && !isa(V) && !isa(V); + if (auto *BA = dyn_cast(V)) + ID = OM.lookup(BA->getBasicBlock()).first; + std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) { + const Use *LU = L.first; + const Use *RU = R.first; + if (LU == RU) + return false; + + auto LID = OM.lookup(LU->getUser()).first; + auto RID = OM.lookup(RU->getUser()).first; + + // If ID is 4, then expect: 7 6 5 1 2 3. + if (LID < RID) { + if (GetsReversed) + if (RID <= ID) + return true; + return false; + } + if (RID < LID) { + if (GetsReversed) + if (LID <= ID) + return false; + return true; + } + + // LID and RID are equal, so we have different operands of the same user. + // Assume operands are added in order for all instructions. + if (GetsReversed) + if (LID <= ID) + return LU->getOperandNo() < RU->getOperandNo(); + return LU->getOperandNo() > RU->getOperandNo(); + }); + + if (std::is_sorted( + List.begin(), List.end(), + [](const Entry &L, const Entry &R) { return L.second < R.second; })) + // Order is already correct. + return; + + // Store the shuffle. + Stack.emplace_back(V, F, List.size()); + assert(List.size() == Stack.back().Shuffle.size() && "Wrong size"); + for (size_t I = 0, E = List.size(); I != E; ++I) + Stack.back().Shuffle[I] = List[I].second; +} + +static void predictValueUseListOrder(const Value *V, const Function *F, + OrderMap &OM, UseListOrderStack &Stack) { + auto &IDPair = OM[V]; + assert(IDPair.first && "Unmapped value"); + if (IDPair.second) + // Already predicted. + return; + + // Do the actual prediction. + IDPair.second = true; + if (!V->use_empty() && std::next(V->use_begin()) != V->use_end()) + predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack); + + // Recursive descent into constants. + if (const Constant *C = dyn_cast(V)) + if (C->getNumOperands()) // Visit GlobalValues. + for (const Value *Op : C->operands()) + if (isa(Op)) // Visit GlobalValues. + predictValueUseListOrder(Op, F, OM, Stack); +} + +static UseListOrderStack predictUseListOrder(const Module *M) { + OrderMap OM = orderModule(M); + + // Use-list orders need to be serialized after all the users have been added + // to a value, or else the shuffles will be incomplete. Store them per + // function in a stack. + // + // Aside from function order, the order of values doesn't matter much here. + UseListOrderStack Stack; + + // We want to visit the functions backward now so we can list function-local + // constants in the last Function they're used in. Module-level constants + // have already been visited above. + for (auto I = M->rbegin(), E = M->rend(); I != E; ++I) { + const Function &F = *I; + if (F.isDeclaration()) + continue; + for (const BasicBlock &BB : F) + predictValueUseListOrder(&BB, &F, OM, Stack); + for (const Argument &A : F.args()) + predictValueUseListOrder(&A, &F, OM, Stack); + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + for (const Value *Op : I.operands()) + if (isa(*Op) || isa(*Op)) // Visit GlobalValues. + predictValueUseListOrder(Op, &F, OM, Stack); + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + predictValueUseListOrder(&I, &F, OM, Stack); + } + + // Visit globals last. + for (const GlobalVariable &G : M->globals()) + predictValueUseListOrder(&G, nullptr, OM, Stack); + for (const Function &F : *M) + predictValueUseListOrder(&F, nullptr, OM, Stack); + for (const GlobalAlias &A : M->aliases()) + predictValueUseListOrder(&A, nullptr, OM, Stack); + for (const GlobalVariable &G : M->globals()) + if (G.hasInitializer()) + predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack); + for (const GlobalAlias &A : M->aliases()) + predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack); + for (const Function &F : *M) + if (F.hasPrefixData()) + predictValueUseListOrder(F.getPrefixData(), nullptr, OM, Stack); + + return Stack; +} + static const Module *getModuleFromVal(const Value *V) { if (const Argument *MA = dyn_cast(V)) return MA->getParent() ? MA->getParent()->getParent() : nullptr; @@ -75,9 +287,11 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) { case CallingConv::AnyReg: Out << "anyregcc"; break; case CallingConv::PreserveMost: Out << "preserve_mostcc"; break; case CallingConv::PreserveAll: Out << "preserve_allcc"; break; + case CallingConv::GHC: Out << "ghccc"; break; case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break; case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break; case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break; + case CallingConv::X86_VectorCall:Out << "x86_vectorcallcc"; break; case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break; case CallingConv::ARM_APCS: Out << "arm_apcscc"; break; case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break; @@ -347,6 +561,8 @@ public: FunctionProcessed = false; } + const Function *getFunction() const { return TheFunction; } + /// After calling incorporateFunction, use this method to remove the /// most recently incorporated function from the SlotTracker. This /// will reset the state of the machine back to just the module contents. @@ -418,13 +634,6 @@ static SlotTracker *createSlotTracker(const Value *V) { if (const Function *Func = dyn_cast(V)) return new SlotTracker(Func); - if (const MDNode *MD = dyn_cast(V)) { - if (!MD->isFunctionLocal()) - return new SlotTracker(MD->getFunction()); - - return new SlotTracker((Function *)nullptr); - } - return nullptr; } @@ -437,16 +646,14 @@ static SlotTracker *createSlotTracker(const Value *V) { // Module level constructor. Causes the contents of the Module (sans functions) // to be added to the slot table. SlotTracker::SlotTracker(const Module *M) - : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), - mNext(0), fNext(0), mdnNext(0), asNext(0) { -} + : TheModule(M), TheFunction(nullptr), FunctionProcessed(false), mNext(0), + fNext(0), mdnNext(0), asNext(0) {} // Function level constructor. Causes the contents of the Module and the one // function provided to be added to the slot table. SlotTracker::SlotTracker(const Function *F) - : TheModule(F ? F->getParent() : nullptr), TheFunction(F), - FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) { -} + : TheModule(F ? F->getParent() : nullptr), TheFunction(F), + FunctionProcessed(false), mNext(0), fNext(0), mdnNext(0), asNext(0) {} inline void SlotTracker::initialize() { if (TheModule) { @@ -508,7 +715,7 @@ void SlotTracker::processFunction() { ST_DEBUG("Inserting Instructions:\n"); - SmallVector, 4> MDForInst; + SmallVector, 4> MDForInst; // Add all of the basic blocks and instructions with no names. for (Function::const_iterator BB = TheFunction->begin(), @@ -528,8 +735,9 @@ void SlotTracker::processFunction() { if (Function *F = CI->getCalledFunction()) if (F->isIntrinsic()) for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) - if (MDNode *N = dyn_cast_or_null(I->getOperand(i))) - CreateMetadataSlot(N); + if (auto *V = dyn_cast_or_null(I->getOperand(i))) + if (MDNode *N = dyn_cast(V->getMetadata())) + CreateMetadataSlot(N); // Add all the call attributes to the table. AttributeSet Attrs = CI->getAttributes().getFnAttributes(); @@ -640,16 +848,10 @@ void SlotTracker::CreateFunctionSlot(const Value *V) { void SlotTracker::CreateMetadataSlot(const MDNode *N) { assert(N && "Can't insert a null Value into SlotTracker!"); - // Don't insert if N is a function-local metadata, these are always printed - // inline. - if (!N->isFunctionLocal()) { - mdn_iterator I = mdnMap.find(N); - if (I != mdnMap.end()) - return; - - unsigned DestSlot = mdnNext++; - mdnMap[N] = DestSlot; - } + unsigned DestSlot = mdnNext; + if (!mdnMap.insert(std::make_pair(N, DestSlot)).second) + return; + ++mdnNext; // Recursively add any MDNodes referenced by operands. for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) @@ -678,6 +880,11 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, SlotTracker *Machine, const Module *Context); +static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context, + bool FromValue = false); + static const char *getPredicateText(unsigned predicate) { const char * pred = "unknown"; switch (predicate) { @@ -1042,20 +1249,21 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV, Out << ""; } -static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, - TypePrinting *TypePrinter, - SlotTracker *Machine, - const Module *Context) { +static void writeMDTuple(raw_ostream &Out, const MDTuple *Node, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { Out << "!{"; for (unsigned mi = 0, me = Node->getNumOperands(); mi != me; ++mi) { - const Value *V = Node->getOperand(mi); - if (!V) + const Metadata *MD = Node->getOperand(mi); + if (!MD) Out << "null"; - else { + else if (auto *MDV = dyn_cast(MD)) { + Value *V = MDV->getValue(); TypePrinter->print(V->getType(), Out); Out << ' '; - WriteAsOperandInternal(Out, Node->getOperand(mi), - TypePrinter, Machine, Context); + WriteAsOperandInternal(Out, V, TypePrinter, Machine, Context); + } else { + WriteAsOperandInternal(Out, MD, TypePrinter, Machine, Context); } if (mi + 1 != me) Out << ", "; @@ -1064,6 +1272,60 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, Out << "}"; } +namespace { +struct FieldSeparator { + bool Skip; + FieldSeparator() : Skip(true) {} +}; +raw_ostream &operator<<(raw_ostream &OS, FieldSeparator &FS) { + if (FS.Skip) { + FS.Skip = false; + return OS; + } + return OS << ", "; +} +} // end namespace + +static void writeMDLocation(raw_ostream &Out, const MDLocation *DL, + TypePrinting *TypePrinter, SlotTracker *Machine, + const Module *Context) { + Out << "!MDLocation("; + FieldSeparator FS; + // Always output the line, since 0 is a relevant and important value for it. + Out << FS << "line: " << DL->getLine(); + if (DL->getColumn()) + Out << FS << "column: " << DL->getColumn(); + Out << FS << "scope: "; + WriteAsOperandInternal(Out, DL->getScope(), TypePrinter, Machine, Context); + if (DL->getInlinedAt()) { + Out << FS << "inlinedAt: "; + WriteAsOperandInternal(Out, DL->getInlinedAt(), TypePrinter, Machine, + Context); + } + Out << ")"; +} + +static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node, + TypePrinting *TypePrinter, + SlotTracker *Machine, + const Module *Context) { + assert(isa(Node) && "Expected uniquable MDNode"); + + auto *Uniquable = cast(Node); + if (Uniquable->isDistinct()) + Out << "distinct "; + + switch (Uniquable->getMetadataID()) { + default: + llvm_unreachable("Expected uniquable MDNode"); +#define HANDLE_UNIQUABLE_LEAF(CLASS) \ + case Metadata::CLASS##Kind: \ + write##CLASS(Out, cast(Uniquable), TypePrinter, Machine, Context); \ + break; +#include "llvm/IR/Metadata.def" + } +} + // Full implementation of printing a Value as an operand with support for // TypePrinting, etc. static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, @@ -1099,31 +1361,9 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, return; } - if (const MDNode *N = dyn_cast(V)) { - if (N->isFunctionLocal()) { - // Print metadata inline, not via slot reference number. - WriteMDNodeBodyInternal(Out, N, TypePrinter, Machine, Context); - return; - } - - if (!Machine) { - if (N->isFunctionLocal()) - Machine = new SlotTracker(N->getFunction()); - else - Machine = new SlotTracker(Context); - } - int Slot = Machine->getMetadataSlot(N); - if (Slot == -1) - Out << ""; - else - Out << '!' << Slot; - return; - } - - if (const MDString *MDS = dyn_cast(V)) { - Out << "!\""; - PrintEscapedString(MDS->getString(), Out); - Out << '"'; + if (auto *MD = dyn_cast(V)) { + WriteAsOperandInternal(Out, MD->getMetadata(), TypePrinter, Machine, + Context, /* FromValue */ true); return; } @@ -1166,6 +1406,40 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V, Out << ""; } +static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD, + TypePrinting *TypePrinter, + SlotTracker *Machine, const Module *Context, + bool FromValue) { + if (const MDNode *N = dyn_cast(MD)) { + if (!Machine) + Machine = new SlotTracker(Context); + int Slot = Machine->getMetadataSlot(N); + if (Slot == -1) + // Give the pointer value instead of "badref", since this comes up all + // the time when debugging. + Out << "<" << N << ">"; + else + Out << '!' << Slot; + return; + } + + if (const MDString *MDS = dyn_cast(MD)) { + Out << "!\""; + PrintEscapedString(MDS->getString(), Out); + Out << '"'; + return; + } + + auto *V = cast(MD); + assert(TypePrinter && "TypePrinter required for metadata values"); + assert((FromValue || !isa(V)) && + "Unexpected function-local metadata outside of value argument"); + + TypePrinter->print(V->getValue()->getType(), Out); + Out << ' '; + WriteAsOperandInternal(Out, V->getValue(), TypePrinter, Machine, Context); +} + void AssemblyWriter::init() { if (!TheModule) return; @@ -1279,6 +1553,9 @@ void AssemblyWriter::writeParamOperand(const Value *Operand, void AssemblyWriter::printModule(const Module *M) { Machine.initialize(); + if (shouldPreserveAssemblyUseListOrder()) + UseListOrders = predictUseListOrder(M); + if (!M->getModuleIdentifier().empty() && // Don't print the ID if it will start a new line (which would // require a comment char before it). @@ -1339,9 +1616,13 @@ void AssemblyWriter::printModule(const Module *M) { I != E; ++I) printAlias(I); + // Output global use-lists. + printUseLists(nullptr); + // Output all of the functions. for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I) printFunction(I); + assert(UseListOrders.empty() && "All use-lists should have been consumed"); // Output all attribute groups. if (!Machine.as_empty()) { @@ -1455,6 +1736,24 @@ static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM, } } +static void maybePrintComdat(formatted_raw_ostream &Out, + const GlobalObject &GO) { + const Comdat *C = GO.getComdat(); + if (!C) + return; + + if (isa(GO)) + Out << ','; + Out << " comdat"; + + if (GO.getName() == C->getName()) + return; + + Out << '('; + PrintLLVMName(Out, C->getName(), ComdatPrefix); + Out << ')'; +} + void AssemblyWriter::printGlobal(const GlobalVariable *GV) { if (GV->isMaterializable()) Out << "; Materializable\n"; @@ -1488,10 +1787,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) { PrintEscapedString(GV->getSection(), Out); Out << '"'; } - if (GV->hasComdat()) { - Out << ", comdat "; - PrintLLVMName(Out, GV->getComdat()->getName(), ComdatPrefix); - } + maybePrintComdat(Out, *GV); if (GV->getAlignment()) Out << ", align " << GV->getAlignment(); @@ -1509,6 +1805,7 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { PrintLLVMName(Out, GA); Out << " = "; } + PrintLinkage(GA->getLinkage(), Out); PrintVisibility(GA->getVisibility(), Out); PrintDLLStorageClass(GA->getDLLStorageClass(), Out); PrintThreadLocalModel(GA->getThreadLocalMode(), Out); @@ -1517,8 +1814,6 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) { Out << "alias "; - PrintLinkage(GA->getLinkage(), Out); - const Constant *Aliasee = GA->getAliasee(); if (!Aliasee) { @@ -1673,10 +1968,7 @@ void AssemblyWriter::printFunction(const Function *F) { PrintEscapedString(F->getSection(), Out); Out << '"'; } - if (F->hasComdat()) { - Out << " comdat "; - PrintLLVMName(Out, F->getComdat()->getName(), ComdatPrefix); - } + maybePrintComdat(Out, *F); if (F->getAlignment()) Out << " align " << F->getAlignment(); if (F->hasGC()) @@ -1685,6 +1977,11 @@ void AssemblyWriter::printFunction(const Function *F) { Out << " prefix "; writeOperand(F->getPrefixData(), true); } + if (F->hasPrologueData()) { + Out << " prologue "; + writeOperand(F->getPrologueData(), true); + } + if (F->isDeclaration()) { Out << '\n'; } else { @@ -1693,6 +1990,9 @@ void AssemblyWriter::printFunction(const Function *F) { for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I) printBasicBlock(I); + // Output the function's use-lists. + printUseLists(F); + Out << "}\n"; } @@ -1956,6 +2256,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) { Out << ", "; writeParamOperand(CI->getArgOperand(op), PAL, op + 1); } + + // Emit an ellipsis if this is a musttail call in a vararg function. This + // is only to aid readability, musttail calls forward varargs by default. + if (CI->isMustTailCall() && CI->getParent() && + CI->getParent()->getParent() && + CI->getParent()->getParent()->isVarArg()) + Out << ", ..."; + Out << ')'; if (PAL.hasAttributes(AttributeSet::FunctionIndex)) Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes()); @@ -2088,7 +2396,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) { } // Print Metadata info. - SmallVector, 4> InstMD; + SmallVector, 4> InstMD; I.getAllMetadata(InstMD); if (!InstMD.empty()) { SmallVector MDNames; @@ -2113,8 +2421,8 @@ static void WriteMDNodeComment(const MDNode *Node, if (Node->getNumOperands() < 1) return; - Value *Op = Node->getOperand(0); - if (!Op || !isa(Op) || cast(Op)->getBitWidth() < 32) + Metadata *Op = Node->getOperand(0); + if (!Op || !isa(Op)) return; DIDescriptor Desc(Node); @@ -2132,7 +2440,7 @@ static void WriteMDNodeComment(const MDNode *Node, } void AssemblyWriter::writeMDNode(unsigned Slot, const MDNode *Node) { - Out << '!' << Slot << " = metadata "; + Out << '!' << Slot << " = "; printMDNodeBody(Node); } @@ -2170,6 +2478,45 @@ void AssemblyWriter::writeAllAttributeGroups() { } // namespace llvm +void AssemblyWriter::printUseListOrder(const UseListOrder &Order) { + bool IsInFunction = Machine.getFunction(); + if (IsInFunction) + Out << " "; + + Out << "uselistorder"; + if (const BasicBlock *BB = + IsInFunction ? nullptr : dyn_cast(Order.V)) { + Out << "_bb "; + writeOperand(BB->getParent(), false); + Out << ", "; + writeOperand(BB, false); + } else { + Out << " "; + writeOperand(Order.V, true); + } + Out << ", { "; + + assert(Order.Shuffle.size() >= 2 && "Shuffle too small"); + Out << Order.Shuffle[0]; + for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I) + Out << ", " << Order.Shuffle[I]; + Out << " }\n"; +} + +void AssemblyWriter::printUseLists(const Function *F) { + auto hasMore = + [&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; }; + if (!hasMore()) + // Nothing to do. + return; + + Out << "\n; uselistorder directives\n"; + while (hasMore()) { + printUseListOrder(UseListOrders.back()); + UseListOrders.pop_back(); + } +} + //===----------------------------------------------------------------------===// // External Interface declarations //===----------------------------------------------------------------------===// @@ -2245,18 +2592,14 @@ void Value::print(raw_ostream &ROS) const { W.printFunction(F); else W.printAlias(cast(GV)); - } else if (const MDNode *N = dyn_cast(this)) { - const Function *F = N->getFunction(); - SlotTracker SlotTable(F); - AssemblyWriter W(OS, SlotTable, F ? F->getParent() : nullptr, nullptr); - W.printMDNodeBody(N); + } else if (const MetadataAsValue *V = dyn_cast(this)) { + V->getMetadata()->print(ROS); } else if (const Constant *C = dyn_cast(this)) { TypePrinting TypePrinter; TypePrinter.print(C->getType(), OS); OS << ' '; WriteConstantInternal(OS, C, TypePrinter, nullptr, nullptr); - } else if (isa(this) || isa(this) || - isa(this)) { + } else if (isa(this) || isa(this)) { this->printAsOperand(OS); } else { llvm_unreachable("Unknown value to print out!"); @@ -2266,9 +2609,8 @@ void Value::print(raw_ostream &ROS) const { void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const { // Fast path: Don't construct and populate a TypePrinting object if we // won't be needing any types printed. - if (!PrintType && - ((!isa(this) && !isa(this)) || - hasName() || isa(this))) { + if (!PrintType && ((!isa(this) && !isa(this)) || + hasName() || isa(this))) { WriteAsOperandInternal(O, this, nullptr, nullptr, M); return; } @@ -2287,11 +2629,37 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) cons WriteAsOperandInternal(O, this, &TypePrinter, nullptr, M); } +void Metadata::print(raw_ostream &ROS) const { + formatted_raw_ostream OS(ROS); + if (auto *N = dyn_cast(this)) { + SlotTracker SlotTable(static_cast(nullptr)); + AssemblyWriter W(OS, SlotTable, nullptr, nullptr); + W.printMDNodeBody(N); + + return; + } + printAsOperand(OS); +} + +void Metadata::printAsOperand(raw_ostream &ROS, bool PrintType, + const Module *M) const { + formatted_raw_ostream OS(ROS); + + std::unique_ptr TypePrinter; + if (PrintType) { + TypePrinter.reset(new TypePrinting); + if (M) + TypePrinter->incorporateTypes(*M); + } + WriteAsOperandInternal(OS, this, TypePrinter.get(), nullptr, M, + /* FromValue */ true); +} + // Value::dump - allow easy printing of Values from the debugger. void Value::dump() const { print(dbgs()); dbgs() << '\n'; } // Type::dump - allow easy printing of Types from the debugger. -void Type::dump() const { print(dbgs()); } +void Type::dump() const { print(dbgs()); dbgs() << '\n'; } // Module::dump() - Allow printing of Modules from the debugger. void Module::dump() const { print(dbgs(), nullptr); } @@ -2301,3 +2669,8 @@ void Comdat::dump() const { print(dbgs()); } // NamedMDNode::dump() - Allow printing of NamedMDNodes from the debugger. void NamedMDNode::dump() const { print(dbgs()); } + +void Metadata::dump() const { + print(dbgs()); + dbgs() << '\n'; +} diff --git a/lib/IR/AsmWriter.h b/lib/IR/AsmWriter.h index aef9c8a..60da5ad 100644 --- a/lib/IR/AsmWriter.h +++ b/lib/IR/AsmWriter.h @@ -12,14 +12,15 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_ASSEMBLYWRITER_H -#define LLVM_IR_ASSEMBLYWRITER_H +#ifndef LLVM_LIB_IR_ASMWRITER_H +#define LLVM_LIB_IR_ASMWRITER_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/TypeFinder.h" +#include "llvm/IR/UseListOrder.h" #include "llvm/Support/FormattedStream.h" namespace llvm { @@ -73,6 +74,7 @@ private: TypePrinting TypePrinter; AssemblyAnnotationWriter *AnnotationWriter; SetVector Comdats; + UseListOrderStack UseListOrders; public: /// Construct an AssemblyWriter with an external SlotTracker @@ -111,6 +113,9 @@ public: void printInstructionLine(const Instruction &I); void printInstruction(const Instruction &I); + void printUseListOrder(const UseListOrder &Order); + void printUseLists(const Function *F); + private: void init(); @@ -121,4 +126,4 @@ private: } // namespace llvm -#endif //LLVM_IR_ASMWRITER_H +#endif diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index cc6d557..0448dc17 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_ATTRIBUTESIMPL_H -#define LLVM_ATTRIBUTESIMPL_H +#ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H +#define LLVM_LIB_IR_ATTRIBUTEIMPL_H #include "llvm/ADT/FoldingSet.h" #include "llvm/IR/Attributes.h" diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp index 459bd88..e3544df 100644 --- a/lib/IR/AutoUpgrade.cpp +++ b/lib/IR/AutoUpgrade.cpp @@ -15,6 +15,7 @@ #include "llvm/IR/CFG.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/Function.h" @@ -43,6 +44,22 @@ static bool UpgradeSSE41Function(Function* F, Intrinsic::ID IID, return true; } +// Upgrade the declarations of intrinsic functions whose 8-bit immediate mask +// arguments have changed their type from i32 to i8. +static bool UpgradeX86IntrinsicsWith8BitMask(Function *F, Intrinsic::ID IID, + Function *&NewFn) { + // Check that the last argument is an i32. + Type *LastArgType = F->getFunctionType()->getParamType( + F->getFunctionType()->getNumParams() - 1); + if (!LastArgType->isIntegerTy(32)) + return false; + + // Move this function aside and map down. + F->setName(F->getName() + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), IID); + return true; +} + static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { assert(F && "Illegal to upgrade a non-existent Function."); @@ -90,6 +107,20 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { } break; } + case 'd': { + if (Name.startswith("dbg.declare") && F->arg_size() == 2) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_declare); + return true; + } + if (Name.startswith("dbg.value") && F->arg_size() == 3) { + F->setName(Name + ".old"); + NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value); + return true; + } + break; + } + case 'o': // We only need to change the name to match the mangling including the // address space. @@ -130,6 +161,51 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) { if (Name == "x86.sse41.ptestnzc") return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestnzc, NewFn); } + // Several blend and other instructions with maskes used the wrong number of + // bits. + if (Name == "x86.sse41.pblendw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_pblendw, + NewFn); + if (Name == "x86.sse41.blendpd") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendpd, + NewFn); + if (Name == "x86.sse41.blendps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendps, + NewFn); + if (Name == "x86.sse41.insertps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_insertps, + NewFn); + if (Name == "x86.sse41.dppd") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dppd, + NewFn); + if (Name == "x86.sse41.dpps") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dpps, + NewFn); + if (Name == "x86.sse41.mpsadbw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_mpsadbw, + NewFn); + if (Name == "x86.avx.blend.pd.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx_blend_pd_256, NewFn); + if (Name == "x86.avx.blend.ps.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx_blend_ps_256, NewFn); + if (Name == "x86.avx.dp.ps.256") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx_dp_ps_256, + NewFn); + if (Name == "x86.avx2.pblendw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_pblendw, + NewFn); + if (Name == "x86.avx2.pblendd.128") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx2_pblendd_128, NewFn); + if (Name == "x86.avx2.pblendd.256") + return UpgradeX86IntrinsicsWith8BitMask( + F, Intrinsic::x86_avx2_pblendd_256, NewFn); + if (Name == "x86.avx2.mpsadbw") + return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_mpsadbw, + NewFn); + // frcz.ss/sd may need to have an argument dropped if (Name.startswith("x86.xop.vfrcz.ss") && F->arg_size() == 2) { F->setName(Name + ".old"); @@ -173,66 +249,28 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) { return Upgraded; } -static bool UpgradeGlobalStructors(GlobalVariable *GV) { - ArrayType *ATy = dyn_cast(GV->getType()->getElementType()); - StructType *OldTy = - ATy ? dyn_cast(ATy->getElementType()) : nullptr; - - // Only upgrade an array of a two field struct with the appropriate field - // types. - if (!OldTy || OldTy->getNumElements() != 2) - return false; - - // Get the upgraded 3 element type. - PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo(); - Type *Tys[3] = { - OldTy->getElementType(0), - OldTy->getElementType(1), - VoidPtrTy - }; - StructType *NewTy = - StructType::get(GV->getContext(), Tys, /*isPacked=*/false); - - // Build new constants with a null third field filled in. - Constant *OldInitC = GV->getInitializer(); - ConstantArray *OldInit = dyn_cast(OldInitC); - if (!OldInit && !isa(OldInitC)) - return false; - std::vector Initializers; - if (OldInit) { - for (Use &U : OldInit->operands()) { - ConstantStruct *Init = cast(&U); - Constant *NewInit = - ConstantStruct::get(NewTy, Init->getOperand(0), Init->getOperand(1), - Constant::getNullValue(VoidPtrTy), nullptr); - Initializers.push_back(NewInit); - } - } - assert(Initializers.size() == ATy->getNumElements()); - - // Replace the old GV with a new one. - ATy = ArrayType::get(NewTy, Initializers.size()); - Constant *NewInit = ConstantArray::get(ATy, Initializers); - GlobalVariable *NewGV = new GlobalVariable( - *GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "", - GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(), - GV->isExternallyInitialized()); - NewGV->copyAttributesFrom(GV); - NewGV->takeName(GV); - assert(GV->use_empty() && "program cannot use initializer list"); - GV->eraseFromParent(); - return true; -} - bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) { - if (GV->getName() == "llvm.global_ctors" || - GV->getName() == "llvm.global_dtors") - return UpgradeGlobalStructors(GV); - // Nothing to do yet. return false; } +static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) { + if (!DbgNode || Elt >= DbgNode->getNumOperands()) + return nullptr; + return dyn_cast_or_null(DbgNode->getOperand(Elt)); +} + +static MetadataAsValue *getExpression(Value *VarOperand, Function *F) { + // Old-style DIVariables have an optional expression as the 8th element. + DIExpression Expr(getNodeField( + cast(cast(VarOperand)->getMetadata()), 8)); + if (!Expr) { + DIBuilder DIB(*F->getParent(), /*AllowUnresolved*/ false); + Expr = DIB.createExpression(); + } + return MetadataAsValue::get(F->getContext(), Expr); +} + // UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the // upgraded intrinsic. All argument and return casting must be provided in // order to seamlessly integrate with existing context. @@ -269,8 +307,9 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { Builder.SetInsertPoint(CI->getParent(), CI); Module *M = F->getParent(); - SmallVector Elts; - Elts.push_back(ConstantInt::get(Type::getInt32Ty(C), 1)); + SmallVector Elts; + Elts.push_back( + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(C), 1))); MDNode *Node = MDNode::get(C, Elts); Value *Arg0 = CI->getArgOperand(0); @@ -396,12 +435,32 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { } std::string Name = CI->getName().str(); - CI->setName(Name + ".old"); + if (!Name.empty()) + CI->setName(Name + ".old"); switch (NewFn->getIntrinsicID()) { default: llvm_unreachable("Unknown function for CallInst upgrade."); + // Upgrade debug intrinsics to use an additional DIExpression argument. + case Intrinsic::dbg_declare: { + auto NewCI = + Builder.CreateCall3(NewFn, CI->getArgOperand(0), CI->getArgOperand(1), + getExpression(CI->getArgOperand(1), F), Name); + NewCI->setDebugLoc(CI->getDebugLoc()); + CI->replaceAllUsesWith(NewCI); + CI->eraseFromParent(); + return; + } + case Intrinsic::dbg_value: { + auto NewCI = Builder.CreateCall4( + NewFn, CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2), + getExpression(CI->getArgOperand(2), F), Name); + NewCI->setDebugLoc(CI->getDebugLoc()); + CI->replaceAllUsesWith(NewCI); + CI->eraseFromParent(); + return; + } case Intrinsic::ctlz: case Intrinsic::cttz: assert(CI->getNumArgOperands() == 1 && @@ -419,14 +478,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->eraseFromParent(); return; - case Intrinsic::arm_neon_vclz: { - // Change name from llvm.arm.neon.vclz.* to llvm.ctlz.* - CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0), - Builder.getFalse(), - "llvm.ctlz." + Name.substr(14))); - CI->eraseFromParent(); - return; - } case Intrinsic::ctpop: { CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(0))); CI->eraseFromParent(); @@ -468,6 +519,34 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) { CI->eraseFromParent(); return; } + + case Intrinsic::x86_sse41_pblendw: + case Intrinsic::x86_sse41_blendpd: + case Intrinsic::x86_sse41_blendps: + case Intrinsic::x86_sse41_insertps: + case Intrinsic::x86_sse41_dppd: + case Intrinsic::x86_sse41_dpps: + case Intrinsic::x86_sse41_mpsadbw: + case Intrinsic::x86_avx_blend_pd_256: + case Intrinsic::x86_avx_blend_ps_256: + case Intrinsic::x86_avx_dp_ps_256: + case Intrinsic::x86_avx2_pblendw: + case Intrinsic::x86_avx2_pblendd_128: + case Intrinsic::x86_avx2_pblendd_256: + case Intrinsic::x86_avx2_mpsadbw: { + // Need to truncate the last argument from i32 to i8 -- this argument models + // an inherently 8-bit immediate operand to these x86 instructions. + SmallVector Args(CI->arg_operands().begin(), + CI->arg_operands().end()); + + // Replace the last argument with a trunc. + Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc"); + + CallInst *NewCall = Builder.CreateCall(NewFn, Args); + CI->replaceAllUsesWith(NewCall); + CI->eraseFromParent(); + return; + } } } @@ -501,22 +580,18 @@ void llvm::UpgradeInstWithTBAATag(Instruction *I) { return; if (MD->getNumOperands() == 3) { - Value *Elts[] = { - MD->getOperand(0), - MD->getOperand(1) - }; + Metadata *Elts[] = {MD->getOperand(0), MD->getOperand(1)}; MDNode *ScalarType = MDNode::get(I->getContext(), Elts); // Create a MDNode - Value *Elts2[] = { - ScalarType, ScalarType, - Constant::getNullValue(Type::getInt64Ty(I->getContext())), - MD->getOperand(2) - }; + Metadata *Elts2[] = {ScalarType, ScalarType, + ConstantAsMetadata::get(Constant::getNullValue( + Type::getInt64Ty(I->getContext()))), + MD->getOperand(2)}; I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts2)); } else { // Create a MDNode - Value *Elts[] = {MD, MD, - Constant::getNullValue(Type::getInt64Ty(I->getContext()))}; + Metadata *Elts[] = {MD, MD, ConstantAsMetadata::get(Constant::getNullValue( + Type::getInt64Ty(I->getContext())))}; I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts)); } } diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp index ba07433..98a3062 100644 --- a/lib/IR/BasicBlock.cpp +++ b/lib/IR/BasicBlock.cpp @@ -19,7 +19,6 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Type.h" #include using namespace llvm; @@ -47,20 +46,24 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent, BasicBlock *InsertBefore) : Value(Type::getLabelTy(C), Value::BasicBlockVal), Parent(nullptr) { - // Make sure that we get added to a function - LeakDetector::addGarbageObject(this); - - if (InsertBefore) { - assert(NewParent && + if (NewParent) + insertInto(NewParent, InsertBefore); + else + assert(!InsertBefore && "Cannot insert block before another block with no function!"); - NewParent->getBasicBlockList().insert(InsertBefore, this); - } else if (NewParent) { - NewParent->getBasicBlockList().push_back(this); - } setName(Name); } +void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) { + assert(NewParent && "Expected a parent"); + assert(!Parent && "Already has a parent"); + + if (InsertBefore) + NewParent->getBasicBlockList().insert(InsertBefore, this); + else + NewParent->getBasicBlockList().push_back(this); +} BasicBlock::~BasicBlock() { // If the address of the block is taken and it is being deleted (e.g. because @@ -87,14 +90,8 @@ BasicBlock::~BasicBlock() { } void BasicBlock::setParent(Function *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); - // Set Parent=parent, updating instruction symtab entries as appropriate. InstList.setSymTabObject(&Parent, parent); - - if (getParent()) - LeakDetector::removeGarbageObject(this); } void BasicBlock::removeFromParent() { @@ -131,6 +128,37 @@ const TerminatorInst *BasicBlock::getTerminator() const { return dyn_cast(&InstList.back()); } +CallInst *BasicBlock::getTerminatingMustTailCall() { + if (InstList.empty()) + return nullptr; + ReturnInst *RI = dyn_cast(&InstList.back()); + if (!RI || RI == &InstList.front()) + return nullptr; + + Instruction *Prev = RI->getPrevNode(); + if (!Prev) + return nullptr; + + if (Value *RV = RI->getReturnValue()) { + if (RV != Prev) + return nullptr; + + // Look through the optional bitcast. + if (auto *BI = dyn_cast(Prev)) { + RV = BI->getOperand(0); + Prev = BI->getPrevNode(); + if (!Prev || RV != Prev) + return nullptr; + } + } + + if (auto *CI = dyn_cast(Prev)) { + if (CI->isMustTailCall()) + return CI; + } + return nullptr; +} + Instruction* BasicBlock::getFirstNonPHI() { BasicBlock::iterator i = begin(); // All valid basic blocks should have a terminator, diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt index 38a80b1..1a210e0 100644 --- a/lib/IR/CMakeLists.txt +++ b/lib/IR/CMakeLists.txt @@ -27,18 +27,20 @@ add_llvm_library(LLVMCore IntrinsicInst.cpp LLVMContext.cpp LLVMContextImpl.cpp - LeakDetector.cpp LegacyPassManager.cpp MDBuilder.cpp Mangler.cpp Metadata.cpp + MetadataTracking.cpp Module.cpp Pass.cpp PassManager.cpp PassRegistry.cpp + Statepoint.cpp Type.cpp TypeFinder.cpp Use.cpp + UseListOrder.cpp User.cpp Value.cpp ValueSymbolTable.cpp diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index 395ac39..9176bf2 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -27,12 +27,14 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MathExtras.h" #include using namespace llvm; +using namespace llvm::PatternMatch; //===----------------------------------------------------------------------===// // ConstantFold*Instruction Implementations @@ -593,8 +595,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, bool ignored; uint64_t x[2]; uint32_t DestBitWidth = cast(DestTy)->getBitWidth(); - (void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, - APFloat::rmTowardZero, &ignored); + if (APFloat::opInvalidOp == + V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI, + APFloat::rmTowardZero, &ignored)) { + // Undefined behavior invoked - the destination type can't represent + // the input constant. + return UndefValue::get(DestTy); + } APInt Val(DestBitWidth, x); return ConstantInt::get(FPC->getContext(), Val); } @@ -653,9 +660,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, APInt api = CI->getValue(); APFloat apf(DestTy->getFltSemantics(), APInt::getNullValue(DestTy->getPrimitiveSizeInBits())); - (void)apf.convertFromAPInt(api, - opc==Instruction::SIToFP, - APFloat::rmNearestTiesToEven); + if (APFloat::opOverflow & + apf.convertFromAPInt(api, opc==Instruction::SIToFP, + APFloat::rmNearestTiesToEven)) { + // Undefined behavior invoked - the destination type can't represent + // the input constant. + return UndefValue::get(DestTy); + } return ConstantFP::get(V->getContext(), apf); } return nullptr; @@ -674,6 +685,9 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V, } return nullptr; case Instruction::Trunc: { + if (V->getType()->isVectorTy()) + return nullptr; + uint32_t DestBitWidth = cast(DestTy)->getBitWidth(); if (ConstantInt *CI = dyn_cast(V)) { return ConstantInt::get(V->getContext(), @@ -901,49 +915,70 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, return C1; return Constant::getNullValue(C1->getType()); // undef & X -> 0 case Instruction::Mul: { - ConstantInt *CI; - // X * undef -> undef if X is odd or undef - if (((CI = dyn_cast(C1)) && CI->getValue()[0]) || - ((CI = dyn_cast(C2)) && CI->getValue()[0]) || - (isa(C1) && isa(C2))) - return UndefValue::get(C1->getType()); + // undef * undef -> undef + if (isa(C1) && isa(C2)) + return C1; + const APInt *CV; + // X * undef -> undef if X is odd + if (match(C1, m_APInt(CV)) || match(C2, m_APInt(CV))) + if ((*CV)[0]) + return UndefValue::get(C1->getType()); // X * undef -> 0 otherwise return Constant::getNullValue(C1->getType()); } - case Instruction::UDiv: case Instruction::SDiv: + case Instruction::UDiv: + // X / undef -> undef + if (match(C1, m_Zero())) + return C2; + // undef / 0 -> undef // undef / 1 -> undef - if (Opcode == Instruction::UDiv || Opcode == Instruction::SDiv) - if (ConstantInt *CI2 = dyn_cast(C2)) - if (CI2->isOne()) - return C1; - // FALL THROUGH + if (match(C2, m_Zero()) || match(C2, m_One())) + return C1; + // undef / X -> 0 otherwise + return Constant::getNullValue(C1->getType()); case Instruction::URem: case Instruction::SRem: - if (!isa(C2)) // undef / X -> 0 - return Constant::getNullValue(C1->getType()); - return C2; // X / undef -> undef + // X % undef -> undef + if (match(C2, m_Undef())) + return C2; + // undef % 0 -> undef + if (match(C2, m_Zero())) + return C1; + // undef % X -> 0 otherwise + return Constant::getNullValue(C1->getType()); case Instruction::Or: // X | undef -> -1 if (isa(C1) && isa(C2)) // undef | undef -> undef return C1; return Constant::getAllOnesValue(C1->getType()); // undef | X -> ~0 case Instruction::LShr: - if (isa(C2) && isa(C1)) - return C1; // undef lshr undef -> undef - return Constant::getNullValue(C1->getType()); // X lshr undef -> 0 - // undef lshr X -> 0 + // X >>l undef -> undef + if (isa(C2)) + return C2; + // undef >>l 0 -> undef + if (match(C2, m_Zero())) + return C1; + // undef >>l X -> 0 + return Constant::getNullValue(C1->getType()); case Instruction::AShr: - if (!isa(C2)) // undef ashr X --> all ones - return Constant::getAllOnesValue(C1->getType()); - else if (isa(C1)) - return C1; // undef ashr undef -> undef - else - return C1; // X ashr undef --> X + // X >>a undef -> undef + if (isa(C2)) + return C2; + // undef >>a 0 -> undef + if (match(C2, m_Zero())) + return C1; + // TODO: undef >>a X -> undef if the shift is exact + // undef >>a X -> 0 + return Constant::getNullValue(C1->getType()); case Instruction::Shl: - if (isa(C2) && isa(C1)) - return C1; // undef shl undef -> undef - // undef << X -> 0 or X << undef -> 0 + // X << undef -> undef + if (isa(C2)) + return C2; + // undef << 0 -> undef + if (match(C2, m_Zero())) + return C1; + // undef << X -> 0 return Constant::getNullValue(C1->getType()); } } @@ -1336,9 +1371,24 @@ static FCmpInst::Predicate evaluateFCmpRelation(Constant *V1, Constant *V2) { static ICmpInst::Predicate areGlobalsPotentiallyEqual(const GlobalValue *GV1, const GlobalValue *GV2) { + auto isGlobalUnsafeForEquality = [](const GlobalValue *GV) { + if (GV->hasExternalWeakLinkage() || GV->hasWeakAnyLinkage()) + return true; + if (const auto *GVar = dyn_cast(GV)) { + Type *Ty = GVar->getType()->getPointerElementType(); + // A global with opaque type might end up being zero sized. + if (!Ty->isSized()) + return true; + // A global with an empty type might lie at the address of any other + // global. + if (Ty->isEmptyTy()) + return true; + } + return false; + }; // Don't try to decide equality of aliases. if (!isa(GV1) && !isa(GV2)) - if (!GV1->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) + if (!isGlobalUnsafeForEquality(GV1) && !isGlobalUnsafeForEquality(GV2)) return ICmpInst::ICMP_NE; return ICmpInst::BAD_ICMP_PREDICATE; } @@ -2144,9 +2194,10 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C, // If all indices are known integers and normalized, we can do a simple // check for the "inbounds" property. - if (!Unknown && !inBounds && - isa(C) && isInBoundsIndices(Idxs)) - return ConstantExpr::getInBoundsGetElementPtr(C, Idxs); + if (!Unknown && !inBounds) + if (auto *GV = dyn_cast(C)) + if (!GV->hasExternalWeakLinkage() && isInBoundsIndices(Idxs)) + return ConstantExpr::getInBoundsGetElementPtr(C, Idxs); return nullptr; } diff --git a/lib/IR/ConstantFold.h b/lib/IR/ConstantFold.h index e12f27a..a516abe 100644 --- a/lib/IR/ConstantFold.h +++ b/lib/IR/ConstantFold.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CONSTANTFOLDING_H -#define CONSTANTFOLDING_H +#ifndef LLVM_LIB_IR_CONSTANTFOLD_H +#define LLVM_LIB_IR_CONSTANTFOLD_H #include "llvm/ADT/ArrayRef.h" diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index b815936a..1d2602a 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -107,6 +107,28 @@ bool Constant::isAllOnesValue() const { return false; } +bool Constant::isOneValue() const { + // Check for 1 integers + if (const ConstantInt *CI = dyn_cast(this)) + return CI->isOne(); + + // Check for FP which are bitcasted from 1 integers + if (const ConstantFP *CFP = dyn_cast(this)) + return CFP->getValueAPF().bitcastToAPInt() == 1; + + // Check for constant vectors which are splats of 1 values. + if (const ConstantVector *CV = dyn_cast(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isOneValue(); + + // Check for constant vectors which are splats of 1 values. + if (const ConstantDataVector *CV = dyn_cast(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isOneValue(); + + return false; +} + bool Constant::isMinSignedValue() const { // Check for INT_MIN integers if (const ConstantInt *CI = dyn_cast(this)) @@ -129,6 +151,29 @@ bool Constant::isMinSignedValue() const { return false; } +bool Constant::isNotMinSignedValue() const { + // Check for INT_MIN integers + if (const ConstantInt *CI = dyn_cast(this)) + return !CI->isMinValue(/*isSigned=*/true); + + // Check for FP which are bitcasted from INT_MIN integers + if (const ConstantFP *CFP = dyn_cast(this)) + return !CFP->getValueAPF().bitcastToAPInt().isMinSignedValue(); + + // Check for constant vectors which are splats of INT_MIN values. + if (const ConstantVector *CV = dyn_cast(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isNotMinSignedValue(); + + // Check for constant vectors which are splats of INT_MIN values. + if (const ConstantDataVector *CV = dyn_cast(this)) + if (Constant *Splat = CV->getSplatValue()) + return Splat->isNotMinSignedValue(); + + // It *may* contain INT_MIN, we can't tell. + return false; +} + // Constructor to create a '0' constant of arbitrary type... Constant *Constant::getNullValue(Type *Ty) { switch (Ty->getTypeID()) { @@ -261,7 +306,7 @@ void Constant::destroyConstantImpl() { } static bool canTrapImpl(const Constant *C, - SmallPtrSet &NonTrappingOps) { + SmallPtrSetImpl &NonTrappingOps) { assert(C->getType()->isFirstClassType() && "Cannot evaluate aggregate vals!"); // The only thing that could possibly trap are constant exprs. const ConstantExpr *CE = dyn_cast(C); @@ -271,7 +316,7 @@ static bool canTrapImpl(const Constant *C, // ConstantExpr traps if any operands can trap. for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) { if (ConstantExpr *Op = dyn_cast(CE->getOperand(i))) { - if (NonTrappingOps.insert(Op) && canTrapImpl(Op, NonTrappingOps)) + if (NonTrappingOps.insert(Op).second && canTrapImpl(Op, NonTrappingOps)) return true; } } @@ -318,7 +363,7 @@ ConstHasGlobalValuePredicate(const Constant *C, const Constant *ConstOp = dyn_cast(Op); if (!ConstOp) continue; - if (Visited.insert(ConstOp)) + if (Visited.insert(ConstOp).second) WorkList.push_back(ConstOp); } } @@ -509,19 +554,17 @@ Constant *ConstantInt::getFalse(Type *Ty) { ConstantInt::getFalse(Ty->getContext())); } - -// Get a ConstantInt from an APInt. Note that the value stored in the DenseMap -// as the key, is a DenseMapAPIntKeyInfo::KeyTy which has provided the -// operator== and operator!= to ensure that the DenseMap doesn't attempt to -// compare APInt's of different widths, which would violate an APInt class -// invariant which generates an assertion. +// Get a ConstantInt from an APInt. ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt &V) { - // Get the corresponding integer type for the bit width of the value. - IntegerType *ITy = IntegerType::get(Context, V.getBitWidth()); // get an existing value or the insertion position LLVMContextImpl *pImpl = Context.pImpl; - ConstantInt *&Slot = pImpl->IntConstants[DenseMapAPIntKeyInfo::KeyTy(V, ITy)]; - if (!Slot) Slot = new ConstantInt(ITy, V); + ConstantInt *&Slot = pImpl->IntConstants[V]; + if (!Slot) { + // Get the corresponding integer type for the bit width of the value. + IntegerType *ITy = IntegerType::get(Context, V.getBitWidth()); + Slot = new ConstantInt(ITy, V); + } + assert(Slot->getType() == IntegerType::get(Context, V.getBitWidth())); return Slot; } @@ -644,7 +687,7 @@ Constant *ConstantFP::getZeroValueForNegation(Type *Ty) { ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) { LLVMContextImpl* pImpl = Context.pImpl; - ConstantFP *&Slot = pImpl->FPConstants[DenseMapAPFloatKeyInfo::KeyTy(V)]; + ConstantFP *&Slot = pImpl->FPConstants[V]; if (!Slot) { Type *Ty; @@ -781,6 +824,11 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef V) } Constant *ConstantArray::get(ArrayType *Ty, ArrayRef V) { + if (Constant *C = getImpl(Ty, V)) + return C; + return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V); +} +Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef V) { // Empty arrays are canonicalized to ConstantAggregateZero. if (V.empty()) return ConstantAggregateZero::get(Ty); @@ -789,7 +837,6 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef V) { assert(V[i]->getType() == Ty->getElementType() && "Wrong type in array element initializer"); } - LLVMContextImpl *pImpl = Ty->getContext().pImpl; // If this is an all-zero array, return a ConstantAggregateZero object. If // all undef, return an UndefValue, if "all simple", then return a @@ -871,7 +918,7 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef V) { } // Otherwise, we really do want to create a ConstantArray. - return pImpl->ArrayConstants.getOrCreate(Ty, V); + return nullptr; } /// getTypeForElements - Return an anonymous struct type to use for a constant @@ -959,9 +1006,14 @@ ConstantVector::ConstantVector(VectorType *T, ArrayRef V) // ConstantVector accessors. Constant *ConstantVector::get(ArrayRef V) { + if (Constant *C = getImpl(V)) + return C; + VectorType *Ty = VectorType::get(V.front()->getType(), V.size()); + return Ty->getContext().pImpl->VectorConstants.getOrCreate(Ty, V); +} +Constant *ConstantVector::getImpl(ArrayRef V) { assert(!V.empty() && "Vectors can't be empty"); VectorType *T = VectorType::get(V.front()->getType(), V.size()); - LLVMContextImpl *pImpl = T->getContext().pImpl; // If this is an all-undef or all-zero vector, return a // ConstantAggregateZero or UndefValue. @@ -1053,7 +1105,7 @@ Constant *ConstantVector::get(ArrayRef V) { // Otherwise, the element type isn't compatible with ConstantDataVector, or // the operand list constants a ConstantExpr or something else strange. - return pImpl->VectorConstants.getOrCreate(T, V); + return nullptr; } Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) { @@ -1141,8 +1193,8 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { /// getWithOperands - This returns the current constant expression with the /// operands replaced with the specified values. The specified array must /// have the same number of operands as our current one. -Constant *ConstantExpr:: -getWithOperands(ArrayRef Ops, Type *Ty) const { +Constant *ConstantExpr::getWithOperands(ArrayRef Ops, Type *Ty, + bool OnlyIfReduced) const { assert(Ops.size() == getNumOperands() && "Operand count mismatch!"); bool AnyChange = Ty != getType(); for (unsigned i = 0; i != Ops.size(); ++i) @@ -1151,6 +1203,7 @@ getWithOperands(ArrayRef Ops, Type *Ty) const { if (!AnyChange) // No operands changed, return self. return const_cast(this); + Type *OnlyIfReducedTy = OnlyIfReduced ? Ty : nullptr; switch (getOpcode()) { case Instruction::Trunc: case Instruction::ZExt: @@ -1165,28 +1218,34 @@ getWithOperands(ArrayRef Ops, Type *Ty) const { case Instruction::IntToPtr: case Instruction::BitCast: case Instruction::AddrSpaceCast: - return ConstantExpr::getCast(getOpcode(), Ops[0], Ty); + return ConstantExpr::getCast(getOpcode(), Ops[0], Ty, OnlyIfReduced); case Instruction::Select: - return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]); + return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2], OnlyIfReducedTy); case Instruction::InsertElement: - return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]); + return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2], + OnlyIfReducedTy); case Instruction::ExtractElement: - return ConstantExpr::getExtractElement(Ops[0], Ops[1]); + return ConstantExpr::getExtractElement(Ops[0], Ops[1], OnlyIfReducedTy); case Instruction::InsertValue: - return ConstantExpr::getInsertValue(Ops[0], Ops[1], getIndices()); + return ConstantExpr::getInsertValue(Ops[0], Ops[1], getIndices(), + OnlyIfReducedTy); case Instruction::ExtractValue: - return ConstantExpr::getExtractValue(Ops[0], getIndices()); + return ConstantExpr::getExtractValue(Ops[0], getIndices(), OnlyIfReducedTy); case Instruction::ShuffleVector: - return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); + return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2], + OnlyIfReducedTy); case Instruction::GetElementPtr: return ConstantExpr::getGetElementPtr(Ops[0], Ops.slice(1), - cast(this)->isInBounds()); + cast(this)->isInBounds(), + OnlyIfReducedTy); case Instruction::ICmp: case Instruction::FCmp: - return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]); + return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1], + OnlyIfReducedTy); default: assert(getNumOperands() == 2 && "Must be binary operator?"); - return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassOptionalData); + return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassOptionalData, + OnlyIfReducedTy); } } @@ -1447,27 +1506,21 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { // and return early. BlockAddress *&NewBA = getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)]; - if (!NewBA) { - getBasicBlock()->AdjustBlockAddressRefCount(-1); - - // Remove the old entry, this can't cause the map to rehash (just a - // tombstone will get added). - getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), - getBasicBlock())); - NewBA = this; - setOperand(0, NewF); - setOperand(1, NewBB); - getBasicBlock()->AdjustBlockAddressRefCount(1); + if (NewBA) { + replaceUsesOfWithOnConstantImpl(NewBA); return; } - // Otherwise, I do need to replace this with an existing value. - assert(NewBA != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(NewBA); + getBasicBlock()->AdjustBlockAddressRefCount(-1); - destroyConstant(); + // Remove the old entry, this can't cause the map to rehash (just a + // tombstone will get added). + getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), + getBasicBlock())); + NewBA = this; + setOperand(0, NewF); + setOperand(1, NewBB); + getBasicBlock()->AdjustBlockAddressRefCount(1); } //---- ConstantExpr::get() implementations. @@ -1475,22 +1528,26 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { /// This is a utility function to handle folding of casts and lookup of the /// cast in the ExprConstants map. It is used by the various get* methods below. -static inline Constant *getFoldedCast( - Instruction::CastOps opc, Constant *C, Type *Ty) { +static Constant *getFoldedCast(Instruction::CastOps opc, Constant *C, Type *Ty, + bool OnlyIfReduced = false) { assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!"); // Fold a few common cases if (Constant *FC = ConstantFoldCastInstruction(opc, C, Ty)) return FC; + if (OnlyIfReduced) + return nullptr; + LLVMContextImpl *pImpl = Ty->getContext().pImpl; // Look up the constant in the table first to ensure uniqueness. - ExprMapKeyType Key(opc, C); + ConstantExprKeyType Key(opc, C); return pImpl->ExprConstants.getOrCreate(Ty, Key); } -Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) { +Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty, + bool OnlyIfReduced) { Instruction::CastOps opc = Instruction::CastOps(oc); assert(Instruction::isCast(opc) && "opcode out of range"); assert(C && Ty && "Null arguments to getCast"); @@ -1499,19 +1556,32 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) { switch (opc) { default: llvm_unreachable("Invalid cast opcode"); - case Instruction::Trunc: return getTrunc(C, Ty); - case Instruction::ZExt: return getZExt(C, Ty); - case Instruction::SExt: return getSExt(C, Ty); - case Instruction::FPTrunc: return getFPTrunc(C, Ty); - case Instruction::FPExt: return getFPExtend(C, Ty); - case Instruction::UIToFP: return getUIToFP(C, Ty); - case Instruction::SIToFP: return getSIToFP(C, Ty); - case Instruction::FPToUI: return getFPToUI(C, Ty); - case Instruction::FPToSI: return getFPToSI(C, Ty); - case Instruction::PtrToInt: return getPtrToInt(C, Ty); - case Instruction::IntToPtr: return getIntToPtr(C, Ty); - case Instruction::BitCast: return getBitCast(C, Ty); - case Instruction::AddrSpaceCast: return getAddrSpaceCast(C, Ty); + case Instruction::Trunc: + return getTrunc(C, Ty, OnlyIfReduced); + case Instruction::ZExt: + return getZExt(C, Ty, OnlyIfReduced); + case Instruction::SExt: + return getSExt(C, Ty, OnlyIfReduced); + case Instruction::FPTrunc: + return getFPTrunc(C, Ty, OnlyIfReduced); + case Instruction::FPExt: + return getFPExtend(C, Ty, OnlyIfReduced); + case Instruction::UIToFP: + return getUIToFP(C, Ty, OnlyIfReduced); + case Instruction::SIToFP: + return getSIToFP(C, Ty, OnlyIfReduced); + case Instruction::FPToUI: + return getFPToUI(C, Ty, OnlyIfReduced); + case Instruction::FPToSI: + return getFPToSI(C, Ty, OnlyIfReduced); + case Instruction::PtrToInt: + return getPtrToInt(C, Ty, OnlyIfReduced); + case Instruction::IntToPtr: + return getIntToPtr(C, Ty, OnlyIfReduced); + case Instruction::BitCast: + return getBitCast(C, Ty, OnlyIfReduced); + case Instruction::AddrSpaceCast: + return getAddrSpaceCast(C, Ty, OnlyIfReduced); } } @@ -1584,7 +1654,7 @@ Constant *ConstantExpr::getFPCast(Constant *C, Type *Ty) { return getCast(opcode, C, Ty); } -Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty) { +Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1595,10 +1665,10 @@ Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty) { assert(C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&& "SrcTy must be larger than DestTy for Trunc!"); - return getFoldedCast(Instruction::Trunc, C, Ty); + return getFoldedCast(Instruction::Trunc, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getSExt(Constant *C, Type *Ty) { +Constant *ConstantExpr::getSExt(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1609,10 +1679,10 @@ Constant *ConstantExpr::getSExt(Constant *C, Type *Ty) { assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "SrcTy must be smaller than DestTy for SExt!"); - return getFoldedCast(Instruction::SExt, C, Ty); + return getFoldedCast(Instruction::SExt, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getZExt(Constant *C, Type *Ty) { +Constant *ConstantExpr::getZExt(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1623,10 +1693,10 @@ Constant *ConstantExpr::getZExt(Constant *C, Type *Ty) { assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "SrcTy must be smaller than DestTy for ZExt!"); - return getFoldedCast(Instruction::ZExt, C, Ty); + return getFoldedCast(Instruction::ZExt, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1635,10 +1705,10 @@ Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty) { assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&& "This is an illegal floating point truncation!"); - return getFoldedCast(Instruction::FPTrunc, C, Ty); + return getFoldedCast(Instruction::FPTrunc, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1647,10 +1717,10 @@ Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty) { assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() && C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&& "This is an illegal floating point extension!"); - return getFoldedCast(Instruction::FPExt, C, Ty); + return getFoldedCast(Instruction::FPExt, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty) { +Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1658,10 +1728,10 @@ Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() && "This is an illegal uint to floating point cast!"); - return getFoldedCast(Instruction::UIToFP, C, Ty); + return getFoldedCast(Instruction::UIToFP, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty) { +Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1669,10 +1739,10 @@ Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() && "This is an illegal sint to floating point cast!"); - return getFoldedCast(Instruction::SIToFP, C, Ty); + return getFoldedCast(Instruction::SIToFP, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1680,10 +1750,10 @@ Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() && "This is an illegal floating point to uint cast!"); - return getFoldedCast(Instruction::FPToUI, C, Ty); + return getFoldedCast(Instruction::FPToUI, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) { +Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced) { #ifndef NDEBUG bool fromVec = C->getType()->getTypeID() == Type::VectorTyID; bool toVec = Ty->getTypeID() == Type::VectorTyID; @@ -1691,10 +1761,11 @@ Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) { assert((fromVec == toVec) && "Cannot convert from scalar to/from vector"); assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() && "This is an illegal floating point to sint cast!"); - return getFoldedCast(Instruction::FPToSI, C, Ty); + return getFoldedCast(Instruction::FPToSI, C, Ty, OnlyIfReduced); } -Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(C->getType()->getScalarType()->isPointerTy() && "PtrToInt source must be pointer or pointer vector"); assert(DstTy->getScalarType()->isIntegerTy() && @@ -1703,10 +1774,11 @@ Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) { if (isa(C->getType())) assert(C->getType()->getVectorNumElements()==DstTy->getVectorNumElements()&& "Invalid cast between a different number of vector elements"); - return getFoldedCast(Instruction::PtrToInt, C, DstTy); + return getFoldedCast(Instruction::PtrToInt, C, DstTy, OnlyIfReduced); } -Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(C->getType()->getScalarType()->isIntegerTy() && "IntToPtr source must be integer or integer vector"); assert(DstTy->getScalarType()->isPointerTy() && @@ -1715,10 +1787,11 @@ Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) { if (isa(C->getType())) assert(C->getType()->getVectorNumElements()==DstTy->getVectorNumElements()&& "Invalid cast between a different number of vector elements"); - return getFoldedCast(Instruction::IntToPtr, C, DstTy); + return getFoldedCast(Instruction::IntToPtr, C, DstTy, OnlyIfReduced); } -Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(CastInst::castIsValid(Instruction::BitCast, C, DstTy) && "Invalid constantexpr bitcast!"); @@ -1726,10 +1799,11 @@ Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) { // speedily. if (C->getType() == DstTy) return C; - return getFoldedCast(Instruction::BitCast, C, DstTy); + return getFoldedCast(Instruction::BitCast, C, DstTy, OnlyIfReduced); } -Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) { +Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy, + bool OnlyIfReduced) { assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) && "Invalid constantexpr addrspacecast!"); @@ -1746,11 +1820,11 @@ Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) { } C = getBitCast(C, MidTy); } - return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy); + return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy, OnlyIfReduced); } Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags) { + unsigned Flags, Type *OnlyIfReducedTy) { // Check the operands for consistency first. assert(Opcode >= Instruction::BinaryOpsBegin && Opcode < Instruction::BinaryOpsEnd && @@ -1819,8 +1893,11 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2)) return FC; // Fold a few common cases. + if (OnlyIfReducedTy == C1->getType()) + return nullptr; + Constant *ArgVec[] = { C1, C2 }; - ExprMapKeyType Key(Opcode, ArgVec, 0, Flags); + ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags); LLVMContextImpl *pImpl = C1->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(C1->getType(), Key); @@ -1840,7 +1917,7 @@ Constant *ConstantExpr::getAlignOf(Type* Ty) { // alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1 // Note that a non-inbounds gep is used, as null isn't within any object. Type *AligningTy = - StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, NULL); + StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, nullptr); Constant *NullPtr = Constant::getNullValue(AligningTy->getPointerTo(0)); Constant *Zero = ConstantInt::get(Type::getInt64Ty(Ty->getContext()), 0); Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1); @@ -1868,8 +1945,8 @@ Constant *ConstantExpr::getOffsetOf(Type* Ty, Constant *FieldNo) { Type::getInt64Ty(Ty->getContext())); } -Constant *ConstantExpr::getCompare(unsigned short Predicate, - Constant *C1, Constant *C2) { +Constant *ConstantExpr::getCompare(unsigned short Predicate, Constant *C1, + Constant *C2, bool OnlyIfReduced) { assert(C1->getType() == C2->getType() && "Op types should be identical!"); switch (Predicate) { @@ -1880,31 +1957,35 @@ Constant *ConstantExpr::getCompare(unsigned short Predicate, case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: case CmpInst::FCMP_UGE: case CmpInst::FCMP_ULT: case CmpInst::FCMP_ULE: case CmpInst::FCMP_UNE: case CmpInst::FCMP_TRUE: - return getFCmp(Predicate, C1, C2); + return getFCmp(Predicate, C1, C2, OnlyIfReduced); case CmpInst::ICMP_EQ: case CmpInst::ICMP_NE: case CmpInst::ICMP_UGT: case CmpInst::ICMP_UGE: case CmpInst::ICMP_ULT: case CmpInst::ICMP_ULE: case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: case CmpInst::ICMP_SLT: case CmpInst::ICMP_SLE: - return getICmp(Predicate, C1, C2); + return getICmp(Predicate, C1, C2, OnlyIfReduced); } } -Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) { +Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2, + Type *OnlyIfReducedTy) { assert(!SelectInst::areInvalidOperands(C, V1, V2)&&"Invalid select operands"); if (Constant *SC = ConstantFoldSelectInstruction(C, V1, V2)) return SC; // Fold common cases + if (OnlyIfReducedTy == V1->getType()) + return nullptr; + Constant *ArgVec[] = { C, V1, V2 }; - ExprMapKeyType Key(Instruction::Select, ArgVec); + ConstantExprKeyType Key(Instruction::Select, ArgVec); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(V1->getType(), Key); } Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef Idxs, - bool InBounds) { + bool InBounds, Type *OnlyIfReducedTy) { assert(C->getType()->isPtrOrPtrVectorTy() && "Non-pointer type for constant GetElementPtr expression"); @@ -1919,6 +2000,9 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef Idxs, if (VectorType *VecTy = dyn_cast(C->getType())) ReqTy = VectorType::get(ReqTy, VecTy->getNumElements()); + if (OnlyIfReducedTy == ReqTy) + return nullptr; + // Look up the constant in the table first to ensure uniqueness std::vector ArgVec; ArgVec.reserve(1 + Idxs.size()); @@ -1932,15 +2016,15 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef Idxs, "getelementptr index type missmatch"); ArgVec.push_back(cast(Idxs[i])); } - const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0, - InBounds ? GEPOperator::IsInBounds : 0); + const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0, + InBounds ? GEPOperator::IsInBounds : 0); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } -Constant * -ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { +Constant *ConstantExpr::getICmp(unsigned short pred, Constant *LHS, + Constant *RHS, bool OnlyIfReduced) { assert(LHS->getType() == RHS->getType()); assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE && pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate"); @@ -1948,10 +2032,13 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS)) return FC; // Fold a few common cases... + if (OnlyIfReduced) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { LHS, RHS }; // Get the key type with both the opcode and predicate - const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred); + const ConstantExprKeyType Key(Instruction::ICmp, ArgVec, pred); Type *ResultTy = Type::getInt1Ty(LHS->getContext()); if (VectorType *VT = dyn_cast(LHS->getType())) @@ -1961,18 +2048,21 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { return pImpl->ExprConstants.getOrCreate(ResultTy, Key); } -Constant * -ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) { +Constant *ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, + Constant *RHS, bool OnlyIfReduced) { assert(LHS->getType() == RHS->getType()); assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate"); if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS)) return FC; // Fold a few common cases... + if (OnlyIfReduced) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { LHS, RHS }; // Get the key type with both the opcode and predicate - const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred); + const ConstantExprKeyType Key(Instruction::FCmp, ArgVec, pred); Type *ResultTy = Type::getInt1Ty(LHS->getContext()); if (VectorType *VT = dyn_cast(LHS->getType())) @@ -1982,7 +2072,8 @@ ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) { return pImpl->ExprConstants.getOrCreate(ResultTy, Key); } -Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { +Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx, + Type *OnlyIfReducedTy) { assert(Val->getType()->isVectorTy() && "Tried to create extractelement operation on non-vector type!"); assert(Idx->getType()->isIntegerTy() && @@ -1991,17 +2082,20 @@ Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx)) return FC; // Fold a few common cases. + Type *ReqTy = Val->getType()->getVectorElementType(); + if (OnlyIfReducedTy == ReqTy) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { Val, Idx }; - const ExprMapKeyType Key(Instruction::ExtractElement, ArgVec); + const ConstantExprKeyType Key(Instruction::ExtractElement, ArgVec); LLVMContextImpl *pImpl = Val->getContext().pImpl; - Type *ReqTy = Val->getType()->getVectorElementType(); return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } -Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, - Constant *Idx) { +Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, + Constant *Idx, Type *OnlyIfReducedTy) { assert(Val->getType()->isVectorTy() && "Tried to create insertelement operation on non-vector type!"); assert(Elt->getType() == Val->getType()->getVectorElementType() && @@ -2011,16 +2105,20 @@ Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, if (Constant *FC = ConstantFoldInsertElementInstruction(Val, Elt, Idx)) return FC; // Fold a few common cases. + + if (OnlyIfReducedTy == Val->getType()) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { Val, Elt, Idx }; - const ExprMapKeyType Key(Instruction::InsertElement, ArgVec); + const ConstantExprKeyType Key(Instruction::InsertElement, ArgVec); LLVMContextImpl *pImpl = Val->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(Val->getType(), Key); } -Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, - Constant *Mask) { +Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, + Constant *Mask, Type *OnlyIfReducedTy) { assert(ShuffleVectorInst::isValidOperands(V1, V2, Mask) && "Invalid shuffle vector constant expr operands!"); @@ -2031,16 +2129,20 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, Type *EltTy = V1->getType()->getVectorElementType(); Type *ShufTy = VectorType::get(EltTy, NElts); + if (OnlyIfReducedTy == ShufTy) + return nullptr; + // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { V1, V2, Mask }; - const ExprMapKeyType Key(Instruction::ShuffleVector, ArgVec); + const ConstantExprKeyType Key(Instruction::ShuffleVector, ArgVec); LLVMContextImpl *pImpl = ShufTy->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ShufTy, Key); } Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, - ArrayRef Idxs) { + ArrayRef Idxs, + Type *OnlyIfReducedTy) { assert(Agg->getType()->isFirstClassType() && "Non-first-class type for constant insertvalue expression"); @@ -2052,15 +2154,18 @@ Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, if (Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs)) return FC; + if (OnlyIfReducedTy == ReqTy) + return nullptr; + Constant *ArgVec[] = { Agg, Val }; - const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs); + const ConstantExprKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs); LLVMContextImpl *pImpl = Agg->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } -Constant *ConstantExpr::getExtractValue(Constant *Agg, - ArrayRef Idxs) { +Constant *ConstantExpr::getExtractValue(Constant *Agg, ArrayRef Idxs, + Type *OnlyIfReducedTy) { assert(Agg->getType()->isFirstClassType() && "Tried to create extractelement operation on non-first-class type!"); @@ -2073,8 +2178,11 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg, if (Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs)) return FC; + if (OnlyIfReducedTy == ReqTy) + return nullptr; + Constant *ArgVec[] = { Agg }; - const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs); + const ConstantExprKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs); LLVMContextImpl *pImpl = Agg->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -2326,14 +2434,16 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { return ConstantAggregateZero::get(Ty); // Do a lookup to see if we have already formed one of these. - StringMap::MapEntryTy &Slot = - Ty->getContext().pImpl->CDSConstants.GetOrCreateValue(Elements); + auto &Slot = + *Ty->getContext() + .pImpl->CDSConstants.insert(std::make_pair(Elements, nullptr)) + .first; // The bucket can point to a linked list of different CDS's that have the same // body but different types. For example, 0,0,0,1 could be a 4 element array // of i8, or a 1-element array of i32. They'll both end up in the same /// StringMap bucket, linked up by their Next pointers. Walk the list. - ConstantDataSequential **Entry = &Slot.getValue(); + ConstantDataSequential **Entry = &Slot.second; for (ConstantDataSequential *Node = *Entry; Node; Entry = &Node->Next, Node = *Entry) if (Node->getType() == Ty) @@ -2342,10 +2452,10 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) { // Okay, we didn't get a hit. Create a node of the right class, link it in, // and return it. if (isa(Ty)) - return *Entry = new ConstantDataArray(Ty, Slot.getKeyData()); + return *Entry = new ConstantDataArray(Ty, Slot.first().data()); assert(isa(Ty)); - return *Entry = new ConstantDataVector(Ty, Slot.getKeyData()); + return *Entry = new ConstantDataVector(Ty, Slot.first().data()); } void ConstantDataSequential::destroyConstant() { @@ -2431,7 +2541,7 @@ Constant *ConstantDataArray::getString(LLVMContext &Context, StringRef Str, bool AddNull) { if (!AddNull) { const uint8_t *Data = reinterpret_cast(Str.data()); - return get(Context, ArrayRef(const_cast(Data), + return get(Context, makeArrayRef(const_cast(Data), Str.size())); } @@ -2602,7 +2712,7 @@ bool ConstantDataSequential::isCString() const { } /// getSplatValue - If this is a splat constant, meaning that all of the -/// elements have the same value, return that value. Otherwise return NULL. +/// elements have the same value, return that value. Otherwise return nullptr. Constant *ConstantDataVector::getSplatValue() const { const char *Base = getRawDataValues().data(); @@ -2630,16 +2740,23 @@ Constant *ConstantDataVector::getSplatValue() const { /// work, but would be really slow because it would have to unique each updated /// array instance. /// +void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) { + // I do need to replace this with an existing value. + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement. + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To); - LLVMContextImpl *pImpl = getType()->getContext().pImpl; - SmallVector Values; - LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup; - Lookup.first = cast(getType()); Values.reserve(getNumOperands()); // Build replacement array. // Fill values with the modified operands of the constant array. Also, @@ -2658,51 +2775,25 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, AllSame &= Val == ToC; } - Constant *Replacement = nullptr; if (AllSame && ToC->isNullValue()) { - Replacement = ConstantAggregateZero::get(getType()); - } else if (AllSame && isa(ToC)) { - Replacement = UndefValue::get(getType()); - } else { - // Check to see if we have this array type already. - Lookup.second = makeArrayRef(Values); - LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I = - pImpl->ArrayConstants.find(Lookup); - - if (I != pImpl->ArrayConstants.map_end()) { - Replacement = I->first; - } else { - // Okay, the new shape doesn't exist in the system yet. Instead of - // creating a new constant array, inserting it, replaceallusesof'ing the - // old with the new, then deleting the old... just update the current one - // in place! - pImpl->ArrayConstants.remove(this); - - // Update to the new value. Optimize for the case when we have a single - // operand that we're changing, but handle bulk updates efficiently. - if (NumUpdated == 1) { - unsigned OperandToUpdate = U - OperandList; - assert(getOperand(OperandToUpdate) == From && - "ReplaceAllUsesWith broken!"); - setOperand(OperandToUpdate, ToC); - } else { - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (getOperand(i) == From) - setOperand(i, ToC); - } - pImpl->ArrayConstants.insert(this); - return; - } + replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType())); + return; + } + if (AllSame && isa(ToC)) { + replaceUsesOfWithOnConstantImpl(UndefValue::get(getType())); + return; } - // Otherwise, I do need to replace this with an existing value. - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); + // Check for any other type of constant-folding. + if (Constant *C = getImpl(getType(), Values)) { + replaceUsesOfWithOnConstantImpl(C); + return; + } - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->ArrayConstants.replaceOperandsInPlace( + Values, this, From, ToC, NumUpdated, U - OperandList)) + replaceUsesOfWithOnConstantImpl(C); } void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, @@ -2714,8 +2805,6 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); SmallVector Values; - LLVMContextImpl::StructConstantsTy::LookupKey Lookup; - Lookup.first = cast(getType()); Values.reserve(getNumOperands()); // Build replacement struct. // Fill values with the modified operands of the constant struct. Also, @@ -2742,64 +2831,47 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, } Values[OperandToUpdate] = ToC; - LLVMContextImpl *pImpl = getContext().pImpl; - - Constant *Replacement = nullptr; if (isAllZeros) { - Replacement = ConstantAggregateZero::get(getType()); - } else if (isAllUndef) { - Replacement = UndefValue::get(getType()); - } else { - // Check to see if we have this struct type already. - Lookup.second = makeArrayRef(Values); - LLVMContextImpl::StructConstantsTy::MapTy::iterator I = - pImpl->StructConstants.find(Lookup); - - if (I != pImpl->StructConstants.map_end()) { - Replacement = I->first; - } else { - // Okay, the new shape doesn't exist in the system yet. Instead of - // creating a new constant struct, inserting it, replaceallusesof'ing the - // old with the new, then deleting the old... just update the current one - // in place! - pImpl->StructConstants.remove(this); - - // Update to the new value. - setOperand(OperandToUpdate, ToC); - pImpl->StructConstants.insert(this); - return; - } + replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType())); + return; + } + if (isAllUndef) { + replaceUsesOfWithOnConstantImpl(UndefValue::get(getType())); + return; } - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->StructConstants.replaceOperandsInPlace( + Values, this, From, ToC)) + replaceUsesOfWithOnConstantImpl(C); } void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); + Constant *ToC = cast(To); SmallVector Values; Values.reserve(getNumOperands()); // Build replacement array... + unsigned NumUpdated = 0; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Val = getOperand(i); - if (Val == From) Val = cast(To); + if (Val == From) { + ++NumUpdated; + Val = ToC; + } Values.push_back(Val); } - Constant *Replacement = get(Values); - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); + if (Constant *C = getImpl(Values)) { + replaceUsesOfWithOnConstantImpl(C); + return; + } - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->VectorConstants.replaceOperandsInPlace( + Values, this, From, ToC, NumUpdated, U - OperandList)) + replaceUsesOfWithOnConstantImpl(C); } void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, @@ -2808,19 +2880,26 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, Constant *To = cast(ToV); SmallVector NewOps; + unsigned NumUpdated = 0; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Op = getOperand(i); - NewOps.push_back(Op == From ? To : Op); + if (Op == From) { + ++NumUpdated; + Op = To; + } + NewOps.push_back(Op); } + assert(NumUpdated && "I didn't contain From!"); - Constant *Replacement = getWithOperands(NewOps); - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); + if (Constant *C = getWithOperands(NewOps, getType(), true)) { + replaceUsesOfWithOnConstantImpl(C); + return; + } - // Delete the old constant! - destroyConstant(); + // Update to the new value. + if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace( + NewOps, this, From, To, NumUpdated, U - OperandList)) + replaceUsesOfWithOnConstantImpl(C); } Instruction *ConstantExpr::getAsInstruction() { diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h index f06509f..571dec2 100644 --- a/lib/IR/ConstantsContext.h +++ b/lib/IR/ConstantsContext.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CONSTANTSCONTEXT_H -#define LLVM_CONSTANTSCONTEXT_H +#ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H +#define LLVM_LIB_IR_CONSTANTSCONTEXT_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" @@ -29,8 +29,6 @@ #define DEBUG_TYPE "ir" namespace llvm { -template -struct ConstantTraits; /// UnaryConstantExpr - This class is private to Constants.cpp, and is used /// behind the scenes to implement unary constant exprs. @@ -169,11 +167,10 @@ public: void *operator new(size_t s) { return User::operator new(s, 1); } - ExtractValueConstantExpr(Constant *Agg, - const SmallVector &IdxList, + ExtractValueConstantExpr(Constant *Agg, ArrayRef IdxList, Type *DestTy) - : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1), - Indices(IdxList) { + : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1), + Indices(IdxList.begin(), IdxList.end()) { Op<0>() = Agg; } @@ -196,10 +193,9 @@ public: return User::operator new(s, 2); } InsertValueConstantExpr(Constant *Agg, Constant *Val, - const SmallVector &IdxList, - Type *DestTy) - : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2), - Indices(IdxList) { + ArrayRef IdxList, Type *DestTy) + : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2), + Indices(IdxList.begin(), IdxList.end()) { Op<0>() = Agg; Op<1>() = Val; } @@ -316,379 +312,241 @@ struct OperandTraits : }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value) -struct ExprMapKeyType { - ExprMapKeyType(unsigned opc, - ArrayRef ops, - unsigned short flags = 0, - unsigned short optionalflags = 0, - ArrayRef inds = None) - : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags), - operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {} - uint8_t opcode; - uint8_t subclassoptionaldata; - uint16_t subclassdata; - std::vector operands; - SmallVector indices; - bool operator==(const ExprMapKeyType& that) const { - return this->opcode == that.opcode && - this->subclassdata == that.subclassdata && - this->subclassoptionaldata == that.subclassoptionaldata && - this->operands == that.operands && - this->indices == that.indices; - } - bool operator<(const ExprMapKeyType & that) const { - return std::tie(opcode, operands, subclassdata, subclassoptionaldata, - indices) < - std::tie(that.opcode, that.operands, that.subclassdata, - that.subclassoptionaldata, that.indices); - } - - bool operator!=(const ExprMapKeyType& that) const { - return !(*this == that); - } -}; - -struct InlineAsmKeyType { - InlineAsmKeyType(StringRef AsmString, - StringRef Constraints, bool hasSideEffects, - bool isAlignStack, InlineAsm::AsmDialect asmDialect) - : asm_string(AsmString), constraints(Constraints), - has_side_effects(hasSideEffects), is_align_stack(isAlignStack), - asm_dialect(asmDialect) {} - std::string asm_string; - std::string constraints; - bool has_side_effects; - bool is_align_stack; - InlineAsm::AsmDialect asm_dialect; - bool operator==(const InlineAsmKeyType& that) const { - return this->asm_string == that.asm_string && - this->constraints == that.constraints && - this->has_side_effects == that.has_side_effects && - this->is_align_stack == that.is_align_stack && - this->asm_dialect == that.asm_dialect; - } - bool operator<(const InlineAsmKeyType& that) const { - return std::tie(asm_string, constraints, has_side_effects, is_align_stack, - asm_dialect) < - std::tie(that.asm_string, that.constraints, that.has_side_effects, - that.is_align_stack, that.asm_dialect); - } - - bool operator!=(const InlineAsmKeyType& that) const { - return !(*this == that); - } -}; +template struct ConstantAggrKeyType; +struct InlineAsmKeyType; +struct ConstantExprKeyType; -// The number of operands for each ConstantCreator::create method is -// determined by the ConstantTraits template. -// ConstantCreator - A class that is used to create constants by -// ConstantUniqueMap*. This class should be partially specialized if there is -// something strange that needs to be done to interface to the ctor for the -// constant. -// -template -struct ConstantTraits< std::vector > { - static unsigned uses(const std::vector& v) { - return v.size(); - } -}; - -template<> -struct ConstantTraits { - static unsigned uses(Constant * const & v) { - return 1; - } +template struct ConstantInfo; +template <> struct ConstantInfo { + typedef ConstantExprKeyType ValType; + typedef Type TypeClass; }; - -template -struct ConstantCreator { - static ConstantClass *create(TypeClass *Ty, const ValType &V) { - return new(ConstantTraits::uses(V)) ConstantClass(Ty, V); +template <> struct ConstantInfo { + typedef InlineAsmKeyType ValType; + typedef PointerType TypeClass; +}; +template <> struct ConstantInfo { + typedef ConstantAggrKeyType ValType; + typedef ArrayType TypeClass; +}; +template <> struct ConstantInfo { + typedef ConstantAggrKeyType ValType; + typedef StructType TypeClass; +}; +template <> struct ConstantInfo { + typedef ConstantAggrKeyType ValType; + typedef VectorType TypeClass; +}; + +template struct ConstantAggrKeyType { + ArrayRef Operands; + ConstantAggrKeyType(ArrayRef Operands) : Operands(Operands) {} + ConstantAggrKeyType(ArrayRef Operands, const ConstantClass *) + : Operands(Operands) {} + ConstantAggrKeyType(const ConstantClass *C, + SmallVectorImpl &Storage) { + assert(Storage.empty() && "Expected empty storage"); + for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I) + Storage.push_back(C->getOperand(I)); + Operands = Storage; + } + + bool operator==(const ConstantAggrKeyType &X) const { + return Operands == X.Operands; + } + bool operator==(const ConstantClass *C) const { + if (Operands.size() != C->getNumOperands()) + return false; + for (unsigned I = 0, E = Operands.size(); I != E; ++I) + if (Operands[I] != C->getOperand(I)) + return false; + return true; } -}; - -template -struct ConstantArrayCreator { - static ConstantClass *create(TypeClass *Ty, ArrayRef V) { - return new(V.size()) ConstantClass(Ty, V); + unsigned getHash() const { + return hash_combine_range(Operands.begin(), Operands.end()); } -}; -template -struct ConstantKeyData { - typedef void ValType; - static ValType getValType(ConstantClass *C) { - llvm_unreachable("Unknown Constant type!"); + typedef typename ConstantInfo::TypeClass TypeClass; + ConstantClass *create(TypeClass *Ty) const { + return new (Operands.size()) ConstantClass(Ty, Operands); } }; -template<> -struct ConstantCreator { - static ConstantExpr *create(Type *Ty, const ExprMapKeyType &V, - unsigned short pred = 0) { - if (Instruction::isCast(V.opcode)) - return new UnaryConstantExpr(V.opcode, V.operands[0], Ty); - if ((V.opcode >= Instruction::BinaryOpsBegin && - V.opcode < Instruction::BinaryOpsEnd)) - return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1], - V.subclassoptionaldata); - if (V.opcode == Instruction::Select) - return new SelectConstantExpr(V.operands[0], V.operands[1], - V.operands[2]); - if (V.opcode == Instruction::ExtractElement) - return new ExtractElementConstantExpr(V.operands[0], V.operands[1]); - if (V.opcode == Instruction::InsertElement) - return new InsertElementConstantExpr(V.operands[0], V.operands[1], - V.operands[2]); - if (V.opcode == Instruction::ShuffleVector) - return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1], - V.operands[2]); - if (V.opcode == Instruction::InsertValue) - return new InsertValueConstantExpr(V.operands[0], V.operands[1], - V.indices, Ty); - if (V.opcode == Instruction::ExtractValue) - return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty); - if (V.opcode == Instruction::GetElementPtr) { - std::vector IdxList(V.operands.begin()+1, V.operands.end()); - return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty, - V.subclassoptionaldata); +struct InlineAsmKeyType { + StringRef AsmString; + StringRef Constraints; + bool HasSideEffects; + bool IsAlignStack; + InlineAsm::AsmDialect AsmDialect; + + InlineAsmKeyType(StringRef AsmString, StringRef Constraints, + bool HasSideEffects, bool IsAlignStack, + InlineAsm::AsmDialect AsmDialect) + : AsmString(AsmString), Constraints(Constraints), + HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack), + AsmDialect(AsmDialect) {} + InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl &) + : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()), + HasSideEffects(Asm->hasSideEffects()), + IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {} + + bool operator==(const InlineAsmKeyType &X) const { + return HasSideEffects == X.HasSideEffects && + IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect && + AsmString == X.AsmString && Constraints == X.Constraints; + } + bool operator==(const InlineAsm *Asm) const { + return HasSideEffects == Asm->hasSideEffects() && + IsAlignStack == Asm->isAlignStack() && + AsmDialect == Asm->getDialect() && + AsmString == Asm->getAsmString() && + Constraints == Asm->getConstraintString(); + } + unsigned getHash() const { + return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack, + AsmDialect); + } + + typedef ConstantInfo::TypeClass TypeClass; + InlineAsm *create(TypeClass *Ty) const { + return new InlineAsm(Ty, AsmString, Constraints, HasSideEffects, + IsAlignStack, AsmDialect); + } +}; + +struct ConstantExprKeyType { + uint8_t Opcode; + uint8_t SubclassOptionalData; + uint16_t SubclassData; + ArrayRef Ops; + ArrayRef Indexes; + + ConstantExprKeyType(unsigned Opcode, ArrayRef Ops, + unsigned short SubclassData = 0, + unsigned short SubclassOptionalData = 0, + ArrayRef Indexes = None) + : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), + SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {} + ConstantExprKeyType(ArrayRef Operands, const ConstantExpr *CE) + : Opcode(CE->getOpcode()), + SubclassOptionalData(CE->getRawSubclassOptionalData()), + SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands), + Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef()) {} + ConstantExprKeyType(const ConstantExpr *CE, + SmallVectorImpl &Storage) + : Opcode(CE->getOpcode()), + SubclassOptionalData(CE->getRawSubclassOptionalData()), + SubclassData(CE->isCompare() ? CE->getPredicate() : 0), + Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef()) { + assert(Storage.empty() && "Expected empty storage"); + for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I) + Storage.push_back(CE->getOperand(I)); + Ops = Storage; + } + + bool operator==(const ConstantExprKeyType &X) const { + return Opcode == X.Opcode && SubclassData == X.SubclassData && + SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops && + Indexes == X.Indexes; + } + + bool operator==(const ConstantExpr *CE) const { + if (Opcode != CE->getOpcode()) + return false; + if (SubclassOptionalData != CE->getRawSubclassOptionalData()) + return false; + if (Ops.size() != CE->getNumOperands()) + return false; + if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0)) + return false; + for (unsigned I = 0, E = Ops.size(); I != E; ++I) + if (Ops[I] != CE->getOperand(I)) + return false; + if (Indexes != (CE->hasIndices() ? CE->getIndices() : ArrayRef())) + return false; + return true; + } + + unsigned getHash() const { + return hash_combine(Opcode, SubclassOptionalData, SubclassData, + hash_combine_range(Ops.begin(), Ops.end()), + hash_combine_range(Indexes.begin(), Indexes.end())); + } + + typedef ConstantInfo::TypeClass TypeClass; + ConstantExpr *create(TypeClass *Ty) const { + switch (Opcode) { + default: + if (Instruction::isCast(Opcode)) + return new UnaryConstantExpr(Opcode, Ops[0], Ty); + if ((Opcode >= Instruction::BinaryOpsBegin && + Opcode < Instruction::BinaryOpsEnd)) + return new BinaryConstantExpr(Opcode, Ops[0], Ops[1], + SubclassOptionalData); + llvm_unreachable("Invalid ConstantExpr!"); + case Instruction::Select: + return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]); + case Instruction::ExtractElement: + return new ExtractElementConstantExpr(Ops[0], Ops[1]); + case Instruction::InsertElement: + return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]); + case Instruction::ShuffleVector: + return new ShuffleVectorConstantExpr(Ops[0], Ops[1], Ops[2]); + case Instruction::InsertValue: + return new InsertValueConstantExpr(Ops[0], Ops[1], Indexes, Ty); + case Instruction::ExtractValue: + return new ExtractValueConstantExpr(Ops[0], Indexes, Ty); + case Instruction::GetElementPtr: + return GetElementPtrConstantExpr::Create(Ops[0], Ops.slice(1), Ty, + SubclassOptionalData); + case Instruction::ICmp: + return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData, + Ops[0], Ops[1]); + case Instruction::FCmp: + return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData, + Ops[0], Ops[1]); } - - // The compare instructions are weird. We have to encode the predicate - // value and it is combined with the instruction opcode by multiplying - // the opcode by one hundred. We must decode this to get the predicate. - if (V.opcode == Instruction::ICmp) - return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata, - V.operands[0], V.operands[1]); - if (V.opcode == Instruction::FCmp) - return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata, - V.operands[0], V.operands[1]); - llvm_unreachable("Invalid ConstantExpr!"); - } -}; - -template<> -struct ConstantKeyData { - typedef ExprMapKeyType ValType; - static ValType getValType(ConstantExpr *CE) { - std::vector Operands; - Operands.reserve(CE->getNumOperands()); - for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) - Operands.push_back(cast(CE->getOperand(i))); - return ExprMapKeyType(CE->getOpcode(), Operands, - CE->isCompare() ? CE->getPredicate() : 0, - CE->getRawSubclassOptionalData(), - CE->hasIndices() ? - CE->getIndices() : ArrayRef()); - } -}; - -template<> -struct ConstantCreator { - static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) { - return new InlineAsm(Ty, Key.asm_string, Key.constraints, - Key.has_side_effects, Key.is_align_stack, - Key.asm_dialect); } }; -template<> -struct ConstantKeyData { - typedef InlineAsmKeyType ValType; - static ValType getValType(InlineAsm *Asm) { - return InlineAsmKeyType(Asm->getAsmString(), Asm->getConstraintString(), - Asm->hasSideEffects(), Asm->isAlignStack(), - Asm->getDialect()); - } -}; - -template -class ConstantUniqueMap { -public: - typedef std::pair MapKey; - typedef std::map MapTy; - typedef std::map InverseMapTy; -private: - /// Map - This is the main map from the element descriptor to the Constants. - /// This is the primary way we avoid creating two of the same shape - /// constant. - MapTy Map; - - /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping - /// from the constants to their element in Map. This is important for - /// removal of constants from the array, which would otherwise have to scan - /// through the map with very large keys. - InverseMapTy InverseMap; - -public: - typename MapTy::iterator map_begin() { return Map.begin(); } - typename MapTy::iterator map_end() { return Map.end(); } - - void freeConstants() { - for (typename MapTy::iterator I=Map.begin(), E=Map.end(); - I != E; ++I) { - // Asserts that use_empty(). - delete I->second; - } - } - - /// InsertOrGetItem - Return an iterator for the specified element. - /// If the element exists in the map, the returned iterator points to the - /// entry and Exists=true. If not, the iterator points to the newly - /// inserted entry and returns Exists=false. Newly inserted entries have - /// I->second == 0, and should be filled in. - typename MapTy::iterator InsertOrGetItem(std::pair - &InsertVal, - bool &Exists) { - std::pair IP = Map.insert(InsertVal); - Exists = !IP.second; - return IP.first; - } - -private: - typename MapTy::iterator FindExistingElement(ConstantClass *CP) { - if (HasLargeKey) { - typename InverseMapTy::iterator IMI = InverseMap.find(CP); - assert(IMI != InverseMap.end() && IMI->second != Map.end() && - IMI->second->second == CP && - "InverseMap corrupt!"); - return IMI->second; - } - - typename MapTy::iterator I = - Map.find(MapKey(static_cast(CP->getType()), - ConstantKeyData::getValType(CP))); - if (I == Map.end() || I->second != CP) { - // FIXME: This should not use a linear scan. If this gets to be a - // performance problem, someone should look at this. - for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) - /* empty */; - } - return I; - } - - ConstantClass *Create(TypeClass *Ty, ValRefType V, - typename MapTy::iterator I) { - ConstantClass* Result = - ConstantCreator::create(Ty, V); - - assert(Result->getType() == Ty && "Type specified is not correct!"); - I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.insert(std::make_pair(Result, I)); - - return Result; - } +template class ConstantUniqueMap { public: - - /// getOrCreate - Return the specified constant from the map, creating it if - /// necessary. - ConstantClass *getOrCreate(TypeClass *Ty, ValRefType V) { - MapKey Lookup(Ty, V); - ConstantClass* Result = nullptr; - - typename MapTy::iterator I = Map.find(Lookup); - // Is it in the map? - if (I != Map.end()) - Result = I->second; - - if (!Result) { - // If no preexisting value, create one now... - Result = Create(Ty, V, I); - } - - return Result; - } - - void remove(ConstantClass *CP) { - typename MapTy::iterator I = FindExistingElement(CP); - assert(I != Map.end() && "Constant not found in constant table!"); - assert(I->second == CP && "Didn't find correct element?"); - - if (HasLargeKey) // Remember the reverse mapping if needed. - InverseMap.erase(CP); - - Map.erase(I); - } - - /// MoveConstantToNewSlot - If we are about to change C to be the element - /// specified by I, update our internal data structures to reflect this - /// fact. - void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) { - // First, remove the old location of the specified constant in the map. - typename MapTy::iterator OldI = FindExistingElement(C); - assert(OldI != Map.end() && "Constant not found in constant table!"); - assert(OldI->second == C && "Didn't find correct element?"); - - // Remove the old entry from the map. - Map.erase(OldI); - - // Update the inverse map so that we know that this constant is now - // located at descriptor I. - if (HasLargeKey) { - assert(I->second == C && "Bad inversemap entry!"); - InverseMap[C] = I; - } - } + typedef typename ConstantInfo::ValType ValType; + typedef typename ConstantInfo::TypeClass TypeClass; + typedef std::pair LookupKey; - void dump() const { - DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); - } -}; - -// Unique map for aggregate constants -template -class ConstantAggrUniqueMap { -public: - typedef ArrayRef Operands; - typedef std::pair LookupKey; private: struct MapInfo { - typedef DenseMapInfo ConstantClassInfo; - typedef DenseMapInfo ConstantInfo; - typedef DenseMapInfo TypeClassInfo; - static inline ConstantClass* getEmptyKey() { + typedef DenseMapInfo ConstantClassInfo; + static inline ConstantClass *getEmptyKey() { return ConstantClassInfo::getEmptyKey(); } - static inline ConstantClass* getTombstoneKey() { + static inline ConstantClass *getTombstoneKey() { return ConstantClassInfo::getTombstoneKey(); } static unsigned getHashValue(const ConstantClass *CP) { - SmallVector CPOperands; - CPOperands.reserve(CP->getNumOperands()); - for (unsigned I = 0, E = CP->getNumOperands(); I < E; ++I) - CPOperands.push_back(CP->getOperand(I)); - return getHashValue(LookupKey(CP->getType(), CPOperands)); + SmallVector Storage; + return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage))); } static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) { return LHS == RHS; } static unsigned getHashValue(const LookupKey &Val) { - return hash_combine(Val.first, hash_combine_range(Val.second.begin(), - Val.second.end())); + return hash_combine(Val.first, Val.second.getHash()); } static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) { if (RHS == getEmptyKey() || RHS == getTombstoneKey()) return false; - if (LHS.first != RHS->getType() - || LHS.second.size() != RHS->getNumOperands()) + if (LHS.first != RHS->getType()) return false; - for (unsigned I = 0, E = RHS->getNumOperands(); I < E; ++I) { - if (LHS.second[I] != RHS->getOperand(I)) - return false; - } - return true; + return LHS.second == RHS; } }; + public: typedef DenseMap MapTy; private: - /// Map - This is the main map from the element descriptor to the Constants. - /// This is the primary way we avoid creating two of the same shape - /// constant. MapTy Map; public: @@ -696,44 +554,33 @@ public: typename MapTy::iterator map_end() { return Map.end(); } void freeConstants() { - for (typename MapTy::iterator I=Map.begin(), E=Map.end(); - I != E; ++I) { + for (auto &I : Map) // Asserts that use_empty(). - delete I->first; - } + delete I.first; } private: - typename MapTy::iterator findExistingElement(ConstantClass *CP) { - return Map.find(CP); - } - - ConstantClass *Create(TypeClass *Ty, Operands V, typename MapTy::iterator I) { - ConstantClass* Result = - ConstantArrayCreator::create(Ty, V); + ConstantClass *create(TypeClass *Ty, ValType V) { + ConstantClass *Result = V.create(Ty); assert(Result->getType() == Ty && "Type specified is not correct!"); - Map[Result] = '\0'; + insert(Result); return Result; } -public: - /// getOrCreate - Return the specified constant from the map, creating it if - /// necessary. - ConstantClass *getOrCreate(TypeClass *Ty, Operands V) { +public: + /// Return the specified constant from the map, creating it if necessary. + ConstantClass *getOrCreate(TypeClass *Ty, ValType V) { LookupKey Lookup(Ty, V); - ConstantClass* Result = nullptr; + ConstantClass *Result = nullptr; - typename MapTy::iterator I = Map.find_as(Lookup); - // Is it in the map? - if (I != Map.end()) + auto I = find(Lookup); + if (I == Map.end()) + Result = create(Ty, V); + else Result = I->first; - - if (!Result) { - // If no preexisting value, create one now... - Result = Create(Ty, V, I); - } + assert(Result && "Unexpected nullptr"); return Result; } @@ -744,23 +591,44 @@ public: } /// Insert the constant into its proper slot. - void insert(ConstantClass *CP) { - Map[CP] = '\0'; - } + void insert(ConstantClass *CP) { Map[CP] = '\0'; } /// Remove this constant from the map void remove(ConstantClass *CP) { - typename MapTy::iterator I = findExistingElement(CP); + typename MapTy::iterator I = Map.find(CP); assert(I != Map.end() && "Constant not found in constant table!"); assert(I->first == CP && "Didn't find correct element?"); Map.erase(I); } - void dump() const { - DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); + ConstantClass *replaceOperandsInPlace(ArrayRef Operands, + ConstantClass *CP, Value *From, + Constant *To, unsigned NumUpdated = 0, + unsigned OperandNo = ~0u) { + LookupKey Lookup(CP->getType(), ValType(Operands, CP)); + auto I = find(Lookup); + if (I != Map.end()) + return I->first; + + // Update to the new value. Optimize for the case when we have a single + // operand that we're changing, but handle bulk updates efficiently. + remove(CP); + if (NumUpdated == 1) { + assert(OperandNo < CP->getNumOperands() && "Invalid index"); + assert(CP->getOperand(OperandNo) != To && "I didn't contain From!"); + CP->setOperand(OperandNo, To); + } else { + for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I) + if (CP->getOperand(I) == From) + CP->setOperand(I, To); + } + insert(CP); + return nullptr; } + + void dump() const { DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); } }; -} +} // end namespace llvm #endif diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index 87099a6..a25c4d6 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -183,20 +183,22 @@ void LLVMDumpModule(LLVMModuleRef M) { LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename, char **ErrorMessage) { - std::string error; - raw_fd_ostream dest(Filename, error, sys::fs::F_Text); - if (!error.empty()) { - *ErrorMessage = strdup(error.c_str()); + std::error_code EC; + raw_fd_ostream dest(Filename, EC, sys::fs::F_Text); + if (EC) { + *ErrorMessage = strdup(EC.message().c_str()); return true; } unwrap(M)->print(dest, nullptr); - if (!error.empty()) { - *ErrorMessage = strdup(error.c_str()); + dest.close(); + + if (dest.has_error()) { + *ErrorMessage = strdup("Error printing to file"); return true; } - dest.flush(); + return false; } @@ -554,12 +556,17 @@ int LLVMHasMetadata(LLVMValueRef Inst) { } LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) { - return wrap(unwrap(Inst)->getMetadata(KindID)); + auto *I = unwrap(Inst); + assert(I && "Expected instruction"); + if (auto *MD = I->getMetadata(KindID)) + return wrap(MetadataAsValue::get(I->getContext(), MD)); + return nullptr; } void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) { - unwrap(Inst)->setMetadata(KindID, - MD ? unwrap(MD) : nullptr); + MDNode *N = + MD ? cast(unwrap(MD)->getMetadata()) : nullptr; + unwrap(Inst)->setMetadata(KindID, N); } /*--.. Conversion functions ................................................--*/ @@ -571,6 +578,21 @@ void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) { LLVM_FOR_EACH_VALUE_SUBCLASS(LLVM_DEFINE_VALUE_CAST) +LLVMValueRef LLVMIsAMDNode(LLVMValueRef Val) { + if (auto *MD = dyn_cast_or_null(unwrap(Val))) + if (isa(MD->getMetadata()) || + isa(MD->getMetadata())) + return Val; + return nullptr; +} + +LLVMValueRef LLVMIsAMDString(LLVMValueRef Val) { + if (auto *MD = dyn_cast_or_null(unwrap(Val))) + if (isa(MD->getMetadata())) + return Val; + return nullptr; +} + /*--.. Operations on Uses ..................................................--*/ LLVMUseRef LLVMGetFirstUse(LLVMValueRef Val) { Value *V = unwrap(Val); @@ -596,21 +618,45 @@ LLVMValueRef LLVMGetUsedValue(LLVMUseRef U) { } /*--.. Operations on Users .................................................--*/ + +static LLVMValueRef getMDNodeOperandImpl(LLVMContext &Context, const MDNode *N, + unsigned Index) { + Metadata *Op = N->getOperand(Index); + if (!Op) + return nullptr; + if (auto *C = dyn_cast(Op)) + return wrap(C->getValue()); + return wrap(MetadataAsValue::get(Context, Op)); +} + LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index) { Value *V = unwrap(Val); - if (MDNode *MD = dyn_cast(V)) - return wrap(MD->getOperand(Index)); + if (auto *MD = dyn_cast(V)) { + if (auto *L = dyn_cast(MD->getMetadata())) { + assert(Index == 0 && "Function-local metadata can only have one operand"); + return wrap(L->getValue()); + } + return getMDNodeOperandImpl(V->getContext(), + cast(MD->getMetadata()), Index); + } + return wrap(cast(V)->getOperand(Index)); } +LLVMUseRef LLVMGetOperandUse(LLVMValueRef Val, unsigned Index) { + Value *V = unwrap(Val); + return wrap(&cast(V)->getOperandUse(Index)); +} + void LLVMSetOperand(LLVMValueRef Val, unsigned Index, LLVMValueRef Op) { unwrap(Val)->setOperand(Index, unwrap(Op)); } int LLVMGetNumOperands(LLVMValueRef Val) { Value *V = unwrap(Val); - if (MDNode *MD = dyn_cast(V)) - return MD->getNumOperands(); + if (isa(V)) + return LLVMGetMDNodeNumOperands(Val); + return cast(V)->getNumOperands(); } @@ -651,7 +697,9 @@ LLVMValueRef LLVMConstPointerNull(LLVMTypeRef Ty) { LLVMValueRef LLVMMDStringInContext(LLVMContextRef C, const char *Str, unsigned SLen) { - return wrap(MDString::get(*unwrap(C), StringRef(Str, SLen))); + LLVMContext &Context = *unwrap(C); + return wrap(MetadataAsValue::get( + Context, MDString::get(Context, StringRef(Str, SLen)))); } LLVMValueRef LLVMMDString(const char *Str, unsigned SLen) { @@ -660,8 +708,29 @@ LLVMValueRef LLVMMDString(const char *Str, unsigned SLen) { LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals, unsigned Count) { - return wrap(MDNode::get(*unwrap(C), - makeArrayRef(unwrap(Vals, Count), Count))); + LLVMContext &Context = *unwrap(C); + SmallVector MDs; + for (auto *OV : makeArrayRef(Vals, Count)) { + Value *V = unwrap(OV); + Metadata *MD; + if (!V) + MD = nullptr; + else if (auto *C = dyn_cast(V)) + MD = ConstantAsMetadata::get(C); + else if (auto *MDV = dyn_cast(V)) { + MD = MDV->getMetadata(); + assert(!isa(MD) && "Unexpected function-local metadata " + "outside of direct argument to call"); + } else { + // This is function-local metadata. Pretend to make an MDNode. + assert(Count == 1 && + "Expected only one operand to function-local metadata"); + return wrap(MetadataAsValue::get(Context, LocalAsMetadata::get(V))); + } + + MDs.push_back(MD); + } + return wrap(MetadataAsValue::get(Context, MDNode::get(Context, MDs))); } LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count) { @@ -669,25 +738,35 @@ LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count) { } const char *LLVMGetMDString(LLVMValueRef V, unsigned* Len) { - if (const MDString *S = dyn_cast(unwrap(V))) { - *Len = S->getString().size(); - return S->getString().data(); - } + if (const auto *MD = dyn_cast(unwrap(V))) + if (const MDString *S = dyn_cast(MD->getMetadata())) { + *Len = S->getString().size(); + return S->getString().data(); + } *Len = 0; return nullptr; } unsigned LLVMGetMDNodeNumOperands(LLVMValueRef V) { - return cast(unwrap(V))->getNumOperands(); + auto *MD = cast(unwrap(V)); + if (isa(MD->getMetadata())) + return 1; + return cast(MD->getMetadata())->getNumOperands(); } void LLVMGetMDNodeOperands(LLVMValueRef V, LLVMValueRef *Dest) { - const MDNode *N = cast(unwrap(V)); + auto *MD = cast(unwrap(V)); + if (auto *MDV = dyn_cast(MD->getMetadata())) { + *Dest = wrap(MDV->getValue()); + return; + } + const auto *N = cast(MD->getMetadata()); const unsigned numOperands = N->getNumOperands(); + LLVMContext &Context = unwrap(V)->getContext(); for (unsigned i = 0; i < numOperands; i++) - Dest[i] = wrap(N->getOperand(i)); + Dest[i] = getMDNodeOperandImpl(Context, N, i); } unsigned LLVMGetNamedMetadataNumOperands(LLVMModuleRef M, const char* name) @@ -703,8 +782,9 @@ void LLVMGetNamedMetadataOperands(LLVMModuleRef M, const char* name, LLVMValueRe NamedMDNode *N = unwrap(M)->getNamedMetadata(name); if (!N) return; + LLVMContext &Context = unwrap(M)->getContext(); for (unsigned i=0;igetNumOperands();i++) - Dest[i] = wrap(N->getOperand(i)); + Dest[i] = wrap(MetadataAsValue::get(Context, N->getOperand(i))); } void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char* name, @@ -713,9 +793,9 @@ void LLVMAddNamedMetadataOperand(LLVMModuleRef M, const char* name, NamedMDNode *N = unwrap(M)->getOrInsertNamedMetadata(name); if (!N) return; - MDNode *Op = Val ? unwrap(Val) : nullptr; - if (Op) - N->addOperand(Op); + if (!Val) + return; + N->addOperand(cast(unwrap(Val)->getMetadata())); } /*--.. Operations on scalar constants ......................................--*/ @@ -767,6 +847,27 @@ long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal) { return unwrap(ConstantVal)->getSExtValue(); } +double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *LosesInfo) { + ConstantFP *cFP = unwrap(ConstantVal) ; + Type *Ty = cFP->getType(); + + if (Ty->isFloatTy()) { + *LosesInfo = false; + return cFP->getValueAPF().convertToFloat(); + } + + if (Ty->isDoubleTy()) { + *LosesInfo = false; + return cFP->getValueAPF().convertToDouble(); + } + + bool APFLosesInfo; + APFloat APF = cFP->getValueAPF(); + APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &APFLosesInfo); + *LosesInfo = APFLosesInfo; + return APF.convertToDouble(); +} + /*--.. Operations on composite constants ...................................--*/ LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str, @@ -790,11 +891,27 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length, return LLVMConstStringInContext(LLVMGetGlobalContext(), Str, Length, DontNullTerminate); } + +LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef c, unsigned idx) { + return wrap(static_cast(unwrap(c))->getElementAsConstant(idx)); +} + +LLVMBool LLVMIsConstantString(LLVMValueRef c) { + return static_cast(unwrap(c))->isString(); +} + +const char *LLVMGetAsString(LLVMValueRef c, size_t* Length) { + StringRef str = static_cast(unwrap(c))->getAsString(); + *Length = str.size(); + return str.data(); +} + LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy, LLVMValueRef *ConstantVals, unsigned Length) { ArrayRef V(unwrap(ConstantVals, Length), Length); return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V)); } + LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count, LLVMBool Packed) { return LLVMConstStructInContext(LLVMGetGlobalContext(), ConstantVals, Count, @@ -1859,12 +1976,27 @@ LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst) { return (LLVMIntPredicate)0; } +LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst) { + if (FCmpInst *I = dyn_cast(unwrap(Inst))) + return (LLVMRealPredicate)I->getPredicate(); + if (ConstantExpr *CE = dyn_cast(unwrap(Inst))) + if (CE->getOpcode() == Instruction::FCmp) + return (LLVMRealPredicate)CE->getPredicate(); + return (LLVMRealPredicate)0; +} + LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst) { if (Instruction *C = dyn_cast(unwrap(Inst))) return map_to_llvmopcode(C->getOpcode()); return (LLVMOpcode)0; } +LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst) { + if (Instruction *C = dyn_cast(unwrap(Inst))) + return wrap(C->clone()); + return nullptr; +} + /*--.. Call and invoke instructions ........................................--*/ unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr) { @@ -1926,6 +2058,34 @@ void LLVMSetTailCall(LLVMValueRef Call, LLVMBool isTailCall) { unwrap(Call)->setTailCall(isTailCall); } +/*--.. Operations on terminators ...........................................--*/ + +unsigned LLVMGetNumSuccessors(LLVMValueRef Term) { + return unwrap(Term)->getNumSuccessors(); +} + +LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i) { + return wrap(unwrap(Term)->getSuccessor(i)); +} + +void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block) { + return unwrap(Term)->setSuccessor(i,unwrap(block)); +} + +/*--.. Operations on branch instructions (only) ............................--*/ + +LLVMBool LLVMIsConditional(LLVMValueRef Branch) { + return unwrap(Branch)->isConditional(); +} + +LLVMValueRef LLVMGetCondition(LLVMValueRef Branch) { + return wrap(unwrap(Branch)->getCondition()); +} + +void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond) { + return unwrap(Branch)->setCondition(unwrap(Cond)); +} + /*--.. Operations on switch instructions (only) ............................--*/ LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef Switch) { @@ -2005,13 +2165,16 @@ void LLVMDisposeBuilder(LLVMBuilderRef Builder) { /*--.. Metadata builders ...................................................--*/ void LLVMSetCurrentDebugLocation(LLVMBuilderRef Builder, LLVMValueRef L) { - MDNode *Loc = L ? unwrap(L) : nullptr; + MDNode *Loc = + L ? cast(unwrap(L)->getMetadata()) : nullptr; unwrap(Builder)->SetCurrentDebugLocation(DebugLoc::getFromDILocation(Loc)); } LLVMValueRef LLVMGetCurrentDebugLocation(LLVMBuilderRef Builder) { - return wrap(unwrap(Builder)->getCurrentDebugLocation() - .getAsMDNode(unwrap(Builder)->getContext())); + LLVMContext &Context = unwrap(Builder)->getContext(); + return wrap(MetadataAsValue::get( + Context, + unwrap(Builder)->getCurrentDebugLocation().getAsMDNode(Context))); } void LLVMSetInstDebugLocation(LLVMBuilderRef Builder, LLVMValueRef Inst) { @@ -2313,7 +2476,7 @@ static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) { case LLVMAtomicOrderingSequentiallyConsistent: return SequentiallyConsistent; } - + llvm_unreachable("Invalid LLVMAtomicOrdering value!"); } @@ -2632,10 +2795,9 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRange( const char *BufferName, LLVMBool RequiresNullTerminator) { - return wrap(MemoryBuffer::getMemBuffer( - StringRef(InputData, InputDataLength), - StringRef(BufferName), - RequiresNullTerminator)); + return wrap(MemoryBuffer::getMemBuffer(StringRef(InputData, InputDataLength), + StringRef(BufferName), + RequiresNullTerminator).release()); } LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy( @@ -2643,9 +2805,9 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy( size_t InputDataLength, const char *BufferName) { - return wrap(MemoryBuffer::getMemBufferCopy( - StringRef(InputData, InputDataLength), - StringRef(BufferName))); + return wrap( + MemoryBuffer::getMemBufferCopy(StringRef(InputData, InputDataLength), + StringRef(BufferName)).release()); } const char *LLVMGetBufferStart(LLVMMemoryBufferRef MemBuf) { diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index 218787c..856bb3c 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -23,30 +23,64 @@ using namespace llvm; using namespace llvm::dwarf; -static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) { - assert((Tag & LLVMDebugVersionMask) == 0 && - "Tag too large for debug encoding!"); - return ConstantInt::get(Type::getInt32Ty(VMContext), Tag | LLVMDebugVersion); +namespace { +class HeaderBuilder { + SmallVector Chars; + +public: + explicit HeaderBuilder(Twine T) { T.toVector(Chars); } + HeaderBuilder(const HeaderBuilder &X) : Chars(X.Chars) {} + HeaderBuilder(HeaderBuilder &&X) : Chars(std::move(X.Chars)) {} + + template HeaderBuilder &concat(Twineable &&X) { + Chars.push_back(0); + Twine(X).toVector(Chars); + return *this; + } + + MDString *get(LLVMContext &Context) const { + return MDString::get(Context, StringRef(Chars.begin(), Chars.size())); + } + + static HeaderBuilder get(unsigned Tag) { + return HeaderBuilder("0x" + Twine::utohexstr(Tag)); + } +}; } -DIBuilder::DIBuilder(Module &m) +DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes) : M(m), VMContext(M.getContext()), TempEnumTypes(nullptr), TempRetainTypes(nullptr), TempSubprograms(nullptr), TempGVs(nullptr), - DeclareFn(nullptr), ValueFn(nullptr) {} + DeclareFn(nullptr), ValueFn(nullptr), + AllowUnresolvedNodes(AllowUnresolvedNodes) {} + +static bool isUnresolved(MDNode *N) { + return N && + (isa(N) || !cast(N)->isResolved()); +} + +void DIBuilder::trackIfUnresolved(MDNode *N) { + if (!AllowUnresolvedNodes) { + assert(!isUnresolved(N) && "Cannot handle unresolved nodes"); + return; + } + if (isUnresolved(N)) + UnresolvedNodes.emplace_back(N); + return; +} -/// finalize - Construct any deferred debug info descriptors. void DIBuilder::finalize() { DIArray Enums = getOrCreateArray(AllEnumTypes); DIType(TempEnumTypes).replaceAllUsesWith(Enums); - SmallVector RetainValues; + SmallVector RetainValues; // Declarations and definitions of the same type may be retained. Some // clients RAUW these pairs, leaving duplicates in the retained types // list. Use a set to remove the duplicates while we transform the // TrackingVHs back into Values. - SmallPtrSet RetainSet; + SmallPtrSet RetainSet; for (unsigned I = 0, E = AllRetainTypes.size(); I < E; I++) - if (RetainSet.insert(AllRetainTypes[I])) + if (RetainSet.insert(AllRetainTypes[I]).second) RetainValues.push_back(AllRetainTypes[I]); DIArray RetainTypes = getOrCreateArray(RetainValues); DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes); @@ -55,13 +89,10 @@ void DIBuilder::finalize() { DIType(TempSubprograms).replaceAllUsesWith(SPs); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { DISubprogram SP(SPs.getElement(i)); - SmallVector Variables; - if (NamedMDNode *NMD = getFnSpecificMDNode(M, SP)) { - for (unsigned ii = 0, ee = NMD->getNumOperands(); ii != ee; ++ii) - Variables.push_back(NMD->getOperand(ii)); - NMD->eraseFromParent(); - } if (MDNode *Temp = SP.getVariablesNodes()) { + SmallVector Variables; + for (Metadata *V : PreservedVariables.lookup(SP)) + Variables.push_back(V); DIArray AV = getOrCreateArray(Variables); DIType(Temp).replaceAllUsesWith(AV); } @@ -70,15 +101,24 @@ void DIBuilder::finalize() { DIArray GVs = getOrCreateArray(AllGVs); DIType(TempGVs).replaceAllUsesWith(GVs); - SmallVector RetainValuesI; + SmallVector RetainValuesI; for (unsigned I = 0, E = AllImportedModules.size(); I < E; I++) RetainValuesI.push_back(AllImportedModules[I]); DIArray IMs = getOrCreateArray(RetainValuesI); DIType(TempImportedModules).replaceAllUsesWith(IMs); + + // Now that all temp nodes have been replaced or deleted, resolve remaining + // cycles. + for (const auto &N : UnresolvedNodes) + if (N) + cast(N)->resolveCycles(); + UnresolvedNodes.clear(); + + // Can't handle unresolved nodes anymore. + AllowUnresolvedNodes = false; } -/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return -/// N. +/// If N is compile unit return NULL otherwise return N. static MDNode *getNonCompileUnitScope(MDNode *N) { if (DIDescriptor(N).isCompileUnit()) return nullptr; @@ -88,15 +128,11 @@ static MDNode *getNonCompileUnitScope(MDNode *N) { static MDNode *createFilePathPair(LLVMContext &VMContext, StringRef Filename, StringRef Directory) { assert(!Filename.empty() && "Unable to create file without name"); - Value *Pair[] = { - MDString::get(VMContext, Filename), - MDString::get(VMContext, Directory) - }; + Metadata *Pair[] = {MDString::get(VMContext, Filename), + MDString::get(VMContext, Directory)}; return MDNode::get(VMContext, Pair); } -/// createCompileUnit - A CompileUnit provides an anchor for all debugging -/// information generated during this instance of compilation. DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, StringRef Directory, StringRef Producer, bool isOptimized, @@ -110,7 +146,7 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, "Invalid Language tag"); assert(!Filename.empty() && "Unable to create compile unit without filename"); - Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; + Metadata *TElts[] = {HeaderBuilder::get(DW_TAG_base_type).get(VMContext)}; TempEnumTypes = MDNode::getTemporary(VMContext, TElts); TempRetainTypes = MDNode::getTemporary(VMContext, TElts); @@ -121,22 +157,18 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, TempImportedModules = MDNode::getTemporary(VMContext, TElts); - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit), - createFilePathPair(VMContext, Filename, Directory), - ConstantInt::get(Type::getInt32Ty(VMContext), Lang), - MDString::get(VMContext, Producer), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - MDString::get(VMContext, Flags), - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer), - TempEnumTypes, - TempRetainTypes, - TempSubprograms, - TempGVs, - TempImportedModules, - MDString::get(VMContext, SplitName), - ConstantInt::get(Type::getInt32Ty(VMContext), Kind) - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_compile_unit) + .concat(Lang) + .concat(Producer) + .concat(isOptimized) + .concat(Flags) + .concat(RunTimeVer) + .concat(SplitName) + .concat(Kind) + .get(VMContext), + createFilePathPair(VMContext, Filename, Directory), + TempEnumTypes, TempRetainTypes, TempSubprograms, TempGVs, + TempImportedModules}; MDNode *CUNode = MDNode::get(VMContext, Elts); @@ -150,35 +182,21 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename, NMD->addOperand(CUNode); } + trackIfUnresolved(CUNode); return DICompileUnit(CUNode); } static DIImportedEntity createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope Context, - Value *NS, unsigned Line, StringRef Name, - SmallVectorImpl> &AllImportedModules) { + Metadata *NS, unsigned Line, StringRef Name, + SmallVectorImpl &AllImportedModules) { const MDNode *R; - if (Name.empty()) { - Value *Elts[] = { - GetTagConstant(C, Tag), - Context, - NS, - ConstantInt::get(Type::getInt32Ty(C), Line), - }; - R = MDNode::get(C, Elts); - } else { - Value *Elts[] = { - GetTagConstant(C, Tag), - Context, - NS, - ConstantInt::get(Type::getInt32Ty(C), Line), - MDString::get(C, Name) - }; - R = MDNode::get(C, Elts); - } + Metadata *Elts[] = {HeaderBuilder::get(Tag).concat(Line).concat(Name).get(C), + Context, NS}; + R = MDNode::get(C, Elts); DIImportedEntity M(R); assert(M.Verify() && "Imported module should be valid"); - AllImportedModules.push_back(TrackingVH(M)); + AllImportedModules.emplace_back(M.get()); return M; } @@ -197,10 +215,14 @@ DIImportedEntity DIBuilder::createImportedModule(DIScope Context, } DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context, - DIScope Decl, + DIDescriptor Decl, unsigned Line, StringRef Name) { + // Make sure to use the unique identifier based metadata reference for + // types that have one. + Metadata *V = + Decl.isType() ? static_cast(DIType(Decl).getRef()) : Decl; return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration, - Context, Decl.getRef(), Line, Name, + Context, V, Line, Name, AllImportedModules); } @@ -211,215 +233,187 @@ DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context, Context, Imp, Line, Name, AllImportedModules); } -/// createFile - Create a file descriptor to hold debugging information -/// for a file. DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_file_type), - createFilePathPair(VMContext, Filename, Directory) - }; + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_file_type).get(VMContext), + createFilePathPair(VMContext, Filename, Directory)}; return DIFile(MDNode::get(VMContext, Elts)); } -/// createEnumerator - Create a single enumerator value. DIEnumerator DIBuilder::createEnumerator(StringRef Name, int64_t Val) { assert(!Name.empty() && "Unable to create enumerator without name"); - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_enumerator), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt64Ty(VMContext), Val) - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_enumerator) + .concat(Name) + .concat(Val) + .get(VMContext)}; return DIEnumerator(MDNode::get(VMContext, Elts)); } -/// \brief Create a DWARF unspecified type. DIBasicType DIBuilder::createUnspecifiedType(StringRef Name) { assert(!Name.empty() && "Unable to create type without name"); // Unspecified types are encoded in DIBasicType format. Line number, filename, // size, alignment, offset and flags are always empty here. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_type), - nullptr, // Filename - nullptr, // Unused - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; - ConstantInt::get(Type::getInt32Ty(VMContext), 0) // Encoding + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_unspecified_type) + .concat(Name) + .concat(0) + .concat(0) + .concat(0) + .concat(0) + .concat(0) + .concat(0) + .get(VMContext), + nullptr, // Filename + nullptr // Unused }; return DIBasicType(MDNode::get(VMContext, Elts)); } -/// \brief Create C++11 nullptr type. DIBasicType DIBuilder::createNullPtrType() { return createUnspecifiedType("decltype(nullptr)"); } -/// createBasicType - Create debugging information entry for a basic -/// type, e.g 'char'. DIBasicType DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits, uint64_t AlignInBits, unsigned Encoding) { assert(!Name.empty() && "Unable to create type without name"); // Basic types are encoded in DIBasicType format. Line number, filename, // offset and flags are always empty here. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_base_type), - nullptr, // File/directory name - nullptr, // Unused - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags; - ConstantInt::get(Type::getInt32Ty(VMContext), Encoding) + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_base_type) + .concat(Name) + .concat(0) // Line + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .concat(Encoding) + .get(VMContext), + nullptr, // Filename + nullptr // Unused }; return DIBasicType(MDNode::get(VMContext, Elts)); } -/// createQualifiedType - Create debugging information entry for a qualified -/// type, e.g. 'const int'. DIDerivedType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) { // Qualified types are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - nullptr, // Filename - nullptr, // Unused - MDString::get(VMContext, StringRef()), // Empty name. - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - FromTy.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(Tag) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // Unused + FromTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createPointerType - Create debugging information entry for a pointer. DIDerivedType DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits, uint64_t AlignInBits, StringRef Name) { // Pointer types are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type), - nullptr, // Filename - nullptr, // Unused - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - PointeeTy.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_pointer_type) + .concat(Name) + .concat(0) // Line + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // Unused + PointeeTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy, - DIType Base) { +DIDerivedType +DIBuilder::createMemberPointerType(DIType PointeeTy, DIType Base, + uint64_t SizeInBits, uint64_t AlignInBits) { // Pointer types are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_ptr_to_member_type), - nullptr, // Filename - nullptr, // Unused - nullptr, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - PointeeTy.getRef(), - Base.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_ptr_to_member_type) + .concat(StringRef()) + .concat(0) // Line + .concat(SizeInBits) // Size + .concat(AlignInBits) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // Unused + PointeeTy.getRef(), Base.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createReferenceType - Create debugging information entry for a reference -/// type. DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) { assert(RTy.isType() && "Unable to create reference type"); // References are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - nullptr, // Filename - nullptr, // TheCU, - nullptr, // Name - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - RTy.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(Tag) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, // Filename + nullptr, // TheCU, + RTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createTypedef - Create debugging information entry for a typedef. DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File, unsigned LineNo, DIDescriptor Context) { // typedefs are encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_typedef), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - Ty.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_typedef) + .concat(Name) + .concat(LineNo) + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + File.getFileNode(), + DIScope(getNonCompileUnitScope(Context)).getRef(), + Ty.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createFriend - Create debugging information entry for a 'friend'. DIDerivedType DIBuilder::createFriend(DIType Ty, DIType FriendTy) { // typedefs are encoded in DIDerivedType format. assert(Ty.isType() && "Invalid type!"); assert(FriendTy.isType() && "Invalid friend type!"); - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_friend), - nullptr, - Ty.getRef(), - nullptr, // Name - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - FriendTy.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_friend) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(0) // Flags + .get(VMContext), + nullptr, Ty.getRef(), FriendTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createInheritance - Create debugging information entry to establish -/// inheritance relationship between two types. DIDerivedType DIBuilder::createInheritance(DIType Ty, DIType BaseTy, uint64_t BaseOffset, unsigned Flags) { assert(Ty.isType() && "Unable to create inheritance"); // TAG_inheritance is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_inheritance), - nullptr, - Ty.getRef(), - nullptr, // Name - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), BaseOffset), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - BaseTy.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_inheritance) + .concat(StringRef()) // Name + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(BaseOffset) + .concat(Flags) + .get(VMContext), + nullptr, Ty.getRef(), BaseTy.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createMemberType - Create debugging information entry for a member. DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, @@ -427,76 +421,47 @@ DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name, uint64_t OffsetInBits, unsigned Flags, DIType Ty) { // TAG_member is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty.getRef() - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(OffsetInBits) + .concat(Flags) + .get(VMContext), + File.getFileNode(), + DIScope(getNonCompileUnitScope(Scope)).getRef(), + Ty.getRef()}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createStaticMemberType - Create debugging information entry for a -/// C++ static data member. -DIDerivedType -DIBuilder::createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - DIType Ty, unsigned Flags, - llvm::Value *Val) { - // TAG_member is encoded in DIDerivedType format. - Flags |= DIDescriptor::FlagStaticMember; - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty.getRef(), - Val - }; - return DIDerivedType(MDNode::get(VMContext, Elts)); +static Metadata *getConstantOrNull(Constant *C) { + if (C) + return ConstantAsMetadata::get(C); + return nullptr; } -/// createObjCIVar - Create debugging information entry for Objective-C -/// instance variable. -DIDerivedType -DIBuilder::createObjCIVar(StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, DIType Ty, - StringRef PropertyName, StringRef GetterName, - StringRef SetterName, unsigned PropertyAttributes) { +DIDerivedType DIBuilder::createStaticMemberType(DIDescriptor Scope, + StringRef Name, DIFile File, + unsigned LineNumber, DIType Ty, + unsigned Flags, + llvm::Constant *Val) { // TAG_member is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - getNonCompileUnitScope(File), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty, - MDString::get(VMContext, PropertyName), - MDString::get(VMContext, GetterName), - MDString::get(VMContext, SetterName), - ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes) - }; + Flags |= DIDescriptor::FlagStaticMember; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member) + .concat(Name) + .concat(LineNumber) + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(Flags) + .get(VMContext), + File.getFileNode(), + DIScope(getNonCompileUnitScope(Scope)).getRef(), + Ty.getRef(), getConstantOrNull(Val)}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createObjCIVar - Create debugging information entry for Objective-C -/// instance variable. DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, @@ -504,88 +469,65 @@ DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File, uint64_t OffsetInBits, unsigned Flags, DIType Ty, MDNode *PropertyNode) { // TAG_member is encoded in DIDerivedType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_member), - File.getFileNode(), - getNonCompileUnitScope(File), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Ty, - PropertyNode - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(OffsetInBits) + .concat(Flags) + .get(VMContext), + File.getFileNode(), getNonCompileUnitScope(File), Ty, + PropertyNode}; return DIDerivedType(MDNode::get(VMContext, Elts)); } -/// createObjCProperty - Create debugging information entry for Objective-C -/// property. DIObjCProperty DIBuilder::createObjCProperty(StringRef Name, DIFile File, unsigned LineNumber, StringRef GetterName, StringRef SetterName, unsigned PropertyAttributes, DIType Ty) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_APPLE_property), - MDString::get(VMContext, Name), - File, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - MDString::get(VMContext, GetterName), - MDString::get(VMContext, SetterName), - ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes), - Ty - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_APPLE_property) + .concat(Name) + .concat(LineNumber) + .concat(GetterName) + .concat(SetterName) + .concat(PropertyAttributes) + .get(VMContext), + File, Ty}; return DIObjCProperty(MDNode::get(VMContext, Elts)); } -/// createTemplateTypeParameter - Create debugging information for template -/// type parameter. DITemplateTypeParameter DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name, DIType Ty, MDNode *File, unsigned LineNo, unsigned ColumnNo) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - Ty.getRef(), - File, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_template_type_parameter) + .concat(Name) + .concat(LineNo) + .concat(ColumnNo) + .get(VMContext), + DIScope(getNonCompileUnitScope(Context)).getRef(), + Ty.getRef(), File}; return DITemplateTypeParameter(MDNode::get(VMContext, Elts)); } -DITemplateValueParameter -DIBuilder::createTemplateValueParameter(unsigned Tag, DIDescriptor Context, - StringRef Name, DIType Ty, - Value *Val, MDNode *File, - unsigned LineNo, - unsigned ColumnNo) { - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - Ty.getRef(), - Val, - File, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo) - }; +static DITemplateValueParameter createTemplateValueParameterHelper( + LLVMContext &VMContext, unsigned Tag, DIDescriptor Context, StringRef Name, + DIType Ty, Metadata *MD, MDNode *File, unsigned LineNo, unsigned ColumnNo) { + Metadata *Elts[] = { + HeaderBuilder::get(Tag).concat(Name).concat(LineNo).concat(ColumnNo).get( + VMContext), + DIScope(getNonCompileUnitScope(Context)).getRef(), Ty.getRef(), MD, File}; return DITemplateValueParameter(MDNode::get(VMContext, Elts)); } -/// createTemplateValueParameter - Create debugging information for template -/// value parameter. DITemplateValueParameter DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name, - DIType Ty, Value *Val, - MDNode *File, unsigned LineNo, - unsigned ColumnNo) { - return createTemplateValueParameter(dwarf::DW_TAG_template_value_parameter, - Context, Name, Ty, Val, File, LineNo, - ColumnNo); + DIType Ty, Constant *Val, MDNode *File, + unsigned LineNo, unsigned ColumnNo) { + return createTemplateValueParameterHelper( + VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty, + getConstantOrNull(Val), File, LineNo, ColumnNo); } DITemplateValueParameter @@ -593,8 +535,8 @@ DIBuilder::createTemplateTemplateParameter(DIDescriptor Context, StringRef Name, DIType Ty, StringRef Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) { - return createTemplateValueParameter( - dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty, + return createTemplateValueParameterHelper( + VMContext, dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty, MDString::get(VMContext, Val), File, LineNo, ColumnNo); } @@ -603,12 +545,11 @@ DIBuilder::createTemplateParameterPack(DIDescriptor Context, StringRef Name, DIType Ty, DIArray Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) { - return createTemplateValueParameter(dwarf::DW_TAG_GNU_template_parameter_pack, - Context, Name, Ty, Val, File, LineNo, - ColumnNo); + return createTemplateValueParameterHelper( + VMContext, dwarf::DW_TAG_GNU_template_parameter_pack, Context, Name, Ty, + Val, File, LineNo, ColumnNo); } -/// createClassType - Create debugging information entry for a class. DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, @@ -622,24 +563,20 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, assert((!Context || Context.isScope() || Context.isType()) && "createClassType should be called with a valid Context"); // TAG_class_type is encoded in DICompositeType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_class_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getRef(), - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - VTableHolder.getRef(), - TemplateParams, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_class_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(OffsetInBits) + .concat(Flags) + .concat(0) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(), + DerivedFrom.getRef(), Elements, VTableHolder.getRef(), TemplateParams, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType R(MDNode::get(VMContext, Elts)); assert(R.isCompositeType() && "createClassType should return a DICompositeType"); @@ -648,7 +585,6 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name, return R; } -/// createStructType - Create debugging information entry for a struct. DICompositeType DIBuilder::createStructType(DIDescriptor Context, StringRef Name, DIFile File, unsigned LineNumber, @@ -660,24 +596,20 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context, DIType VTableHolder, StringRef UniqueIdentifier) { // TAG_structure_type is encoded in DICompositeType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_structure_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - DerivedFrom.getRef(), - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), - VTableHolder.getRef(), - nullptr, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_structure_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) + .concat(Flags) + .concat(RunTimeLang) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(), + DerivedFrom.getRef(), Elements, VTableHolder.getRef(), nullptr, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType R(MDNode::get(VMContext, Elts)); assert(R.isCompositeType() && "createStructType should return a DICompositeType"); @@ -686,7 +618,6 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context, return R; } -/// createUnionType - Create debugging information entry for an union. DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, @@ -695,80 +626,65 @@ DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name, unsigned RunTimeLang, StringRef UniqueIdentifier) { // TAG_union_type is encoded in DICompositeType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_union_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - nullptr, - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang), - nullptr, - nullptr, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_union_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(Flags) + .concat(RunTimeLang) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), + nullptr, Elements, nullptr, nullptr, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType R(MDNode::get(VMContext, Elts)); if (!UniqueIdentifier.empty()) retainType(R); return R; } -/// createSubroutineType - Create subroutine type. -DICompositeType DIBuilder::createSubroutineType(DIFile File, - DIArray ParameterTypes, - unsigned Flags) { +DISubroutineType DIBuilder::createSubroutineType(DIFile File, + DITypeArray ParameterTypes, + unsigned Flags) { // TAG_subroutine_type is encoded in DICompositeType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - nullptr, - MDString::get(VMContext, ""), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align - ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), // Flags - nullptr, - ParameterTypes, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - nullptr // Type Identifer + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_subroutine_type) + .concat(StringRef()) + .concat(0) // Line + .concat(0) // Size + .concat(0) // Align + .concat(0) // Offset + .concat(Flags) // Flags + .concat(0) + .get(VMContext), + nullptr, nullptr, nullptr, ParameterTypes, nullptr, nullptr, + nullptr // Type Identifer }; - return DICompositeType(MDNode::get(VMContext, Elts)); + return DISubroutineType(MDNode::get(VMContext, Elts)); } -/// createEnumerationType - Create debugging information entry for an -/// enumeration. DICompositeType DIBuilder::createEnumerationType( DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, StringRef UniqueIdentifier) { // TAG_enumeration_type is encoded in DICompositeType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - UnderlyingType.getRef(), - Elements, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_enumeration_type) + .concat(Name) + .concat(LineNumber) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .concat(0) + .get(VMContext), + File.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), + UnderlyingType.getRef(), Elements, nullptr, nullptr, + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; DICompositeType CTy(MDNode::get(VMContext, Elts)); AllEnumTypes.push_back(CTy); if (!UniqueIdentifier.empty()) @@ -776,138 +692,115 @@ DICompositeType DIBuilder::createEnumerationType( return CTy; } -/// createArrayType - Create debugging information entry for an array. DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // TAG_array_type is encoded in DICompositeType format. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_array_type), - nullptr, // Filename/Directory, - nullptr, // Unused - MDString::get(VMContext, ""), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), Size), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags - Ty.getRef(), - Subscripts, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - nullptr // Type Identifer + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_array_type) + .concat(StringRef()) + .concat(0) // Line + .concat(Size) + .concat(AlignInBits) + .concat(0) // Offset + .concat(0) // Flags + .concat(0) + .get(VMContext), + nullptr, // Filename/Directory, + nullptr, // Unused + Ty.getRef(), Subscripts, nullptr, nullptr, + nullptr // Type Identifer }; return DICompositeType(MDNode::get(VMContext, Elts)); } -/// createVectorType - Create debugging information entry for a vector. DICompositeType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits, DIType Ty, DIArray Subscripts) { // A vector is an array type with the FlagVector flag applied. - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_array_type), - nullptr, // Filename/Directory, - nullptr, // Unused - MDString::get(VMContext, ""), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line - ConstantInt::get(Type::getInt64Ty(VMContext), Size), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), DIType::FlagVector), - Ty.getRef(), - Subscripts, - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - nullptr, - nullptr // Type Identifer + Metadata *Elts[] = { + HeaderBuilder::get(dwarf::DW_TAG_array_type) + .concat("") + .concat(0) // Line + .concat(Size) + .concat(AlignInBits) + .concat(0) // Offset + .concat(DIType::FlagVector) + .concat(0) + .get(VMContext), + nullptr, // Filename/Directory, + nullptr, // Unused + Ty.getRef(), Subscripts, nullptr, nullptr, + nullptr // Type Identifer }; return DICompositeType(MDNode::get(VMContext, Elts)); } -/// createArtificialType - Create a new DIType with "artificial" flag set. -DIType DIBuilder::createArtificialType(DIType Ty) { - if (Ty.isArtificial()) - return Ty; +static HeaderBuilder setTypeFlagsInHeader(StringRef Header, + unsigned FlagsToSet) { + DIHeaderFieldIterator I(Header); + std::advance(I, 6); - SmallVector Elts; - MDNode *N = Ty; - assert (N && "Unexpected input DIType!"); - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) - Elts.push_back(N->getOperand(i)); + unsigned Flags; + if (I->getAsInteger(0, Flags)) + Flags = 0; + Flags |= FlagsToSet; - unsigned CurFlags = Ty.getFlags(); - CurFlags = CurFlags | DIType::FlagArtificial; + return HeaderBuilder(Twine(I.getPrefix())).concat(Flags).concat( + I.getSuffix()); +} - // Flags are stored at this slot. - // FIXME: Add an enum for this magic value. - Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); +static DIType createTypeWithFlags(LLVMContext &Context, DIType Ty, + unsigned FlagsToSet) { + SmallVector Elts; + MDNode *N = Ty; + assert(N && "Unexpected input DIType!"); + // Update header field. + Elts.push_back(setTypeFlagsInHeader(Ty.getHeader(), FlagsToSet).get(Context)); + for (unsigned I = 1, E = N->getNumOperands(); I != E; ++I) + Elts.push_back(N->getOperand(I)); - return DIType(MDNode::get(VMContext, Elts)); + return DIType(MDNode::get(Context, Elts)); +} + +DIType DIBuilder::createArtificialType(DIType Ty) { + if (Ty.isArtificial()) + return Ty; + return createTypeWithFlags(VMContext, Ty, DIType::FlagArtificial); } -/// createObjectPointerType - Create a new type with both the object pointer -/// and artificial flags set. DIType DIBuilder::createObjectPointerType(DIType Ty) { if (Ty.isObjectPointer()) return Ty; - - SmallVector Elts; - MDNode *N = Ty; - assert (N && "Unexpected input DIType!"); - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) - Elts.push_back(N->getOperand(i)); - - unsigned CurFlags = Ty.getFlags(); - CurFlags = CurFlags | (DIType::FlagObjectPointer | DIType::FlagArtificial); - - // Flags are stored at this slot. - // FIXME: Add an enum for this magic value. - Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags); - - return DIType(MDNode::get(VMContext, Elts)); + unsigned Flags = DIType::FlagObjectPointer | DIType::FlagArtificial; + return createTypeWithFlags(VMContext, Ty, Flags); } -/// retainType - Retain DIType in a module even if it is not referenced -/// through debug info anchors. -void DIBuilder::retainType(DIType T) { - AllRetainTypes.push_back(TrackingVH(T)); -} +void DIBuilder::retainType(DIType T) { AllRetainTypes.emplace_back(T); } -/// createUnspecifiedParameter - Create unspeicified type descriptor -/// for the subroutine type. -DIDescriptor DIBuilder::createUnspecifiedParameter() { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters) - }; - return DIDescriptor(MDNode::get(VMContext, Elts)); +DIBasicType DIBuilder::createUnspecifiedParameter() { + return DIBasicType(); } -/// createForwardDecl - Create a temporary forward-declared type that -/// can be RAUW'd if the full type is seen. DICompositeType DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits, StringRef UniqueIdentifier) { // Create a temporary MDNode. - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - F.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), Line), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl), - nullptr, - DIArray(), - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - nullptr, - nullptr, //TemplateParams - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; + Metadata *Elts[] = { + HeaderBuilder::get(Tag) + .concat(Name) + .concat(Line) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(DIDescriptor::FlagFwdDecl) + .concat(RuntimeLang) + .get(VMContext), + F.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), nullptr, + DIArray(), nullptr, + nullptr, // TemplateParams + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; MDNode *Node = MDNode::get(VMContext, Elts); DICompositeType RetTy(Node); assert(RetTy.isCompositeType() && @@ -917,123 +810,108 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope, return RetTy; } -/// createForwardDecl - Create a temporary forward-declared type that -/// can be RAUW'd if the full type is seen. DICompositeType DIBuilder::createReplaceableForwardDecl( unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line, unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits, StringRef UniqueIdentifier) { // Create a temporary MDNode. - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - F.getFileNode(), - DIScope(getNonCompileUnitScope(Scope)).getRef(), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), Line), - ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits), - ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset - ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl), - nullptr, - DIArray(), - ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang), - nullptr, - nullptr, //TemplateParams - UniqueIdentifier.empty() ? nullptr - : MDString::get(VMContext, UniqueIdentifier) - }; - MDNode *Node = MDNode::getTemporary(VMContext, Elts); - DICompositeType RetTy(Node); + Metadata *Elts[] = { + HeaderBuilder::get(Tag) + .concat(Name) + .concat(Line) + .concat(SizeInBits) + .concat(AlignInBits) + .concat(0) // Offset + .concat(DIDescriptor::FlagFwdDecl) + .concat(RuntimeLang) + .get(VMContext), + F.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), nullptr, + DIArray(), nullptr, + nullptr, // TemplateParams + UniqueIdentifier.empty() ? nullptr + : MDString::get(VMContext, UniqueIdentifier)}; + DICompositeType RetTy(MDNode::getTemporary(VMContext, Elts)); assert(RetTy.isCompositeType() && - "createForwardDecl result should be a DIType"); + "createReplaceableForwardDecl result should be a DIType"); if (!UniqueIdentifier.empty()) retainType(RetTy); return RetTy; } -/// getOrCreateArray - Get a DIArray, create one if required. -DIArray DIBuilder::getOrCreateArray(ArrayRef Elements) { +DIArray DIBuilder::getOrCreateArray(ArrayRef Elements) { return DIArray(MDNode::get(VMContext, Elements)); } -/// getOrCreateSubrange - Create a descriptor for a value range. This -/// implicitly uniques the values returned. +DITypeArray DIBuilder::getOrCreateTypeArray(ArrayRef Elements) { + SmallVector Elts; + for (unsigned i = 0, e = Elements.size(); i != e; ++i) { + if (Elements[i] && isa(Elements[i])) + Elts.push_back(DIType(cast(Elements[i])).getRef()); + else + Elts.push_back(Elements[i]); + } + return DITypeArray(MDNode::get(VMContext, Elts)); +} + DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type), - ConstantInt::get(Type::getInt64Ty(VMContext), Lo), - ConstantInt::get(Type::getInt64Ty(VMContext), Count) - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subrange_type) + .concat(Lo) + .concat(Count) + .get(VMContext)}; return DISubrange(MDNode::get(VMContext, Elts)); } -/// \brief Create a new descriptor for the specified global. -DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name, - StringRef LinkageName, - DIFile F, unsigned LineNumber, - DITypeRef Ty, bool isLocalToUnit, - Value *Val) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_variable), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - nullptr, // TheCU, - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ - Val, - DIDescriptor() - }; - MDNode *Node = MDNode::get(VMContext, Elts); - AllGVs.push_back(Node); - return DIGlobalVariable(Node); -} - -/// \brief Create a new descriptor for the specified global. -DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name, DIFile F, - unsigned LineNumber, - DITypeRef Ty, - bool isLocalToUnit, - Value *Val) { - return createGlobalVariable(Name, Name, F, LineNumber, Ty, isLocalToUnit, - Val); -} - -/// createStaticVariable - Create a new descriptor for the specified static -/// variable. -DIGlobalVariable DIBuilder::createStaticVariable(DIDescriptor Context, - StringRef Name, - StringRef LinkageName, - DIFile F, unsigned LineNumber, - DITypeRef Ty, - bool isLocalToUnit, - Value *Val, MDNode *Decl) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_variable), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - getNonCompileUnitScope(Context), - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/ - Val, - DIDescriptor(Decl) - }; - MDNode *Node = MDNode::get(VMContext, Elts); - AllGVs.push_back(Node); - return DIGlobalVariable(Node); +static DIGlobalVariable createGlobalVariableHelper( + LLVMContext &VMContext, DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile F, unsigned LineNumber, DITypeRef Ty, + bool isLocalToUnit, Constant *Val, MDNode *Decl, bool isDefinition, + std::function)> CreateFunc) { + + MDNode *TheCtx = getNonCompileUnitScope(Context); + if (DIScope(TheCtx).isCompositeType()) { + assert(!DICompositeType(TheCtx).getIdentifier() && + "Context of a global variable should not be a type with identifier"); + } + + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_variable) + .concat(Name) + .concat(Name) + .concat(LinkageName) + .concat(LineNumber) + .concat(isLocalToUnit) + .concat(isDefinition) + .get(VMContext), + TheCtx, F, Ty, getConstantOrNull(Val), + DIDescriptor(Decl)}; + + return DIGlobalVariable(CreateFunc(Elts)); +} + +DIGlobalVariable DIBuilder::createGlobalVariable( + DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, + unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val, + MDNode *Decl) { + return createGlobalVariableHelper( + VMContext, Context, Name, LinkageName, F, LineNumber, Ty, isLocalToUnit, + Val, Decl, true, [&](ArrayRef Elts) -> MDNode *{ + MDNode *Node = MDNode::get(VMContext, Elts); + AllGVs.push_back(Node); + return Node; + }); +} + +DIGlobalVariable DIBuilder::createTempGlobalVariableFwdDecl( + DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, + unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val, + MDNode *Decl) { + return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F, + LineNumber, Ty, isLocalToUnit, Val, Decl, + false, [&](ArrayRef Elts) { + return MDNode::getTemporary(VMContext, Elts); + }); } -/// createVariable - Create a new descriptor for the specified variable. DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo, DITypeRef Ty, @@ -1042,24 +920,20 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, DIDescriptor Context(getNonCompileUnitScope(Scope)); assert((!Context || Context.isScope()) && "createLocalVariable should be called with a valid Context"); - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - getNonCompileUnitScope(Scope), - MDString::get(VMContext, Name), - File, - ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))), - Ty, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - Constant::getNullValue(Type::getInt32Ty(VMContext)) - }; + Metadata *Elts[] = {HeaderBuilder::get(Tag) + .concat(Name) + .concat(LineNo | (ArgNo << 24)) + .concat(Flags) + .get(VMContext), + getNonCompileUnitScope(Scope), File, Ty}; MDNode *Node = MDNode::get(VMContext, Elts); if (AlwaysPreserve) { // The optimizer may remove local variable. If there is an interest // to preserve variable info in such situation then stash it in a // named mdnode. DISubprogram Fn(getDISubprogram(Scope)); - NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn); - FnLocals->addOperand(Node); + assert(Fn && "Missing subprogram for local variable"); + PreservedVariables[Fn].emplace_back(Node); } DIVariable RetVar(Node); assert(RetVar.isVariable() && @@ -1067,33 +941,20 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope, return RetVar; } -/// createComplexVariable - Create a new descriptor for the specified variable -/// which has a complex address expression for its address. -DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, DIFile F, - unsigned LineNo, - DITypeRef Ty, - ArrayRef Addr, - unsigned ArgNo) { - assert(Addr.size() > 0 && "complex address is empty"); - Value *Elts[] = { - GetTagConstant(VMContext, Tag), - getNonCompileUnitScope(Scope), - MDString::get(VMContext, Name), - F, - ConstantInt::get(Type::getInt32Ty(VMContext), - (LineNo | (ArgNo << 24))), - Ty, - Constant::getNullValue(Type::getInt32Ty(VMContext)), - Constant::getNullValue(Type::getInt32Ty(VMContext)), - MDNode::get(VMContext, Addr) - }; - return DIVariable(MDNode::get(VMContext, Elts)); +DIExpression DIBuilder::createExpression(ArrayRef Addr) { + auto Header = HeaderBuilder::get(DW_TAG_expression); + for (int64_t I : Addr) + Header.concat(I); + Metadata *Elts[] = {Header.get(VMContext)}; + return DIExpression(MDNode::get(VMContext, Elts)); +} + +DIExpression DIBuilder::createPieceExpression(unsigned OffsetInBytes, + unsigned SizeInBytes) { + int64_t Addr[] = {dwarf::DW_OP_piece, OffsetInBytes, SizeInBytes}; + return createExpression(Addr); } -/// createFunction - Create a new descriptor for the specified function. -/// FIXME: this is added for dragonegg. Once we update dragonegg -/// to call resolve function, this will be removed. DISubprogram DIBuilder::createFunction(DIScopeRef Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, @@ -1109,7 +970,38 @@ DISubprogram DIBuilder::createFunction(DIScopeRef Context, StringRef Name, Flags, isOptimized, Fn, TParams, Decl); } -/// createFunction - Create a new descriptor for the specified function. +static DISubprogram createFunctionHelper( + LLVMContext &VMContext, DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, unsigned Flags, + bool isOptimized, Function *Fn, MDNode *TParams, MDNode *Decl, MDNode *Vars, + std::function)> CreateFunc) { + assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type && + "function types should be subroutines"); + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subprogram) + .concat(Name) + .concat(Name) + .concat(LinkageName) + .concat(LineNo) + .concat(isLocalToUnit) + .concat(isDefinition) + .concat(0) + .concat(0) + .concat(Flags) + .concat(isOptimized) + .concat(ScopeLine) + .get(VMContext), + File.getFileNode(), + DIScope(getNonCompileUnitScope(Context)).getRef(), Ty, + nullptr, getConstantOrNull(Fn), TParams, Decl, Vars}; + + DISubprogram S(CreateFunc(Elts)); + assert(S.isSubprogram() && + "createFunction should return a valid DISubprogram"); + return S; +} + + DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile File, unsigned LineNo, DICompositeType Ty, @@ -1117,43 +1009,36 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name, unsigned ScopeLine, unsigned Flags, bool isOptimized, Function *Fn, MDNode *TParams, MDNode *Decl) { - assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type && - "function types should be subroutines"); - Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) }; - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), - File.getFileNode(), - DIScope(getNonCompileUnitScope(Context)).getRef(), - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - ConstantInt::get(Type::getInt32Ty(VMContext), 0), - nullptr, - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn, - TParams, - Decl, - MDNode::getTemporary(VMContext, TElts), - ConstantInt::get(Type::getInt32Ty(VMContext), ScopeLine) - }; - MDNode *Node = MDNode::get(VMContext, Elts); + return createFunctionHelper(VMContext, Context, Name, LinkageName, File, + LineNo, Ty, isLocalToUnit, isDefinition, + ScopeLine, Flags, isOptimized, Fn, TParams, Decl, + MDNode::getTemporary(VMContext, None), + [&](ArrayRef Elts) -> MDNode *{ + MDNode *Node = MDNode::get(VMContext, Elts); + // Create a named metadata so that we + // do not lose this mdnode. + if (isDefinition) + AllSubprograms.push_back(Node); + return Node; + }); +} - // Create a named metadata so that we do not lose this mdnode. - if (isDefinition) - AllSubprograms.push_back(Node); - DISubprogram S(Node); - assert(S.isSubprogram() && - "createFunction should return a valid DISubprogram"); - return S; +DISubprogram +DIBuilder::createTempFunctionFwdDecl(DIDescriptor Context, StringRef Name, + StringRef LinkageName, DIFile File, + unsigned LineNo, DICompositeType Ty, + bool isLocalToUnit, bool isDefinition, + unsigned ScopeLine, unsigned Flags, + bool isOptimized, Function *Fn, + MDNode *TParams, MDNode *Decl) { + return createFunctionHelper(VMContext, Context, Name, LinkageName, File, + LineNo, Ty, isLocalToUnit, isDefinition, + ScopeLine, Flags, isOptimized, Fn, TParams, Decl, + nullptr, [&](ArrayRef Elts) { + return MDNode::getTemporary(VMContext, Elts); + }); } -/// createMethod - Create a new descriptor for the specified C++ method. DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F, unsigned LineNo, DICompositeType Ty, @@ -1167,29 +1052,23 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, assert(getNonCompileUnitScope(Context) && "Methods should have both a Context and a context that isn't " "the compile unit."); - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_subprogram), - F.getFileNode(), - DIScope(Context).getRef(), - MDString::get(VMContext, Name), - MDString::get(VMContext, Name), - MDString::get(VMContext, LinkageName), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo), - Ty, - ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit), - ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition), - ConstantInt::get(Type::getInt32Ty(VMContext), VK), - ConstantInt::get(Type::getInt32Ty(VMContext), VIndex), - VTableHolder.getRef(), - ConstantInt::get(Type::getInt32Ty(VMContext), Flags), - ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized), - Fn, - TParam, - Constant::getNullValue(Type::getInt32Ty(VMContext)), - nullptr, - // FIXME: Do we want to use different scope/lines? - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subprogram) + .concat(Name) + .concat(Name) + .concat(LinkageName) + .concat(LineNo) + .concat(isLocalToUnit) + .concat(isDefinition) + .concat(VK) + .concat(VIndex) + .concat(Flags) + .concat(isOptimized) + .concat(LineNo) + // FIXME: Do we want to use different scope/lines? + .get(VMContext), + F.getFileNode(), DIScope(Context).getRef(), Ty, + VTableHolder.getRef(), getConstantOrNull(Fn), TParam, + nullptr, nullptr}; MDNode *Node = MDNode::get(VMContext, Elts); if (isDefinition) AllSubprograms.push_back(Node); @@ -1198,32 +1077,26 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name, return S; } -/// createNameSpace - This creates new descriptor for a namespace -/// with the specified parent scope. DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNo) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_namespace), - File.getFileNode(), - getNonCompileUnitScope(Scope), - MDString::get(VMContext, Name), - ConstantInt::get(Type::getInt32Ty(VMContext), LineNo) - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_namespace) + .concat(Name) + .concat(LineNo) + .get(VMContext), + File.getFileNode(), getNonCompileUnitScope(Scope)}; DINameSpace R(MDNode::get(VMContext, Elts)); assert(R.Verify() && "createNameSpace should return a verifiable DINameSpace"); return R; } -/// createLexicalBlockFile - This creates a new MDNode that encapsulates -/// an existing scope with a new filename. DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, - DIFile File) { - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), - File.getFileNode(), - Scope - }; + DIFile File, + unsigned Discriminator) { + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block) + .concat(Discriminator) + .get(VMContext), + File.getFileNode(), Scope}; DILexicalBlockFile R(MDNode::get(VMContext, Elts)); assert( R.Verify() && @@ -1232,8 +1105,7 @@ DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope, } DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col, - unsigned Discriminator) { + unsigned Line, unsigned Col) { // FIXME: This isn't thread safe nor the right way to defeat MDNode uniquing. // I believe the right way is to have a self-referential element in the node. // Also: why do we bother with line/column - they're not used and the @@ -1243,44 +1115,52 @@ DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File, // Defeat MDNode uniquing for lexical blocks by using unique id. static unsigned int unique_id = 0; - Value *Elts[] = { - GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block), - File.getFileNode(), - getNonCompileUnitScope(Scope), - ConstantInt::get(Type::getInt32Ty(VMContext), Line), - ConstantInt::get(Type::getInt32Ty(VMContext), Col), - ConstantInt::get(Type::getInt32Ty(VMContext), Discriminator), - ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++) - }; + Metadata *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block) + .concat(Line) + .concat(Col) + .concat(unique_id++) + .get(VMContext), + File.getFileNode(), getNonCompileUnitScope(Scope)}; DILexicalBlock R(MDNode::get(VMContext, Elts)); assert(R.Verify() && "createLexicalBlock should return a verifiable DILexicalBlock"); return R; } -/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. +static Value *getDbgIntrinsicValueImpl(LLVMContext &VMContext, Value *V) { + assert(V && "no value passed to dbg intrinsic"); + return MetadataAsValue::get(VMContext, ValueAsMetadata::get(V)); +} + Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + DIExpression Expr, Instruction *InsertBefore) { - assert(Storage && "no storage passed to dbg.declare"); assert(VarInfo.isVariable() && "empty or invalid DIVariable passed to dbg.declare"); if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; + trackIfUnresolved(VarInfo); + trackIfUnresolved(Expr); + Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage), + MetadataAsValue::get(VMContext, VarInfo), + MetadataAsValue::get(VMContext, Expr)}; return CallInst::Create(DeclareFn, Args, "", InsertBefore); } -/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, + DIExpression Expr, BasicBlock *InsertAtEnd) { - assert(Storage && "no storage passed to dbg.declare"); assert(VarInfo.isVariable() && "empty or invalid DIVariable passed to dbg.declare"); if (!DeclareFn) DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo }; + trackIfUnresolved(VarInfo); + trackIfUnresolved(Expr); + Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage), + MetadataAsValue::get(VMContext, VarInfo), + MetadataAsValue::get(VMContext, Expr)}; // If this block already has a terminator then insert this intrinsic // before the terminator. @@ -1290,9 +1170,9 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo, return CallInst::Create(DeclareFn, Args, "", InsertAtEnd); } -/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, + DIExpression Expr, Instruction *InsertBefore) { assert(V && "no value passed to dbg.value"); assert(VarInfo.isVariable() && @@ -1300,15 +1180,18 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Args[] = { MDNode::get(V->getContext(), V), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - VarInfo }; + trackIfUnresolved(VarInfo); + trackIfUnresolved(Expr); + Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, V), + ConstantInt::get(Type::getInt64Ty(VMContext), Offset), + MetadataAsValue::get(VMContext, VarInfo), + MetadataAsValue::get(VMContext, Expr)}; return CallInst::Create(ValueFn, Args, "", InsertBefore); } -/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, DIVariable VarInfo, + DIExpression Expr, BasicBlock *InsertAtEnd) { assert(V && "no value passed to dbg.value"); assert(VarInfo.isVariable() && @@ -1316,8 +1199,43 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, if (!ValueFn) ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); - Value *Args[] = { MDNode::get(V->getContext(), V), - ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset), - VarInfo }; + trackIfUnresolved(VarInfo); + trackIfUnresolved(Expr); + Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, V), + ConstantInt::get(Type::getInt64Ty(VMContext), Offset), + MetadataAsValue::get(VMContext, VarInfo), + MetadataAsValue::get(VMContext, Expr)}; return CallInst::Create(ValueFn, Args, "", InsertAtEnd); } + +void DIBuilder::replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder) { + T.setContainingType(VTableHolder); + + // If this didn't create a self-reference, just return. + if (T != VTableHolder) + return; + + // Look for unresolved operands. T has dropped RAUW support and is already + // marked resolved, orphaning any cycles underneath it. + assert(T->isResolved() && "Expected self-reference to be resolved"); + for (const MDOperand &O : T->operands()) + if (auto *N = dyn_cast_or_null(O)) + trackIfUnresolved(N); +} + +void DIBuilder::replaceArrays(DICompositeType &T, DIArray Elements, + DIArray TParams) { + T.setArrays(Elements, TParams); + + // If T isn't resolved, there's no problem. + if (!T->isResolved()) + return; + + // If "T" is resolved, it may be due to a self-reference cycle. Track the + // arrays explicitly if they're unresolved, or else the cycles will be + // orphaned. + if (Elements) + trackIfUnresolved(Elements); + if (TParams) + trackIfUnresolved(TParams); +} diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp index dea05fb..cde3937 100644 --- a/lib/IR/DataLayout.cpp +++ b/lib/IR/DataLayout.cpp @@ -55,7 +55,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { // Add padding if necessary to align the data element properly. if ((StructSize & (TyAlign-1)) != 0) - StructSize = DataLayout::RoundUpAlignment(StructSize, TyAlign); + StructSize = RoundUpToAlignment(StructSize, TyAlign); // Keep track of maximum alignment constraint. StructAlignment = std::max(TyAlign, StructAlignment); @@ -70,7 +70,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) { // Add padding to the end of the struct so that it could be put in an array // and all array elements would be aligned correctly. if ((StructSize & (StructAlignment-1)) != 0) - StructSize = DataLayout::RoundUpAlignment(StructSize, StructAlignment); + StructSize = RoundUpToAlignment(StructSize, StructAlignment); } @@ -179,7 +179,7 @@ void DataLayout::reset(StringRef Desc) { clear(); LayoutMap = nullptr; - LittleEndian = false; + BigEndian = false; StackNaturalAlign = 0; ManglingMode = MM_None; @@ -197,8 +197,10 @@ void DataLayout::reset(StringRef Desc) { static std::pair split(StringRef Str, char Separator) { assert(!Str.empty() && "parse error, string can't be empty here"); std::pair Split = Str.split(Separator); - assert((!Split.second.empty() || Split.first == Str) && - "a trailing separator is not allowed"); + if (Split.second.empty() && Split.first != Str) + report_fatal_error("Trailing separator in datalayout string"); + if (!Split.second.empty() && Split.first.empty()) + report_fatal_error("Expected token before separator in datalayout string"); return Split; } @@ -213,7 +215,8 @@ static unsigned getInt(StringRef R) { /// Convert bits into bytes. Assert if not a byte width multiple. static unsigned inBytes(unsigned Bits) { - assert(Bits % 8 == 0 && "number of bits must be a byte width multiple"); + if (Bits % 8) + report_fatal_error("number of bits must be a byte width multiple"); return Bits / 8; } @@ -239,22 +242,28 @@ void DataLayout::parseSpecifier(StringRef Desc) { // FIXME: remove this on LLVM 4.0. break; case 'E': - LittleEndian = false; + BigEndian = true; break; case 'e': - LittleEndian = true; + BigEndian = false; break; case 'p': { // Address space. unsigned AddrSpace = Tok.empty() ? 0 : getInt(Tok); - assert(AddrSpace < 1 << 24 && - "Invalid address space, must be a 24bit integer"); + if (!isUInt<24>(AddrSpace)) + report_fatal_error("Invalid address space, must be a 24bit integer"); // Size. + if (Rest.empty()) + report_fatal_error( + "Missing size specification for pointer in datalayout string"); Split = split(Rest, ':'); unsigned PointerMemSize = inBytes(getInt(Tok)); // ABI alignment. + if (Rest.empty()) + report_fatal_error( + "Missing alignment specification for pointer in datalayout string"); Split = split(Rest, ':'); unsigned PointerABIAlign = inBytes(getInt(Tok)); @@ -285,10 +294,14 @@ void DataLayout::parseSpecifier(StringRef Desc) { // Bit size. unsigned Size = Tok.empty() ? 0 : getInt(Tok); - assert((AlignType != AGGREGATE_ALIGN || Size == 0) && - "These specifications don't have a size"); + if (AlignType == AGGREGATE_ALIGN && Size != 0) + report_fatal_error( + "Sized aggregate specification in datalayout string"); // ABI alignment. + if (Rest.empty()) + report_fatal_error( + "Missing alignment specification in datalayout string"); Split = split(Rest, ':'); unsigned ABIAlign = inBytes(getInt(Tok)); @@ -306,7 +319,9 @@ void DataLayout::parseSpecifier(StringRef Desc) { case 'n': // Native integer types. for (;;) { unsigned Width = getInt(Tok); - assert(Width != 0 && "width must be non-zero"); + if (Width == 0) + report_fatal_error( + "Zero width native integer type in datalayout string"); LegalIntWidths.push_back(Width); if (Rest.empty()) break; @@ -318,11 +333,15 @@ void DataLayout::parseSpecifier(StringRef Desc) { break; } case 'm': - assert(Tok.empty()); - assert(Rest.size() == 1); + if (!Tok.empty()) + report_fatal_error("Unexpected trailing characters after mangling specifier in datalayout string"); + if (Rest.empty()) + report_fatal_error("Expected mangling specifier in datalayout string"); + if (Rest.size() > 1) + report_fatal_error("Unknown mangling specifier in datalayout string"); switch(Rest[0]) { default: - llvm_unreachable("Unknown mangling in datalayout string"); + report_fatal_error("Unknown mangling in datalayout string"); case 'e': ManglingMode = MM_ELF; break; @@ -338,13 +357,17 @@ void DataLayout::parseSpecifier(StringRef Desc) { } break; default: - llvm_unreachable("Unknown specifier in datalayout string"); + report_fatal_error("Unknown specifier in datalayout string"); break; } } } DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) { + init(M); +} + +void DataLayout::init(const Module *M) { const DataLayout *Other = M->getDataLayout(); if (Other) *this = *Other; @@ -353,7 +376,7 @@ DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) { } bool DataLayout::operator==(const DataLayout &Other) const { - bool Ret = LittleEndian == Other.LittleEndian && + bool Ret = BigEndian == Other.BigEndian && StackNaturalAlign == Other.StackNaturalAlign && ManglingMode == Other.ManglingMode && LegalIntWidths == Other.LegalIntWidths && @@ -522,7 +545,7 @@ std::string DataLayout::getStringRepresentation() const { std::string Result; raw_string_ostream OS(Result); - OS << (LittleEndian ? "e" : "E"); + OS << (BigEndian ? "E" : "e"); switch (ManglingMode) { case MM_None: @@ -637,7 +660,7 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const { ? getPointerABIAlignment(0) : getPointerPrefAlignment(0)); case Type::PointerTyID: { - unsigned AS = dyn_cast(Ty)->getAddressSpace(); + unsigned AS = cast(Ty)->getAddressSpace(); return (abi_or_pref ? getPointerABIAlignment(AS) : getPointerPrefAlignment(AS)); @@ -796,17 +819,17 @@ unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const { } DataLayoutPass::DataLayoutPass() : ImmutablePass(ID), DL("") { - report_fatal_error("Bad DataLayoutPass ctor used. Tool did not specify a " - "DataLayout to use?"); + initializeDataLayoutPassPass(*PassRegistry::getPassRegistry()); } DataLayoutPass::~DataLayoutPass() {} -DataLayoutPass::DataLayoutPass(const DataLayout &DL) - : ImmutablePass(ID), DL(DL) { - initializeDataLayoutPassPass(*PassRegistry::getPassRegistry()); +bool DataLayoutPass::doInitialization(Module &M) { + DL.init(&M); + return false; } -DataLayoutPass::DataLayoutPass(const Module *M) : ImmutablePass(ID), DL(M) { - initializeDataLayoutPassPass(*PassRegistry::getPassRegistry()); +bool DataLayoutPass::doFinalization(Module &M) { + DL.reset(""); + return false; } diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 5e39b24..290dbe2 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" @@ -46,13 +47,12 @@ bool DIDescriptor::Verify() const { DILexicalBlockFile(DbgNode).Verify() || DISubrange(DbgNode).Verify() || DIEnumerator(DbgNode).Verify() || DIObjCProperty(DbgNode).Verify() || - DIUnspecifiedParameter(DbgNode).Verify() || DITemplateTypeParameter(DbgNode).Verify() || DITemplateValueParameter(DbgNode).Verify() || - DIImportedEntity(DbgNode).Verify()); + DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify()); } -static Value *getField(const MDNode *DbgNode, unsigned Elt) { +static Metadata *getField(const MDNode *DbgNode, unsigned Elt) { if (!DbgNode || Elt >= DbgNode->getNumOperands()) return nullptr; return DbgNode->getOperand(Elt); @@ -73,25 +73,17 @@ StringRef DIDescriptor::getStringField(unsigned Elt) const { } uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const { - if (!DbgNode) - return 0; - - if (Elt < DbgNode->getNumOperands()) - if (ConstantInt *CI = - dyn_cast_or_null(DbgNode->getOperand(Elt))) + if (auto *C = getConstantField(Elt)) + if (ConstantInt *CI = dyn_cast(C)) return CI->getZExtValue(); return 0; } int64_t DIDescriptor::getInt64Field(unsigned Elt) const { - if (!DbgNode) - return 0; - - if (Elt < DbgNode->getNumOperands()) - if (ConstantInt *CI = - dyn_cast_or_null(DbgNode->getOperand(Elt))) - return CI->getSExtValue(); + if (auto *C = getConstantField(Elt)) + if (ConstantInt *CI = dyn_cast(C)) + return CI->getZExtValue(); return 0; } @@ -102,12 +94,7 @@ DIDescriptor DIDescriptor::getDescriptorField(unsigned Elt) const { } GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null(DbgNode->getOperand(Elt)); - return nullptr; + return dyn_cast_or_null(getConstantField(Elt)); } Constant *DIDescriptor::getConstantField(unsigned Elt) const { @@ -115,17 +102,14 @@ Constant *DIDescriptor::getConstantField(unsigned Elt) const { return nullptr; if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null(DbgNode->getOperand(Elt)); + if (auto *C = + dyn_cast_or_null(DbgNode->getOperand(Elt))) + return C->getValue(); return nullptr; } Function *DIDescriptor::getFunctionField(unsigned Elt) const { - if (!DbgNode) - return nullptr; - - if (Elt < DbgNode->getNumOperands()) - return dyn_cast_or_null(DbgNode->getOperand(Elt)); - return nullptr; + return dyn_cast_or_null(getConstantField(Elt)); } void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { @@ -134,29 +118,57 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) { if (Elt < DbgNode->getNumOperands()) { MDNode *Node = const_cast(DbgNode); - Node->replaceOperandWith(Elt, F); + Node->replaceOperandWith(Elt, F ? ConstantAsMetadata::get(F) : nullptr); } } -uint64_t DIVariable::getAddrElement(unsigned Idx) const { - DIDescriptor ComplexExpr = getDescriptorField(8); - if (Idx < ComplexExpr->getNumOperands()) - if (auto *CI = dyn_cast_or_null(ComplexExpr->getOperand(Idx))) - return CI->getZExtValue(); +static unsigned DIVariableInlinedAtIndex = 4; +MDNode *DIVariable::getInlinedAt() const { + return getNodeField(DbgNode, DIVariableInlinedAtIndex); +} - assert(false && "non-existing complex address element requested"); - return 0; +/// \brief Return the size reported by the variable's type. +unsigned DIVariable::getSizeInBits(const DITypeIdentifierMap &Map) { + DIType Ty = getType().resolve(Map); + // Follow derived types until we reach a type that + // reports back a size. + while (Ty.isDerivedType() && !Ty.getSizeInBits()) { + DIDerivedType DT(&*Ty); + Ty = DT.getTypeDerivedFrom().resolve(Map); + } + assert(Ty.getSizeInBits() && "type with size 0"); + return Ty.getSizeInBits(); +} + +uint64_t DIExpression::getElement(unsigned Idx) const { + unsigned I = Idx + 1; + assert(I < getNumHeaderFields() && + "non-existing complex address element requested"); + return getHeaderFieldAs(I); } -/// getInlinedAt - If this variable is inlined then return inline location. -MDNode *DIVariable::getInlinedAt() const { return getNodeField(DbgNode, 7); } +bool DIExpression::isVariablePiece() const { + return getNumElements() && getElement(0) == dwarf::DW_OP_piece; +} + +uint64_t DIExpression::getPieceOffset() const { + assert(isVariablePiece()); + return getElement(1); +} + +uint64_t DIExpression::getPieceSize() const { + assert(isVariablePiece()); + return getElement(2); +} //===----------------------------------------------------------------------===// // Predicates //===----------------------------------------------------------------------===// -/// isBasicType - Return true if the specified tag is legal for -/// DIBasicType. +bool DIDescriptor::isSubroutineType() const { + return DbgNode && getTag() == dwarf::DW_TAG_subroutine_type; +} + bool DIDescriptor::isBasicType() const { if (!DbgNode) return false; @@ -169,7 +181,6 @@ bool DIDescriptor::isBasicType() const { } } -/// isDerivedType - Return true if the specified tag is legal for DIDerivedType. bool DIDescriptor::isDerivedType() const { if (!DbgNode) return false; @@ -192,8 +203,6 @@ bool DIDescriptor::isDerivedType() const { } } -/// isCompositeType - Return true if the specified tag is legal for -/// DICompositeType. bool DIDescriptor::isCompositeType() const { if (!DbgNode) return false; @@ -210,7 +219,6 @@ bool DIDescriptor::isCompositeType() const { } } -/// isVariable - Return true if the specified tag is legal for DIVariable. bool DIDescriptor::isVariable() const { if (!DbgNode) return false; @@ -223,32 +231,19 @@ bool DIDescriptor::isVariable() const { } } -/// isType - Return true if the specified tag is legal for DIType. bool DIDescriptor::isType() const { return isBasicType() || isCompositeType() || isDerivedType(); } -/// isSubprogram - Return true if the specified tag is legal for -/// DISubprogram. bool DIDescriptor::isSubprogram() const { return DbgNode && getTag() == dwarf::DW_TAG_subprogram; } -/// isGlobalVariable - Return true if the specified tag is legal for -/// DIGlobalVariable. bool DIDescriptor::isGlobalVariable() const { return DbgNode && (getTag() == dwarf::DW_TAG_variable || getTag() == dwarf::DW_TAG_constant); } -/// isUnspecifiedParmeter - Return true if the specified tag is -/// DW_TAG_unspecified_parameters. -bool DIDescriptor::isUnspecifiedParameter() const { - return DbgNode && getTag() == dwarf::DW_TAG_unspecified_parameters; -} - -/// isScope - Return true if the specified tag is one of the scope -/// related tag. bool DIDescriptor::isScope() const { if (!DbgNode) return false; @@ -265,83 +260,67 @@ bool DIDescriptor::isScope() const { return isType(); } -/// isTemplateTypeParameter - Return true if the specified tag is -/// DW_TAG_template_type_parameter. bool DIDescriptor::isTemplateTypeParameter() const { return DbgNode && getTag() == dwarf::DW_TAG_template_type_parameter; } -/// isTemplateValueParameter - Return true if the specified tag is -/// DW_TAG_template_value_parameter. bool DIDescriptor::isTemplateValueParameter() const { return DbgNode && (getTag() == dwarf::DW_TAG_template_value_parameter || getTag() == dwarf::DW_TAG_GNU_template_template_param || getTag() == dwarf::DW_TAG_GNU_template_parameter_pack); } -/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit. bool DIDescriptor::isCompileUnit() const { return DbgNode && getTag() == dwarf::DW_TAG_compile_unit; } -/// isFile - Return true if the specified tag is DW_TAG_file_type. bool DIDescriptor::isFile() const { return DbgNode && getTag() == dwarf::DW_TAG_file_type; } -/// isNameSpace - Return true if the specified tag is DW_TAG_namespace. bool DIDescriptor::isNameSpace() const { return DbgNode && getTag() == dwarf::DW_TAG_namespace; } -/// isLexicalBlockFile - Return true if the specified descriptor is a -/// lexical block with an extra file. bool DIDescriptor::isLexicalBlockFile() const { return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && - (DbgNode->getNumOperands() == 3); + DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 2; } -/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block. bool DIDescriptor::isLexicalBlock() const { + // FIXME: There are always exactly 4 header fields in DILexicalBlock, but + // something relies on this returning true for DILexicalBlockFile. return DbgNode && getTag() == dwarf::DW_TAG_lexical_block && - (DbgNode->getNumOperands() > 3); + DbgNode->getNumOperands() == 3 && + (getNumHeaderFields() == 2 || getNumHeaderFields() == 4); } -/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type. bool DIDescriptor::isSubrange() const { return DbgNode && getTag() == dwarf::DW_TAG_subrange_type; } -/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator. bool DIDescriptor::isEnumerator() const { return DbgNode && getTag() == dwarf::DW_TAG_enumerator; } -/// isObjCProperty - Return true if the specified tag is DW_TAG_APPLE_property. bool DIDescriptor::isObjCProperty() const { return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property; } -/// \brief Return true if the specified tag is DW_TAG_imported_module or -/// DW_TAG_imported_declaration. bool DIDescriptor::isImportedEntity() const { return DbgNode && (getTag() == dwarf::DW_TAG_imported_module || getTag() == dwarf::DW_TAG_imported_declaration); } +bool DIDescriptor::isExpression() const { + return DbgNode && (getTag() == dwarf::DW_TAG_expression); +} + //===----------------------------------------------------------------------===// // Simple Descriptor Constructors and other Methods //===----------------------------------------------------------------------===// -unsigned DIArray::getNumElements() const { - if (!DbgNode) - return 0; - return DbgNode->getNumOperands(); -} - -/// replaceAllUsesWith - Replace all uses of the MDNode used by this -/// type with the one in the passed descriptor. -void DIType::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { +void DIDescriptor::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { assert(DbgNode && "Trying to replace an unverified type!"); @@ -352,33 +331,26 @@ void DIType::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) { // itself. const MDNode *DN = D; if (DbgNode == DN) { - SmallVector Ops(DbgNode->getNumOperands()); + SmallVector Ops(DbgNode->getNumOperands()); for (size_t i = 0; i != Ops.size(); ++i) Ops[i] = DbgNode->getOperand(i); DN = MDNode::get(VMContext, Ops); } - MDNode *Node = const_cast(DbgNode); - const Value *V = cast_or_null(DN); - Node->replaceAllUsesWith(const_cast(V)); + auto *Node = cast(const_cast(DbgNode)); + Node->replaceAllUsesWith(const_cast(DN)); MDNode::deleteTemporary(Node); - DbgNode = D; + DbgNode = DN; } -/// replaceAllUsesWith - Replace all uses of the MDNode used by this -/// type with the one in D. -void DIType::replaceAllUsesWith(MDNode *D) { - +void DIDescriptor::replaceAllUsesWith(MDNode *D) { assert(DbgNode && "Trying to replace an unverified type!"); assert(DbgNode != D && "This replacement should always happen"); - MDNode *Node = const_cast(DbgNode); - const MDNode *DN = D; - const Value *V = cast_or_null(DN); - Node->replaceAllUsesWith(const_cast(V)); + auto *Node = cast(const_cast(DbgNode)); + Node->replaceAllUsesWith(D); MDNode::deleteTemporary(Node); } -/// Verify - Verify that a compile unit is well formed. bool DICompileUnit::Verify() const { if (!isCompileUnit()) return false; @@ -388,65 +360,66 @@ bool DICompileUnit::Verify() const { if (getFilename().empty()) return false; - return DbgNode->getNumOperands() == 14; + return DbgNode->getNumOperands() == 7 && getNumHeaderFields() == 8; } -/// Verify - Verify that an ObjC property is well formed. bool DIObjCProperty::Verify() const { if (!isObjCProperty()) return false; // Don't worry about the rest of the strings for now. - return DbgNode->getNumOperands() == 8; + return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 6; } -/// Check if a field at position Elt of a MDNode is a MDNode. +/// \brief Check if a field at position Elt of a MDNode is a MDNode. +/// /// We currently allow an empty string and an integer. /// But we don't allow a non-empty string in a MDNode field. static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) { // FIXME: This function should return true, if the field is null or the field // is indeed a MDNode: return !Fld || isa(Fld). - Value *Fld = getField(DbgNode, Elt); + Metadata *Fld = getField(DbgNode, Elt); if (Fld && isa(Fld) && !cast(Fld)->getString().empty()) return false; return true; } -/// Check if a field at position Elt of a MDNode is a MDString. +/// \brief Check if a field at position Elt of a MDNode is a MDString. static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); + Metadata *Fld = getField(DbgNode, Elt); return !Fld || isa(Fld); } -/// Check if a value can be a reference to a type. -static bool isTypeRef(const Value *Val) { - return !Val || - (isa(Val) && !cast(Val)->getString().empty()) || - (isa(Val) && DIType(cast(Val)).isType()); +/// \brief Check if a value can be a reference to a type. +static bool isTypeRef(const Metadata *MD) { + if (!MD) + return true; + if (auto *S = dyn_cast(MD)) + return !S->getString().empty(); + if (auto *N = dyn_cast(MD)) + return DIType(N).isType(); + return false; } -/// Check if a field at position Elt of a MDNode can be a reference to a type. +/// \brief Check if referenced field might be a type. static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); - return isTypeRef(Fld); + return isTypeRef(dyn_cast_or_null(getField(DbgNode, Elt))); } -/// Check if a value can be a ScopeRef. -static bool isScopeRef(const Value *Val) { - return !Val || - (isa(Val) && !cast(Val)->getString().empty()) || - // Not checking for Val->isScope() here, because it would work - // only for lexical scopes and not all subclasses of DIScope. - isa(Val); +/// \brief Check if a value can be a ScopeRef. +static bool isScopeRef(const Metadata *MD) { + if (!MD) + return true; + if (auto *S = dyn_cast(MD)) + return !S->getString().empty(); + return isa(MD); } -/// Check if a field at position Elt of a MDNode can be a ScopeRef. +/// \brief Check if a field at position Elt of a MDNode can be a ScopeRef. static bool fieldIsScopeRef(const MDNode *DbgNode, unsigned Elt) { - Value *Fld = getField(DbgNode, Elt); - return isScopeRef(Fld); + return isScopeRef(dyn_cast_or_null(getField(DbgNode, Elt))); } -/// Verify - Verify that a type descriptor is well formed. bool DIType::Verify() const { if (!isType()) return false; @@ -467,6 +440,7 @@ bool DIType::Verify() const { Tag != dwarf::DW_TAG_inheritance && Tag != dwarf::DW_TAG_friend && getFilename().empty()) return false; + // DIType is abstract, it should be a BasicType, a DerivedType or // a CompositeType. if (isBasicType()) @@ -479,89 +453,112 @@ bool DIType::Verify() const { return false; } -/// Verify - Verify that a basic type descriptor is well formed. bool DIBasicType::Verify() const { - return isBasicType() && DbgNode->getNumOperands() == 10; + return isBasicType() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 8; } -/// Verify - Verify that a derived type descriptor is well formed. bool DIDerivedType::Verify() const { - // Make sure DerivedFrom @ field 9 is TypeRef. - if (!fieldIsTypeRef(DbgNode, 9)) + // Make sure DerivedFrom @ field 3 is TypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; if (getTag() == dwarf::DW_TAG_ptr_to_member_type) - // Make sure ClassType @ field 10 is a TypeRef. - if (!fieldIsTypeRef(DbgNode, 10)) + // Make sure ClassType @ field 4 is a TypeRef. + if (!fieldIsTypeRef(DbgNode, 4)) return false; - return isDerivedType() && DbgNode->getNumOperands() >= 10 && - DbgNode->getNumOperands() <= 14; + return isDerivedType() && DbgNode->getNumOperands() >= 4 && + DbgNode->getNumOperands() <= 8 && getNumHeaderFields() >= 7 && + getNumHeaderFields() <= 8; } -/// Verify - Verify that a composite type descriptor is well formed. bool DICompositeType::Verify() const { if (!isCompositeType()) return false; - // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are TypeRef. - if (!fieldIsTypeRef(DbgNode, 9)) + // Make sure DerivedFrom @ field 3 and ContainingType @ field 5 are TypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; - if (!fieldIsTypeRef(DbgNode, 12)) + if (!fieldIsTypeRef(DbgNode, 5)) return false; - // Make sure the type identifier at field 14 is MDString, it can be null. - if (!fieldIsMDString(DbgNode, 14)) + // Make sure the type identifier at field 7 is MDString, it can be null. + if (!fieldIsMDString(DbgNode, 7)) return false; // A subroutine type can't be both & and &&. if (isLValueReference() && isRValueReference()) return false; - return DbgNode->getNumOperands() == 15; + return DbgNode->getNumOperands() == 8 && getNumHeaderFields() == 8; } -/// Verify - Verify that a subprogram descriptor is well formed. bool DISubprogram::Verify() const { if (!isSubprogram()) return false; - // Make sure context @ field 2 is a ScopeRef and type @ field 7 is a MDNode. + // Make sure context @ field 2 is a ScopeRef and type @ field 3 is a MDNode. if (!fieldIsScopeRef(DbgNode, 2)) return false; - if (!fieldIsMDNode(DbgNode, 7)) + if (!fieldIsMDNode(DbgNode, 3)) return false; - // Containing type @ field 12. - if (!fieldIsTypeRef(DbgNode, 12)) + // Containing type @ field 4. + if (!fieldIsTypeRef(DbgNode, 4)) return false; // A subprogram can't be both & and &&. if (isLValueReference() && isRValueReference()) return false; - return DbgNode->getNumOperands() == 20; + // If a DISubprogram has an llvm::Function*, then scope chains from all + // instructions within the function should lead to this DISubprogram. + if (auto *F = getFunction()) { + for (auto &BB : *F) { + for (auto &I : BB) { + DebugLoc DL = I.getDebugLoc(); + if (DL.isUnknown()) + continue; + + MDNode *Scope = nullptr; + MDNode *IA = nullptr; + // walk the inlined-at scopes + while ((IA = DL.getInlinedAt())) + DL = DebugLoc::getFromDILocation(IA); + DL.getScopeAndInlinedAt(Scope, IA); + assert(!IA); + while (!DIDescriptor(Scope).isSubprogram()) { + DILexicalBlockFile D(Scope); + Scope = D.isLexicalBlockFile() + ? D.getScope() + : DebugLoc::getFromDILexicalBlock(Scope).getScope(); + } + if (!DISubprogram(Scope).describes(F)) + return false; + } + } + } + return DbgNode->getNumOperands() == 9 && getNumHeaderFields() == 12; } -/// Verify - Verify that a global variable descriptor is well formed. bool DIGlobalVariable::Verify() const { if (!isGlobalVariable()) return false; if (getDisplayName().empty()) return false; - // Make sure context @ field 2 is an MDNode. - if (!fieldIsMDNode(DbgNode, 2)) + // Make sure context @ field 1 is an MDNode. + if (!fieldIsMDNode(DbgNode, 1)) return false; - // Make sure that type @ field 8 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 8)) + // Make sure that type @ field 3 is a DITypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; - // Make sure StaticDataMemberDeclaration @ field 12 is MDNode. - if (!fieldIsMDNode(DbgNode, 12)) + // Make sure StaticDataMemberDeclaration @ field 5 is MDNode. + if (!fieldIsMDNode(DbgNode, 5)) return false; - return DbgNode->getNumOperands() == 13; + return DbgNode->getNumOperands() == 6 && getNumHeaderFields() == 7; } -/// Verify - Verify that a variable descriptor is well formed. bool DIVariable::Verify() const { if (!isVariable()) return false; @@ -569,127 +566,120 @@ bool DIVariable::Verify() const { // Make sure context @ field 1 is an MDNode. if (!fieldIsMDNode(DbgNode, 1)) return false; - // Make sure that type @ field 5 is a DITypeRef. - if (!fieldIsTypeRef(DbgNode, 5)) + // Make sure that type @ field 3 is a DITypeRef. + if (!fieldIsTypeRef(DbgNode, 3)) return false; - // Variable without a complex expression. - if (DbgNode->getNumOperands() == 8) + // Check the number of header fields, which is common between complex and + // simple variables. + if (getNumHeaderFields() != 4) + return false; + + // Variable without an inline location. + if (DbgNode->getNumOperands() == 4) return true; - // Make sure the complex expression is an MDNode. - return (DbgNode->getNumOperands() == 9 && fieldIsMDNode(DbgNode, 8)); + // Variable with an inline location. + return getInlinedAt() != nullptr && DbgNode->getNumOperands() == 5; } -/// Verify - Verify that a location descriptor is well formed. -bool DILocation::Verify() const { +bool DIExpression::Verify() const { + // Empty DIExpressions may be represented as a nullptr. if (!DbgNode) - return false; + return true; - return DbgNode->getNumOperands() == 4; + return isExpression() && DbgNode->getNumOperands() == 1; +} + +bool DILocation::Verify() const { + return DbgNode && isa(DbgNode); } -/// Verify - Verify that a namespace descriptor is well formed. bool DINameSpace::Verify() const { if (!isNameSpace()) return false; - return DbgNode->getNumOperands() == 5; + return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 3; } -/// \brief Retrieve the MDNode for the directory/file pair. MDNode *DIFile::getFileNode() const { return getNodeField(DbgNode, 1); } -/// \brief Verify that the file descriptor is well formed. bool DIFile::Verify() const { return isFile() && DbgNode->getNumOperands() == 2; } -/// \brief Verify that the enumerator descriptor is well formed. bool DIEnumerator::Verify() const { - return isEnumerator() && DbgNode->getNumOperands() == 3; + return isEnumerator() && DbgNode->getNumOperands() == 1 && + getNumHeaderFields() == 3; } -/// \brief Verify that the subrange descriptor is well formed. bool DISubrange::Verify() const { - return isSubrange() && DbgNode->getNumOperands() == 3; + return isSubrange() && DbgNode->getNumOperands() == 1 && + getNumHeaderFields() == 3; } -/// \brief Verify that the lexical block descriptor is well formed. bool DILexicalBlock::Verify() const { - return isLexicalBlock() && DbgNode->getNumOperands() == 7; + return isLexicalBlock() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 4; } -/// \brief Verify that the file-scoped lexical block descriptor is well formed. bool DILexicalBlockFile::Verify() const { - return isLexicalBlockFile() && DbgNode->getNumOperands() == 3; -} - -/// \brief Verify that an unspecified parameter descriptor is well formed. -bool DIUnspecifiedParameter::Verify() const { - return isUnspecifiedParameter() && DbgNode->getNumOperands() == 1; + return isLexicalBlockFile() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 2; } -/// \brief Verify that the template type parameter descriptor is well formed. bool DITemplateTypeParameter::Verify() const { - return isTemplateTypeParameter() && DbgNode->getNumOperands() == 7; + return isTemplateTypeParameter() && DbgNode->getNumOperands() == 4 && + getNumHeaderFields() == 4; } -/// \brief Verify that the template value parameter descriptor is well formed. bool DITemplateValueParameter::Verify() const { - return isTemplateValueParameter() && DbgNode->getNumOperands() == 8; + return isTemplateValueParameter() && DbgNode->getNumOperands() == 5 && + getNumHeaderFields() == 4; } -/// \brief Verify that the imported module descriptor is well formed. bool DIImportedEntity::Verify() const { - return isImportedEntity() && - (DbgNode->getNumOperands() == 4 || DbgNode->getNumOperands() == 5); + return isImportedEntity() && DbgNode->getNumOperands() == 3 && + getNumHeaderFields() == 3; } -/// getObjCProperty - Return property node, if this ivar is associated with one. MDNode *DIDerivedType::getObjCProperty() const { - return getNodeField(DbgNode, 10); + return getNodeField(DbgNode, 4); } MDString *DICompositeType::getIdentifier() const { - return cast_or_null(getField(DbgNode, 14)); + return cast_or_null(getField(DbgNode, 7)); } #ifndef NDEBUG static void VerifySubsetOf(const MDNode *LHS, const MDNode *RHS) { for (unsigned i = 0; i != LHS->getNumOperands(); ++i) { // Skip the 'empty' list (that's a single i32 0, rather than truly empty). - if (i == 0 && isa(LHS->getOperand(i))) + if (i == 0 && mdconst::hasa(LHS->getOperand(i))) continue; const MDNode *E = cast(LHS->getOperand(i)); bool found = false; for (unsigned j = 0; !found && j != RHS->getNumOperands(); ++j) - found = E == RHS->getOperand(j); + found = (E == cast(RHS->getOperand(j))); assert(found && "Losing a member during member list replacement"); } } #endif -/// \brief Set the array of member DITypes. -void DICompositeType::setTypeArray(DIArray Elements, DIArray TParams) { - assert((!TParams || DbgNode->getNumOperands() == 15) && - "If you're setting the template parameters this should include a slot " - "for that!"); - TrackingVH N(*this); +void DICompositeType::setArraysHelper(MDNode *Elements, MDNode *TParams) { + TrackingMDNodeRef N(*this); if (Elements) { #ifndef NDEBUG // Check that the new list of members contains all the old members as well. - if (const MDNode *El = cast_or_null(N->getOperand(10))) + if (const MDNode *El = cast_or_null(N->getOperand(4))) VerifySubsetOf(El, Elements); #endif - N->replaceOperandWith(10, Elements); + N->replaceOperandWith(4, Elements); } if (TParams) - N->replaceOperandWith(13, TParams); + N->replaceOperandWith(6, TParams); DbgNode = N; } -/// Generate a reference to this DIType. Uses the type identifier instead -/// of the actual MDNode if possible, to help type uniquing. DIScopeRef DIScope::getRef() const { if (!isCompositeType()) return DIScopeRef(*this); @@ -699,15 +689,12 @@ DIScopeRef DIScope::getRef() const { return DIScopeRef(DTy.getIdentifier()); } -/// \brief Set the containing type. void DICompositeType::setContainingType(DICompositeType ContainingType) { - TrackingVH N(*this); - N->replaceOperandWith(12, ContainingType.getRef()); + TrackingMDNodeRef N(*this); + N->replaceOperandWith(5, ContainingType.getRef()); DbgNode = N; } -/// isInlinedFnArgument - Return true if this variable provides debugging -/// information for an inlined function arguments. bool DIVariable::isInlinedFnArgument(const Function *CurFn) { assert(CurFn && "Invalid function"); if (!getContext().isSubprogram()) @@ -717,8 +704,6 @@ bool DIVariable::isInlinedFnArgument(const Function *CurFn) { return !DISubprogram(getContext()).describes(CurFn); } -/// describes - Return true if this subprogram provides debugging -/// information for the function F. bool DISubprogram::describes(const Function *F) { assert(F && "Invalid function"); if (F == getFunction()) @@ -731,27 +716,18 @@ bool DISubprogram::describes(const Function *F) { return false; } -unsigned DISubprogram::isOptimized() const { - assert(DbgNode && "Invalid subprogram descriptor!"); - if (DbgNode->getNumOperands() == 15) - return getUnsignedField(14); - return 0; -} - MDNode *DISubprogram::getVariablesNodes() const { - return getNodeField(DbgNode, 18); + return getNodeField(DbgNode, 8); } DIArray DISubprogram::getVariables() const { - return DIArray(getNodeField(DbgNode, 18)); + return DIArray(getNodeField(DbgNode, 8)); } -Value *DITemplateValueParameter::getValue() const { - return getField(DbgNode, 4); +Metadata *DITemplateValueParameter::getValue() const { + return DbgNode->getOperand(3); } -// If the current node has a parent scope then return that, -// else return an empty scope. DIScopeRef DIScope::getContext() const { if (isType()) @@ -773,7 +749,6 @@ DIScopeRef DIScope::getContext() const { return DIScopeRef(nullptr); } -// If the scope node has a name, return that, else return an empty string. StringRef DIScope::getName() const { if (isType()) return DIType(DbgNode).getName(); @@ -800,128 +775,103 @@ StringRef DIScope::getDirectory() const { } DIArray DICompileUnit::getEnumTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 7)); + return DIArray(getNodeField(DbgNode, 2)); } DIArray DICompileUnit::getRetainedTypes() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 8)); + return DIArray(getNodeField(DbgNode, 3)); } DIArray DICompileUnit::getSubprograms() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 9)); + return DIArray(getNodeField(DbgNode, 4)); } DIArray DICompileUnit::getGlobalVariables() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 10)); + return DIArray(getNodeField(DbgNode, 5)); } DIArray DICompileUnit::getImportedEntities() const { - if (!DbgNode || DbgNode->getNumOperands() < 13) + if (!DbgNode || DbgNode->getNumOperands() < 7) return DIArray(); - return DIArray(getNodeField(DbgNode, 11)); + return DIArray(getNodeField(DbgNode, 6)); } -/// copyWithNewScope - Return a copy of this location, replacing the -/// current scope with the given one. -DILocation DILocation::copyWithNewScope(LLVMContext &Ctx, - DILexicalBlock NewScope) { - SmallVector Elts; - assert(Verify()); - for (unsigned I = 0; I < DbgNode->getNumOperands(); ++I) { - if (I != 2) - Elts.push_back(DbgNode->getOperand(I)); - else - Elts.push_back(NewScope); - } - MDNode *NewDIL = MDNode::get(Ctx, Elts); - return DILocation(NewDIL); -} +void DICompileUnit::replaceSubprograms(DIArray Subprograms) { + assert(Verify() && "Expected compile unit"); + if (Subprograms == getSubprograms()) + return; -/// computeNewDiscriminator - Generate a new discriminator value for this -/// file and line location. -unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) { - std::pair Key(getFilename().data(), getLineNumber()); - return ++Ctx.pImpl->DiscriminatorTable[Key]; + const_cast(DbgNode)->replaceOperandWith(4, Subprograms); } -/// fixupSubprogramName - Replace contains special characters used -/// in a typical Objective-C names with '.' in a given string. -static void fixupSubprogramName(DISubprogram Fn, SmallVectorImpl &Out) { - StringRef FName = - Fn.getFunction() ? Fn.getFunction()->getName() : Fn.getName(); - FName = Function::getRealLinkageName(FName); - - StringRef Prefix("llvm.dbg.lv."); - Out.reserve(FName.size() + Prefix.size()); - Out.append(Prefix.begin(), Prefix.end()); - - bool isObjCLike = false; - for (size_t i = 0, e = FName.size(); i < e; ++i) { - char C = FName[i]; - if (C == '[') - isObjCLike = true; - - if (isObjCLike && (C == '[' || C == ']' || C == ' ' || C == ':' || - C == '+' || C == '(' || C == ')')) - Out.push_back('.'); - else - Out.push_back(C); - } +void DICompileUnit::replaceGlobalVariables(DIArray GlobalVariables) { + assert(Verify() && "Expected compile unit"); + if (GlobalVariables == getGlobalVariables()) + return; + + const_cast(DbgNode)->replaceOperandWith(5, GlobalVariables); } -/// getFnSpecificMDNode - Return a NameMDNode, if available, that is -/// suitable to hold function specific information. -NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, DISubprogram Fn) { - SmallString<32> Name; - fixupSubprogramName(Fn, Name); - return M.getNamedMetadata(Name.str()); +DILocation DILocation::copyWithNewScope(LLVMContext &Ctx, + DILexicalBlockFile NewScope) { + assert(Verify()); + assert(NewScope && "Expected valid scope"); + + const auto *Old = cast(DbgNode); + return DILocation(MDLocation::get(Ctx, Old->getLine(), Old->getColumn(), + NewScope, Old->getInlinedAt())); } -/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable -/// to hold function specific information. -NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, DISubprogram Fn) { - SmallString<32> Name; - fixupSubprogramName(Fn, Name); - return M.getOrInsertNamedMetadata(Name.str()); +unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) { + std::pair Key(getFilename().data(), getLineNumber()); + return ++Ctx.pImpl->DiscriminatorTable[Key]; } -/// createInlinedVariable - Create a new inlined variable based on current -/// variable. -/// @param DV Current Variable. -/// @param InlinedScope Location at current variable is inlined. DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope, LLVMContext &VMContext) { - SmallVector Elts; - // Insert inlined scope as 7th element. - for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) - i == 7 ? Elts.push_back(InlinedScope) : Elts.push_back(DV->getOperand(i)); - return DIVariable(MDNode::get(VMContext, Elts)); + assert(DIVariable(DV).Verify() && "Expected a DIVariable"); + if (!InlinedScope) + return cleanseInlinedVariable(DV, VMContext); + + // Insert inlined scope. + SmallVector Elts; + for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) + Elts.push_back(DV->getOperand(I)); + Elts.push_back(InlinedScope); + + DIVariable Inlined(MDNode::get(VMContext, Elts)); + assert(Inlined.Verify() && "Expected to create a DIVariable"); + return Inlined; } -/// cleanseInlinedVariable - Remove inlined scope from the variable. DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) { - SmallVector Elts; - // Insert inlined scope as 7th element. - for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i) - i == 7 ? Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext))) - : Elts.push_back(DV->getOperand(i)); - return DIVariable(MDNode::get(VMContext, Elts)); + assert(DIVariable(DV).Verify() && "Expected a DIVariable"); + if (!DIVariable(DV).getInlinedAt()) + return DIVariable(DV); + + // Remove inlined scope. + SmallVector Elts; + for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I) + Elts.push_back(DV->getOperand(I)); + + DIVariable Cleansed(MDNode::get(VMContext, Elts)); + assert(Cleansed.Verify() && "Expected to create a DIVariable"); + return Cleansed; } -/// getDISubprogram - Find subprogram that is enclosing this scope. DISubprogram llvm::getDISubprogram(const MDNode *Scope) { DIDescriptor D(Scope); if (D.isSubprogram()) @@ -936,7 +886,23 @@ DISubprogram llvm::getDISubprogram(const MDNode *Scope) { return DISubprogram(); } -/// getDICompositeType - Find underlying composite type. +DISubprogram llvm::getDISubprogram(const Function *F) { + // We look for the first instr that has a debug annotation leading back to F. + for (auto &BB : *F) { + auto Inst = std::find_if(BB.begin(), BB.end(), [](const Instruction &Inst) { + return !Inst.getDebugLoc().isUnknown(); + }); + if (Inst == BB.end()) + continue; + DebugLoc DLoc = Inst->getDebugLoc(); + const MDNode *Scope = DLoc.getScopeNode(); + DISubprogram Subprogram = getDISubprogram(Scope); + return Subprogram.describes(F) ? Subprogram : DISubprogram(); + } + + return DISubprogram(); +} + DICompositeType llvm::getDICompositeType(DIType T) { if (T.isCompositeType()) return DICompositeType(T); @@ -953,7 +919,6 @@ DICompositeType llvm::getDICompositeType(DIType T) { return DICompositeType(); } -/// Update DITypeIdentifierMap by going through retained types of each CU. DITypeIdentifierMap llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) { DITypeIdentifierMap Map; @@ -1002,7 +967,6 @@ void DebugInfoFinder::InitializeTypeMap(const Module &M) { } } -/// processModule - Process entire module and collect debug info. void DebugInfoFinder::processModule(const Module &M) { InitializeTypeMap(M); if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) { @@ -1041,7 +1005,6 @@ void DebugInfoFinder::processModule(const Module &M) { } } -/// processLocation - Process DILocation. void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) { if (!Loc) return; @@ -1050,7 +1013,6 @@ void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) { processLocation(M, Loc.getOrigLocation()); } -/// processType - Process DIType. void DebugInfoFinder::processType(DIType DT) { if (!addType(DT)) return; @@ -1058,7 +1020,13 @@ void DebugInfoFinder::processType(DIType DT) { if (DT.isCompositeType()) { DICompositeType DCT(DT); processType(DCT.getTypeDerivedFrom().resolve(TypeIdentifierMap)); - DIArray DA = DCT.getTypeArray(); + if (DT.isSubroutineType()) { + DITypeArray DTA = DISubroutineType(DT).getTypeArray(); + for (unsigned i = 0, e = DTA.getNumElements(); i != e; ++i) + processType(DTA.getElement(i).resolve(TypeIdentifierMap)); + return; + } + DIArray DA = DCT.getElements(); for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) { DIDescriptor D = DA.getElement(i); if (D.isType()) @@ -1100,7 +1068,6 @@ void DebugInfoFinder::processScope(DIScope Scope) { } } -/// processSubprogram - Process DISubprogram. void DebugInfoFinder::processSubprogram(DISubprogram SP) { if (!addSubprogram(SP)) return; @@ -1121,7 +1088,6 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) { } } -/// processDeclare - Process DbgDeclareInst. void DebugInfoFinder::processDeclare(const Module &M, const DbgDeclareInst *DDI) { MDNode *N = dyn_cast(DDI->getVariable()); @@ -1133,7 +1099,7 @@ void DebugInfoFinder::processDeclare(const Module &M, if (!DV.isVariable()) return; - if (!NodesSeen.insert(DV)) + if (!NodesSeen.insert(DV).second) return; processScope(DIVariable(N).getContext()); processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); @@ -1149,53 +1115,49 @@ void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) { if (!DV.isVariable()) return; - if (!NodesSeen.insert(DV)) + if (!NodesSeen.insert(DV).second) return; processScope(DIVariable(N).getContext()); processType(DIVariable(N).getType().resolve(TypeIdentifierMap)); } -/// addType - Add type into Tys. bool DebugInfoFinder::addType(DIType DT) { if (!DT) return false; - if (!NodesSeen.insert(DT)) + if (!NodesSeen.insert(DT).second) return false; TYs.push_back(DT); return true; } -/// addCompileUnit - Add compile unit into CUs. bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) { if (!CU) return false; - if (!NodesSeen.insert(CU)) + if (!NodesSeen.insert(CU).second) return false; CUs.push_back(CU); return true; } -/// addGlobalVariable - Add global variable into GVs. bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) { if (!DIG) return false; - if (!NodesSeen.insert(DIG)) + if (!NodesSeen.insert(DIG).second) return false; GVs.push_back(DIG); return true; } -// addSubprogram - Add subprgoram into SPs. bool DebugInfoFinder::addSubprogram(DISubprogram SP) { if (!SP) return false; - if (!NodesSeen.insert(SP)) + if (!NodesSeen.insert(SP).second) return false; SPs.push_back(SP); @@ -1209,7 +1171,7 @@ bool DebugInfoFinder::addScope(DIScope Scope) { // as null for now. if (Scope->getNumOperands() == 0) return false; - if (!NodesSeen.insert(Scope)) + if (!NodesSeen.insert(Scope).second) return false; Scopes.push_back(Scope); return true; @@ -1219,13 +1181,11 @@ bool DebugInfoFinder::addScope(DIScope Scope) { // DIDescriptor: dump routines for all descriptors. //===----------------------------------------------------------------------===// -/// dump - Print descriptor to dbgs() with a newline. void DIDescriptor::dump() const { print(dbgs()); dbgs() << '\n'; } -/// print - Print descriptor. void DIDescriptor::print(raw_ostream &OS) const { if (!DbgNode) return; @@ -1259,6 +1219,8 @@ void DIDescriptor::print(raw_ostream &OS) const { DINameSpace(DbgNode).printInternal(OS); } else if (this->isScope()) { DIScope(DbgNode).printInternal(OS); + } else if (this->isExpression()) { + DIExpression(DbgNode).printInternal(OS); } } @@ -1311,6 +1273,8 @@ void DIType::printInternal(raw_ostream &OS) const { OS << " [private]"; else if (isProtected()) OS << " [protected]"; + else if (isPublic()) + OS << " [public]"; if (isArtificial()) OS << " [artificial]"; @@ -1341,7 +1305,7 @@ void DIDerivedType::printInternal(raw_ostream &OS) const { void DICompositeType::printInternal(raw_ostream &OS) const { DIType::printInternal(OS); - DIArray A = getTypeArray(); + DIArray A = getElements(); OS << " [" << A.getNumElements() << " elements]"; } @@ -1370,6 +1334,8 @@ void DISubprogram::printInternal(raw_ostream &OS) const { OS << " [private]"; else if (isProtected()) OS << " [protected]"; + else if (isPublic()) + OS << " [public]"; if (isLValueReference()) OS << " [reference]"; @@ -1406,6 +1372,33 @@ void DIVariable::printInternal(raw_ostream &OS) const { OS << " [line " << getLineNumber() << ']'; } +void DIExpression::printInternal(raw_ostream &OS) const { + for (unsigned I = 0; I < getNumElements(); ++I) { + uint64_t OpCode = getElement(I); + OS << " [" << OperationEncodingString(OpCode); + switch (OpCode) { + case DW_OP_plus: { + OS << " " << getElement(++I); + break; + } + case DW_OP_piece: { + unsigned Offset = getElement(++I); + unsigned Size = getElement(++I); + OS << " offset=" << Offset << ", size=" << Size; + break; + } + case DW_OP_deref: + // No arguments. + break; + default: + // Else bail out early. This may be a line table entry. + OS << "Unknown]"; + return; + } + OS << "]"; + } +} + void DIObjCProperty::printInternal(raw_ostream &OS) const { StringRef Name = getObjCPropertyName(); if (!Name.empty()) @@ -1449,30 +1442,22 @@ void DIVariable::printExtendedName(raw_ostream &OS) const { } } -/// Specialize constructor to make sure it has the correct type. -template <> DIRef::DIRef(const Value *V) : Val(V) { +template <> DIRef::DIRef(const Metadata *V) : Val(V) { assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode"); } -template <> DIRef::DIRef(const Value *V) : Val(V) { +template <> DIRef::DIRef(const Metadata *V) : Val(V) { assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode"); } -/// Specialize getFieldAs to handle fields that are references to DIScopes. template <> DIScopeRef DIDescriptor::getFieldAs(unsigned Elt) const { - return DIScopeRef(getField(DbgNode, Elt)); + return DIScopeRef(cast_or_null(getField(DbgNode, Elt))); } -/// Specialize getFieldAs to handle fields that are references to DITypes. template <> DITypeRef DIDescriptor::getFieldAs(unsigned Elt) const { - return DITypeRef(getField(DbgNode, Elt)); + return DITypeRef(cast_or_null(getField(DbgNode, Elt))); } -/// Strip debug info in the module if it exists. -/// To do this, we remove all calls to the debugger intrinsics and any named -/// metadata for debugging. We also remove debug locations for instructions. -/// Return true if module is modified. bool llvm::StripDebugInfo(Module &M) { - bool Changed = false; // Remove all of the calls to the debugger intrinsics, and remove them from @@ -1519,12 +1504,11 @@ bool llvm::StripDebugInfo(Module &M) { return Changed; } -/// Return Debug Info Metadata Version by checking module flags. unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) { - Value *Val = M.getModuleFlag("Debug Info Version"); - if (!Val) - return 0; - return cast(Val)->getZExtValue(); + if (auto *Val = mdconst::extract_or_null( + M.getModuleFlag("Debug Info Version"))) + return Val->getZExtValue(); + return 0; } llvm::DenseMap diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp index e8bdcce..075f295 100644 --- a/lib/IR/DebugLoc.cpp +++ b/lib/IR/DebugLoc.cpp @@ -17,129 +17,60 @@ using namespace llvm; // DebugLoc Implementation //===----------------------------------------------------------------------===// -MDNode *DebugLoc::getScope(const LLVMContext &Ctx) const { - if (ScopeIdx == 0) return nullptr; - - if (ScopeIdx > 0) { - // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at - // position specified. - assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() && - "Invalid ScopeIdx!"); - return Ctx.pImpl->ScopeRecords[ScopeIdx-1].get(); - } - - // Otherwise, the index is in the ScopeInlinedAtRecords array. - assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() && - "Invalid ScopeIdx"); - return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get(); -} +unsigned DebugLoc::getLine() const { return DILocation(Loc).getLineNumber(); } +unsigned DebugLoc::getCol() const { return DILocation(Loc).getColumnNumber(); } + +MDNode *DebugLoc::getScope() const { return DILocation(Loc).getScope(); } -MDNode *DebugLoc::getInlinedAt(const LLVMContext &Ctx) const { - // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at - // position specified. Zero is invalid. - if (ScopeIdx >= 0) return nullptr; - - // Otherwise, the index is in the ScopeInlinedAtRecords array. - assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() && - "Invalid ScopeIdx"); - return Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get(); +MDNode *DebugLoc::getInlinedAt() const { + return DILocation(Loc).getOrigLocation(); } /// Return both the Scope and the InlinedAt values. -void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &Ctx) const { - if (ScopeIdx == 0) { - Scope = IA = nullptr; - return; - } - - if (ScopeIdx > 0) { - // Positive ScopeIdx is an index into ScopeRecords, which has no inlined-at - // position specified. - assert(unsigned(ScopeIdx) <= Ctx.pImpl->ScopeRecords.size() && - "Invalid ScopeIdx!"); - Scope = Ctx.pImpl->ScopeRecords[ScopeIdx-1].get(); - IA = nullptr; - return; - } - - // Otherwise, the index is in the ScopeInlinedAtRecords array. - assert(unsigned(-ScopeIdx) <= Ctx.pImpl->ScopeInlinedAtRecords.size() && - "Invalid ScopeIdx"); - Scope = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].first.get(); - IA = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get(); +void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const { + Scope = getScope(); + IA = getInlinedAt(); } -MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const { - if (MDNode *InlinedAt = getInlinedAt(Ctx)) - return DebugLoc::getFromDILocation(InlinedAt).getScopeNode(Ctx); - return getScope(Ctx); +MDNode *DebugLoc::getScopeNode() const { + if (MDNode *InlinedAt = getInlinedAt()) + return DebugLoc::getFromDILocation(InlinedAt).getScopeNode(); + return getScope(); } -DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) const { - const MDNode *Scope = getScopeNode(Ctx); +DebugLoc DebugLoc::getFnDebugLoc() const { + const MDNode *Scope = getScopeNode(); DISubprogram SP = getDISubprogram(Scope); - if (SP.isSubprogram()) { - // Check for number of operands since the compatibility is - // cheap here. FIXME: Name the magic constant. - if (SP->getNumOperands() > 19) - return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); - else - return DebugLoc::get(SP.getLineNumber(), 0, SP); - } + if (SP.isSubprogram()) + return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); return DebugLoc(); } DebugLoc DebugLoc::get(unsigned Line, unsigned Col, MDNode *Scope, MDNode *InlinedAt) { - DebugLoc Result; - // If no scope is available, this is an unknown location. - if (!Scope) return Result; + if (!Scope) + return DebugLoc(); // Saturate line and col to "unknown". + // FIXME: Allow 16-bits for columns. if (Col > 255) Col = 0; if (Line >= (1 << 24)) Line = 0; - Result.LineCol = Line | (Col << 24); - - LLVMContext &Ctx = Scope->getContext(); - - // If there is no inlined-at location, use the ScopeRecords array. - if (!InlinedAt) - Result.ScopeIdx = Ctx.pImpl->getOrAddScopeRecordIdxEntry(Scope, 0); - else - Result.ScopeIdx = Ctx.pImpl->getOrAddScopeInlinedAtIdxEntry(Scope, - InlinedAt, 0); - return Result; + return getFromDILocation( + MDLocation::get(Scope->getContext(), Line, Col, Scope, InlinedAt)); } /// getAsMDNode - This method converts the compressed DebugLoc node into a /// DILocation-compatible MDNode. -MDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const { - if (isUnknown()) return nullptr; - - MDNode *Scope, *IA; - getScopeAndInlinedAt(Scope, IA, Ctx); - assert(Scope && "If scope is null, this should be isUnknown()"); - - LLVMContext &Ctx2 = Scope->getContext(); - Type *Int32 = Type::getInt32Ty(Ctx2); - Value *Elts[] = { - ConstantInt::get(Int32, getLine()), ConstantInt::get(Int32, getCol()), - Scope, IA - }; - return MDNode::get(Ctx2, Elts); -} +MDNode *DebugLoc::getAsMDNode() const { return Loc; } /// getFromDILocation - Translate the DILocation quad into a DebugLoc. DebugLoc DebugLoc::getFromDILocation(MDNode *N) { - DILocation Loc(N); - MDNode *Scope = Loc.getScope(); - if (!Scope) return DebugLoc(); - return get(Loc.getLineNumber(), Loc.getColumnNumber(), Scope, - Loc.getOrigLocation()); + DebugLoc Loc; + Loc.Loc.reset(N); + return Loc; } /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. @@ -151,26 +82,26 @@ DebugLoc DebugLoc::getFromDILexicalBlock(MDNode *N) { nullptr); } -void DebugLoc::dump(const LLVMContext &Ctx) const { +void DebugLoc::dump() const { #ifndef NDEBUG if (!isUnknown()) { dbgs() << getLine(); if (getCol() != 0) dbgs() << ',' << getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx)); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt()); if (!InlinedAtDL.isUnknown()) { dbgs() << " @ "; - InlinedAtDL.dump(Ctx); + InlinedAtDL.dump(); } else dbgs() << "\n"; } #endif } -void DebugLoc::print(const LLVMContext &Ctx, raw_ostream &OS) const { +void DebugLoc::print(raw_ostream &OS) const { if (!isUnknown()) { // Print source line info. - DIScope Scope(getScope(Ctx)); + DIScope Scope(getScope()); assert((!Scope || Scope.isScope()) && "Scope of a DebugLoc should be null or a DIScope."); if (Scope) @@ -180,179 +111,11 @@ void DebugLoc::print(const LLVMContext &Ctx, raw_ostream &OS) const { OS << ':' << getLine(); if (getCol() != 0) OS << ':' << getCol(); - DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt(Ctx)); + DebugLoc InlinedAtDL = DebugLoc::getFromDILocation(getInlinedAt()); if (!InlinedAtDL.isUnknown()) { OS << " @[ "; - InlinedAtDL.print(Ctx, OS); + InlinedAtDL.print(OS); OS << " ]"; } } } - -//===----------------------------------------------------------------------===// -// DenseMap specialization -//===----------------------------------------------------------------------===// - -unsigned DenseMapInfo::getHashValue(const DebugLoc &Key) { - return static_cast(hash_combine(Key.LineCol, Key.ScopeIdx)); -} - -//===----------------------------------------------------------------------===// -// LLVMContextImpl Implementation -//===----------------------------------------------------------------------===// - -int LLVMContextImpl::getOrAddScopeRecordIdxEntry(MDNode *Scope, - int ExistingIdx) { - // If we already have an entry for this scope, return it. - int &Idx = ScopeRecordIdx[Scope]; - if (Idx) return Idx; - - // If we don't have an entry, but ExistingIdx is specified, use it. - if (ExistingIdx) - return Idx = ExistingIdx; - - // Otherwise add a new entry. - - // Start out ScopeRecords with a minimal reasonable size to avoid - // excessive reallocation starting out. - if (ScopeRecords.empty()) - ScopeRecords.reserve(128); - - // Index is biased by 1 for index. - Idx = ScopeRecords.size()+1; - ScopeRecords.push_back(DebugRecVH(Scope, this, Idx)); - return Idx; -} - -int LLVMContextImpl::getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA, - int ExistingIdx) { - // If we already have an entry, return it. - int &Idx = ScopeInlinedAtIdx[std::make_pair(Scope, IA)]; - if (Idx) return Idx; - - // If we don't have an entry, but ExistingIdx is specified, use it. - if (ExistingIdx) - return Idx = ExistingIdx; - - // Start out ScopeInlinedAtRecords with a minimal reasonable size to avoid - // excessive reallocation starting out. - if (ScopeInlinedAtRecords.empty()) - ScopeInlinedAtRecords.reserve(128); - - // Index is biased by 1 and negated. - Idx = -ScopeInlinedAtRecords.size()-1; - ScopeInlinedAtRecords.push_back(std::make_pair(DebugRecVH(Scope, this, Idx), - DebugRecVH(IA, this, Idx))); - return Idx; -} - - -//===----------------------------------------------------------------------===// -// DebugRecVH Implementation -//===----------------------------------------------------------------------===// - -/// deleted - The MDNode this is pointing to got deleted, so this pointer needs -/// to drop to null and we need remove our entry from the DenseMap. -void DebugRecVH::deleted() { - // If this is a non-canonical reference, just drop the value to null, we know - // it doesn't have a map entry. - if (Idx == 0) { - setValPtr(nullptr); - return; - } - - MDNode *Cur = get(); - - // If the index is positive, it is an entry in ScopeRecords. - if (Idx > 0) { - assert(Ctx->ScopeRecordIdx[Cur] == Idx && "Mapping out of date!"); - Ctx->ScopeRecordIdx.erase(Cur); - // Reset this VH to null and we're done. - setValPtr(nullptr); - Idx = 0; - return; - } - - // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it - // is the scope or the inlined-at record entry. - assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size()); - std::pair &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1]; - assert((this == &Entry.first || this == &Entry.second) && - "Mapping out of date!"); - - MDNode *OldScope = Entry.first.get(); - MDNode *OldInlinedAt = Entry.second.get(); - assert(OldScope && OldInlinedAt && - "Entry should be non-canonical if either val dropped to null"); - - // Otherwise, we do have an entry in it, nuke it and we're done. - assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&& - "Mapping out of date"); - Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt)); - - // Reset this VH to null. Drop both 'Idx' values to null to indicate that - // we're in non-canonical form now. - setValPtr(nullptr); - Entry.first.Idx = Entry.second.Idx = 0; -} - -void DebugRecVH::allUsesReplacedWith(Value *NewVa) { - // If being replaced with a non-mdnode value (e.g. undef) handle this as if - // the mdnode got deleted. - MDNode *NewVal = dyn_cast(NewVa); - if (!NewVal) return deleted(); - - // If this is a non-canonical reference, just change it, we know it already - // doesn't have a map entry. - if (Idx == 0) { - setValPtr(NewVa); - return; - } - - MDNode *OldVal = get(); - assert(OldVal != NewVa && "Node replaced with self?"); - - // If the index is positive, it is an entry in ScopeRecords. - if (Idx > 0) { - assert(Ctx->ScopeRecordIdx[OldVal] == Idx && "Mapping out of date!"); - Ctx->ScopeRecordIdx.erase(OldVal); - setValPtr(NewVal); - - int NewEntry = Ctx->getOrAddScopeRecordIdxEntry(NewVal, Idx); - - // If NewVal already has an entry, this becomes a non-canonical reference, - // just drop Idx to 0 to signify this. - if (NewEntry != Idx) - Idx = 0; - return; - } - - // Otherwise, it is an entry in ScopeInlinedAtRecords, we don't know if it - // is the scope or the inlined-at record entry. - assert(unsigned(-Idx-1) < Ctx->ScopeInlinedAtRecords.size()); - std::pair &Entry = Ctx->ScopeInlinedAtRecords[-Idx-1]; - assert((this == &Entry.first || this == &Entry.second) && - "Mapping out of date!"); - - MDNode *OldScope = Entry.first.get(); - MDNode *OldInlinedAt = Entry.second.get(); - assert(OldScope && OldInlinedAt && - "Entry should be non-canonical if either val dropped to null"); - - // Otherwise, we do have an entry in it, nuke it and we're done. - assert(Ctx->ScopeInlinedAtIdx[std::make_pair(OldScope, OldInlinedAt)] == Idx&& - "Mapping out of date"); - Ctx->ScopeInlinedAtIdx.erase(std::make_pair(OldScope, OldInlinedAt)); - - // Reset this VH to the new value. - setValPtr(NewVal); - - int NewIdx = Ctx->getOrAddScopeInlinedAtIdxEntry(Entry.first.get(), - Entry.second.get(), Idx); - // If NewVal already has an entry, this becomes a non-canonical reference, - // just drop Idx to 0 to signify this. - if (NewIdx != Idx) { - std::pair &Entry=Ctx->ScopeInlinedAtRecords[-Idx-1]; - Entry.first.Idx = Entry.second.Idx = 0; - } -} diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index 37cce2b..cfb699a 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -98,7 +98,8 @@ DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I, Instr(&I) { if (const MDNode *SrcLoc = I.getMetadata("srcloc")) { if (SrcLoc->getNumOperands() != 0) - if (const ConstantInt *CI = dyn_cast(SrcLoc->getOperand(0))) + if (const auto *CI = + mdconst::dyn_extract(SrcLoc->getOperand(0))) LocCookie = CI->getZExtValue(); } } diff --git a/lib/IR/DiagnosticPrinter.cpp b/lib/IR/DiagnosticPrinter.cpp index 5e16026..f25fc20 100644 --- a/lib/IR/DiagnosticPrinter.cpp +++ b/lib/IR/DiagnosticPrinter.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the a diagnostic printer relying on raw_ostream. +// This file defines a diagnostic printer relying on raw_ostream. // //===----------------------------------------------------------------------===// diff --git a/lib/IR/Dominators.cpp b/lib/IR/Dominators.cpp index d6649d6..9b6ff1e 100644 --- a/lib/IR/Dominators.cpp +++ b/lib/IR/Dominators.cpp @@ -20,6 +20,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/PassManager.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" @@ -298,10 +299,45 @@ void DominatorTree::verifyDomTree() const { } //===----------------------------------------------------------------------===// +// DominatorTreeAnalysis and related pass implementations +//===----------------------------------------------------------------------===// +// +// This implements the DominatorTreeAnalysis which is used with the new pass +// manager. It also implements some methods from utility passes. +// +//===----------------------------------------------------------------------===// + +DominatorTree DominatorTreeAnalysis::run(Function &F) { + DominatorTree DT; + DT.recalculate(F); + return DT; +} + +char DominatorTreeAnalysis::PassID; + +DominatorTreePrinterPass::DominatorTreePrinterPass(raw_ostream &OS) : OS(OS) {} + +PreservedAnalyses DominatorTreePrinterPass::run(Function &F, + FunctionAnalysisManager *AM) { + OS << "DominatorTree for function: " << F.getName() << "\n"; + AM->getResult(F).print(OS); + + return PreservedAnalyses::all(); +} + +PreservedAnalyses DominatorTreeVerifierPass::run(Function &F, + FunctionAnalysisManager *AM) { + AM->getResult(F).verifyDomTree(); + + return PreservedAnalyses::all(); +} + +//===----------------------------------------------------------------------===// // DominatorTreeWrapperPass Implementation //===----------------------------------------------------------------------===// // -// The implementation details of the wrapper pass that holds a DominatorTree. +// The implementation details of the wrapper pass that holds a DominatorTree +// suitable for use with the legacy pass manager. // //===----------------------------------------------------------------------===// diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index de59b26..bfd0ca6 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -23,7 +23,6 @@ #include "llvm/IR/InstIterator.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/RWMutex.h" @@ -46,20 +45,13 @@ Argument::Argument(Type *Ty, const Twine &Name, Function *Par) : Value(Ty, Value::ArgumentVal) { Parent = nullptr; - // Make sure that we get added to a function - LeakDetector::addGarbageObject(this); - if (Par) Par->getArgumentList().push_back(this); setName(Name); } void Argument::setParent(Function *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } /// getArgNo - Return the index of this formal argument in its containing @@ -166,6 +158,20 @@ bool Argument::hasReturnedAttr() const { hasAttribute(getArgNo()+1, Attribute::Returned); } +/// hasZExtAttr - Return true if this argument has the zext attribute on it in +/// its containing function. +bool Argument::hasZExtAttr() const { + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::ZExt); +} + +/// hasSExtAttr Return true if this argument has the sext attribute on it in its +/// containing function. +bool Argument::hasSExtAttr() const { + return getParent()->getAttributes(). + hasAttribute(getArgNo()+1, Attribute::SExt); +} + /// Return true if this argument has the readonly or readnone attribute on it /// in its containing function. bool Argument::onlyReadsMemory() const { @@ -199,6 +205,12 @@ void Argument::removeAttr(AttributeSet AS) { // Helper Methods in Function //===----------------------------------------------------------------------===// +bool Function::isMaterializable() const { + return getGlobalObjectSubClassData(); +} + +void Function::setIsMaterializable(bool V) { setGlobalObjectSubClassData(V); } + LLVMContext &Function::getContext() const { return getType()->getContext(); } @@ -227,21 +239,19 @@ void Function::eraseFromParent() { // Function Implementation //===----------------------------------------------------------------------===// -Function::Function(FunctionType *Ty, LinkageTypes Linkage, - const Twine &name, Module *ParentModule) - : GlobalObject(PointerType::getUnqual(Ty), - Value::FunctionVal, nullptr, 0, Linkage, name) { +Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name, + Module *ParentModule) + : GlobalObject(PointerType::getUnqual(Ty), Value::FunctionVal, nullptr, 0, + Linkage, name) { assert(FunctionType::isValidReturnType(getReturnType()) && "invalid return type"); + setIsMaterializable(false); SymTab = new ValueSymbolTable(); // If the function has arguments, mark them as lazily built. if (Ty->getNumParams()) setValueSubclassData(1); // Set the "has lazy arguments" bit. - // Make sure that we get added to a function - LeakDetector::addGarbageObject(this); - if (ParentModule) ParentModule->getFunctionList().push_back(this); @@ -277,7 +287,7 @@ void Function::BuildLazyArguments() const { // Clear the lazy arguments bit. unsigned SDC = getSubclassDataFromValue(); - const_cast(this)->setValueSubclassData(SDC &= ~1); + const_cast(this)->setValueSubclassData(SDC &= ~(1<<0)); } size_t Function::arg_size() const { @@ -288,11 +298,7 @@ bool Function::arg_empty() const { } void Function::setParent(Module *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } // dropAllReferences() - This function causes all the subinstructions to "let @@ -304,6 +310,8 @@ void Function::setParent(Module *parent) { // delete. // void Function::dropAllReferences() { + setIsMaterializable(false); + for (iterator I = begin(), E = end(); I != E; ++I) I->dropAllReferences(); @@ -312,8 +320,9 @@ void Function::dropAllReferences() { while (!BasicBlocks.empty()) BasicBlocks.begin()->eraseFromParent(); - // Prefix data is stored in a side table. + // Prefix and prologue data are stored in a side table. setPrefixData(nullptr); + setPrologueData(nullptr); } void Function::addAttribute(unsigned i, Attribute::AttrKind attr) { @@ -393,6 +402,10 @@ void Function::copyAttributesFrom(const GlobalValue *Src) { setPrefixData(SrcF->getPrefixData()); else setPrefixData(nullptr); + if (SrcF->hasPrologueData()) + setPrologueData(SrcF->getPrologueData()); + else + setPrologueData(nullptr); } /// getIntrinsicID - This method returns the ID number of the specified @@ -432,6 +445,42 @@ unsigned Function::lookupIntrinsicID() const { return 0; } +/// Returns a stable mangling for the type specified for use in the name +/// mangling scheme used by 'any' types in intrinsic signatures. The mangling +/// of named types is simply their name. Manglings for unnamed types consist +/// of a prefix ('p' for pointers, 'a' for arrays, 'f_' for functions) +/// combined with the mangling of their component types. A vararg function +/// type will have a suffix of 'vararg'. Since function types can contain +/// other function types, we close a function type mangling with suffix 'f' +/// which can't be confused with it's prefix. This ensures we don't have +/// collisions between two unrelated function types. Otherwise, you might +/// parse ffXX as f(fXX) or f(fX)X. (X is a placeholder for any other type.) +static std::string getMangledTypeStr(Type* Ty) { + std::string Result; + if (PointerType* PTyp = dyn_cast(Ty)) { + Result += "p" + llvm::utostr(PTyp->getAddressSpace()) + + getMangledTypeStr(PTyp->getElementType()); + } else if (ArrayType* ATyp = dyn_cast(Ty)) { + Result += "a" + llvm::utostr(ATyp->getNumElements()) + + getMangledTypeStr(ATyp->getElementType()); + } else if (StructType* STyp = dyn_cast(Ty)) { + if (!STyp->isLiteral()) + Result += STyp->getName(); + else + llvm_unreachable("TODO: implement literal types"); + } else if (FunctionType* FT = dyn_cast(Ty)) { + Result += "f_" + getMangledTypeStr(FT->getReturnType()); + for (size_t i = 0; i < FT->getNumParams(); i++) + Result += getMangledTypeStr(FT->getParamType(i)); + if (FT->isVarArg()) + Result += "vararg"; + // Ensure nested function types are distinguishable. + Result += "f"; + } else if (Ty) + Result += EVT::getEVT(Ty).getEVTString(); + return Result; +} + std::string Intrinsic::getName(ID id, ArrayRef Tys) { assert(id < num_intrinsics && "Invalid intrinsic ID!"); static const char * const Table[] = { @@ -444,12 +493,7 @@ std::string Intrinsic::getName(ID id, ArrayRef Tys) { return Table[id]; std::string Result(Table[id]); for (unsigned i = 0; i < Tys.size(); ++i) { - if (PointerType* PTyp = dyn_cast(Tys[i])) { - Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) + - EVT::getEVT(PTyp->getElementType()).getEVTString(); - } - else if (Tys[i]) - Result += "." + EVT::getEVT(Tys[i]).getEVTString(); + Result += "." + getMangledTypeStr(Tys[i]); } return Result; } @@ -479,19 +523,22 @@ enum IIT_Info { IIT_ARG = 15, // Values from 16+ are only encodable with the inefficient encoding. - IIT_MMX = 16, - IIT_METADATA = 17, - IIT_EMPTYSTRUCT = 18, - IIT_STRUCT2 = 19, - IIT_STRUCT3 = 20, - IIT_STRUCT4 = 21, - IIT_STRUCT5 = 22, - IIT_EXTEND_ARG = 23, - IIT_TRUNC_ARG = 24, - IIT_ANYPTR = 25, - IIT_V1 = 26, - IIT_VARARG = 27, - IIT_HALF_VEC_ARG = 28 + IIT_V64 = 16, + IIT_MMX = 17, + IIT_METADATA = 18, + IIT_EMPTYSTRUCT = 19, + IIT_STRUCT2 = 20, + IIT_STRUCT3 = 21, + IIT_STRUCT4 = 22, + IIT_STRUCT5 = 23, + IIT_EXTEND_ARG = 24, + IIT_TRUNC_ARG = 25, + IIT_ANYPTR = 26, + IIT_V1 = 27, + IIT_VARARG = 28, + IIT_HALF_VEC_ARG = 29, + IIT_SAME_VEC_WIDTH_ARG = 30, + IIT_PTR_TO_ARG = 31 }; @@ -562,6 +609,10 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 32)); DecodeIITType(NextElt, Infos, OutputTable); return; + case IIT_V64: + OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 64)); + DecodeIITType(NextElt, Infos, OutputTable); + return; case IIT_PTR: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0)); DecodeIITType(NextElt, Infos, OutputTable); @@ -595,6 +646,18 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef Infos, ArgInfo)); return; } + case IIT_SAME_VEC_WIDTH_ARG: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::SameVecWidthArgument, + ArgInfo)); + return; + } + case IIT_PTR_TO_ARG: { + unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]); + OutputTable.push_back(IITDescriptor::get(IITDescriptor::PtrToArgument, + ArgInfo)); + return; + } case IIT_EMPTYSTRUCT: OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0)); return; @@ -678,7 +741,7 @@ static Type *DecodeFixedType(ArrayRef &Infos, assert(D.Struct_NumElements <= 5 && "Can't handle this yet"); for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) Elts[i] = DecodeFixedType(Infos, Tys, Context); - return StructType::get(Context, ArrayRef(Elts,D.Struct_NumElements)); + return StructType::get(Context, makeArrayRef(Elts,D.Struct_NumElements)); } case IITDescriptor::Argument: @@ -702,7 +765,19 @@ static Type *DecodeFixedType(ArrayRef &Infos, case IITDescriptor::HalfVecArgument: return VectorType::getHalfElementsVectorType(cast( Tys[D.getArgumentNumber()])); + case IITDescriptor::SameVecWidthArgument: { + Type *EltTy = DecodeFixedType(Infos, Tys, Context); + Type *Ty = Tys[D.getArgumentNumber()]; + if (VectorType *VTy = dyn_cast(Ty)) { + return VectorType::get(EltTy, VTy->getNumElements()); + } + llvm_unreachable("unhandled"); + } + case IITDescriptor::PtrToArgument: { + Type *Ty = Tys[D.getArgumentNumber()]; + return PointerType::getUnqual(Ty); } + } llvm_unreachable("unhandled"); } @@ -720,6 +795,12 @@ FunctionType *Intrinsic::getType(LLVMContext &Context, while (!TableRef.empty()) ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context)); + // DecodeFixedType returns Void for IITDescriptor::Void and IITDescriptor::VarArg + // If we see void type as the type of the last argument, it is vararg intrinsic + if (!ArgTys.empty() && ArgTys.back()->isVoidTy()) { + ArgTys.pop_back(); + return FunctionType::get(ResultTy, ArgTys, true); + } return FunctionType::get(ResultTy, ArgTys, false); } @@ -815,11 +896,40 @@ void Function::setPrefixData(Constant *PrefixData) { PDHolder->setOperand(0, PrefixData); else PDHolder = ReturnInst::Create(getContext(), PrefixData); - SCData |= 2; + SCData |= (1<<1); } else { delete PDHolder; PDMap.erase(this); - SCData &= ~2; + SCData &= ~(1<<1); } setValueSubclassData(SCData); } + +Constant *Function::getPrologueData() const { + assert(hasPrologueData()); + const LLVMContextImpl::PrologueDataMapTy &SOMap = + getContext().pImpl->PrologueDataMap; + assert(SOMap.find(this) != SOMap.end()); + return cast(SOMap.find(this)->second->getReturnValue()); +} + +void Function::setPrologueData(Constant *PrologueData) { + if (!PrologueData && !hasPrologueData()) + return; + + unsigned PDData = getSubclassDataFromValue(); + LLVMContextImpl::PrologueDataMapTy &PDMap = getContext().pImpl->PrologueDataMap; + ReturnInst *&PDHolder = PDMap[this]; + if (PrologueData) { + if (PDHolder) + PDHolder->setOperand(0, PrologueData); + else + PDHolder = ReturnInst::Create(getContext(), PrologueData); + PDData |= (1<<2); + } else { + delete PDHolder; + PDMap.erase(this); + PDData &= ~(1<<2); + } + setValueSubclassData(PDData); +} diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp index 1667401..245c500 100644 --- a/lib/IR/GCOV.cpp +++ b/lib/IR/GCOV.cpp @@ -298,7 +298,8 @@ uint64_t GCOVFunction::getExitCount() const { /// dump - Dump GCOVFunction content to dbgs() for debugging purposes. void GCOVFunction::dump() const { - dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n"; + dbgs() << "===== " << Name << " (" << Ident << ") @ " << Filename << ":" + << LineNumber << "\n"; for (const auto &Block : Blocks) Block->dump(); } @@ -517,11 +518,11 @@ FileInfo::openCoveragePath(StringRef CoveragePath) { if (Options.NoOutput) return llvm::make_unique(); - std::string ErrorInfo; - auto OS = llvm::make_unique(CoveragePath.str().c_str(), - ErrorInfo, sys::fs::F_Text); - if (!ErrorInfo.empty()) { - errs() << ErrorInfo << "\n"; + std::error_code EC; + auto OS = llvm::make_unique(CoveragePath.str(), EC, + sys::fs::F_Text); + if (EC) { + errs() << EC.message() << "\n"; return llvm::make_unique(); } return std::move(OS); diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index 244e3e4..54197d9 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -18,7 +18,6 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/Support/ErrorHandling.h" @@ -29,13 +28,15 @@ using namespace llvm; //===----------------------------------------------------------------------===// bool GlobalValue::isMaterializable() const { - return getParent() && getParent()->isMaterializable(this); + if (const Function *F = dyn_cast(this)) + return F->isMaterializable(); + return false; } bool GlobalValue::isDematerializable() const { return getParent() && getParent()->isDematerializable(this); } -bool GlobalValue::Materialize(std::string *ErrInfo) { - return getParent()->Materialize(this, ErrInfo); +std::error_code GlobalValue::materialize() { + return getParent()->materialize(this); } void GlobalValue::Dematerialize() { getParent()->Dematerialize(this); @@ -77,10 +78,24 @@ void GlobalObject::setAlignment(unsigned Align) { assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); assert(Align <= MaximumAlignment && "Alignment is greater than MaximumAlignment!"); - setGlobalValueSubClassData(Log2_32(Align) + 1); + unsigned AlignmentData = Log2_32(Align) + 1; + unsigned OldData = getGlobalValueSubClassData(); + setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData); assert(getAlignment() == Align && "Alignment representation error!"); } +unsigned GlobalObject::getGlobalObjectSubClassData() const { + unsigned ValueData = getGlobalValueSubClassData(); + return ValueData >> AlignmentBits; +} + +void GlobalObject::setGlobalObjectSubClassData(unsigned Val) { + unsigned OldData = getGlobalValueSubClassData(); + setGlobalValueSubClassData((OldData & AlignmentMask) | + (Val << AlignmentBits)); + assert(getGlobalObjectSubClassData() == Val && "representation error"); +} + void GlobalObject::copyAttributesFrom(const GlobalValue *Src) { const auto *GV = cast(Src); GlobalValue::copyAttributesFrom(GV); @@ -117,7 +132,7 @@ bool GlobalValue::isDeclaration() const { // Functions are definitions if they have a body. if (const Function *F = dyn_cast(this)) - return F->empty(); + return F->empty() && !F->isMaterializable(); // Aliases are always definitions. assert(isa(this)); @@ -143,8 +158,6 @@ GlobalVariable::GlobalVariable(Type *Ty, bool constant, LinkageTypes Link, "Initializer should be the same type as the GlobalVariable!"); Op<0>() = InitVal; } - - LeakDetector::addGarbageObject(this); } GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, @@ -164,8 +177,6 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, Op<0>() = InitVal; } - LeakDetector::addGarbageObject(this); - if (Before) Before->getParent()->getGlobalList().insert(Before, this); else @@ -173,11 +184,7 @@ GlobalVariable::GlobalVariable(Module &M, Type *Ty, bool constant, } void GlobalVariable::setParent(Module *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } void GlobalVariable::removeFromParent() { @@ -230,6 +237,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) { GlobalObject::copyAttributesFrom(Src); const GlobalVariable *SrcVar = cast(Src); setThreadLocalMode(SrcVar->getThreadLocalMode()); + setExternallyInitialized(SrcVar->isExternallyInitialized()); } @@ -242,7 +250,6 @@ GlobalAlias::GlobalAlias(Type *Ty, unsigned AddressSpace, LinkageTypes Link, Module *ParentModule) : GlobalValue(PointerType::get(Ty, AddressSpace), Value::GlobalAliasVal, &Op<0>(), 1, Link, Name) { - LeakDetector::addGarbageObject(this); Op<0>() = Aliasee; if (ParentModule) @@ -279,11 +286,7 @@ GlobalAlias *GlobalAlias::create(const Twine &Name, GlobalValue *Aliasee) { } void GlobalAlias::setParent(Module *parent) { - if (getParent()) - LeakDetector::addGarbageObject(this); Parent = parent; - if (getParent()) - LeakDetector::removeGarbageObject(this); } void GlobalAlias::removeFromParent() { diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index 435e54f..ef1f226 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -53,8 +53,9 @@ Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) { } static CallInst *createCallHelper(Value *Callee, ArrayRef Ops, - IRBuilderBase *Builder) { - CallInst *CI = CallInst::Create(Callee, Ops, ""); + IRBuilderBase *Builder, + const Twine& Name="") { + CallInst *CI = CallInst::Create(Callee, Ops, Name); Builder->GetInsertBlock()->getInstList().insert(Builder->GetInsertPoint(),CI); Builder->SetInstDebugLocation(CI); return CI; @@ -62,7 +63,8 @@ static CallInst *createCallHelper(Value *Callee, ArrayRef Ops, CallInst *IRBuilderBase:: CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag) { + bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, + MDNode *NoAliasTag) { Ptr = getCastedInt8PtrValue(Ptr); Value *Ops[] = { Ptr, Val, Size, getInt32(Align), getInt1(isVolatile) }; Type *Tys[] = { Ptr->getType(), Size->getType() }; @@ -74,13 +76,20 @@ CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } CallInst *IRBuilderBase:: CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag) { + bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag, + MDNode *ScopeTag, MDNode *NoAliasTag) { Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); @@ -98,13 +107,20 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, // Set the TBAA Struct info if present. if (TBAAStructTag) CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } CallInst *IRBuilderBase:: CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag) { + bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, + MDNode *NoAliasTag) { Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); @@ -118,7 +134,13 @@ CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + return CI; } @@ -151,3 +173,126 @@ CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) { Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_end); return createCallHelper(TheFn, Ops, this); } + +CallInst *IRBuilderBase::CreateAssumption(Value *Cond) { + assert(Cond->getType() == getInt1Ty() && + "an assumption condition must be of type i1"); + + Value *Ops[] = { Cond }; + Module *M = BB->getParent()->getParent(); + Value *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume); + return createCallHelper(FnAssume, Ops, this); +} + +/// Create a call to a Masked Load intrinsic. +/// Ptr - the base pointer for the load +/// Align - alignment of the source location +/// Mask - an vector of booleans which indicates what vector lanes should +/// be accessed in memory +/// PassThru - a pass-through value that is used to fill the masked-off lanes +/// of the result +/// Name - name of the result variable +CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align, + Value *Mask, Value *PassThru, + const Twine &Name) { + assert(Ptr->getType()->isPointerTy() && "Ptr must be of pointer type"); + // DataTy is the overloaded type + Type *DataTy = cast(Ptr->getType())->getElementType(); + assert(DataTy->isVectorTy() && "Ptr should point to a vector"); + if (!PassThru) + PassThru = UndefValue::get(DataTy); + Value *Ops[] = { Ptr, getInt32(Align), Mask, PassThru}; + return CreateMaskedIntrinsic(Intrinsic::masked_load, Ops, DataTy, Name); +} + +/// Create a call to a Masked Store intrinsic. +/// Val - the data to be stored, +/// Ptr - the base pointer for the store +/// Align - alignment of the destination location +/// Mask - an vector of booleans which indicates what vector lanes should +/// be accessed in memory +CallInst *IRBuilderBase::CreateMaskedStore(Value *Val, Value *Ptr, + unsigned Align, Value *Mask) { + Value *Ops[] = { Val, Ptr, getInt32(Align), Mask }; + // Type of the data to be stored - the only one overloaded type + return CreateMaskedIntrinsic(Intrinsic::masked_store, Ops, Val->getType()); +} + +/// Create a call to a Masked intrinsic, with given intrinsic Id, +/// an array of operands - Ops, and one overloaded type - DataTy +CallInst *IRBuilderBase::CreateMaskedIntrinsic(unsigned Id, + ArrayRef Ops, + Type *DataTy, + const Twine &Name) { + Module *M = BB->getParent()->getParent(); + Type *OverloadedTypes[] = { DataTy }; + Value *TheFn = Intrinsic::getDeclaration(M, (Intrinsic::ID)Id, OverloadedTypes); + return createCallHelper(TheFn, Ops, this, Name); +} + +CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine& Name) { + // Extract out the type of the callee. + PointerType *FuncPtrType = cast(ActualCallee->getType()); + assert(isa(FuncPtrType->getElementType()) && + "actual callee must be a callable value"); + + + Module *M = BB->getParent()->getParent(); + // Fill in the one generic type'd argument (the function is also vararg) + Type *ArgTypes[] = { FuncPtrType }; + Function *FnStatepoint = + Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint, + ArgTypes); + + std::vector args; + args.push_back(ActualCallee); + args.push_back(getInt32(CallArgs.size())); + args.push_back(getInt32(0 /*unused*/)); + args.insert(args.end(), CallArgs.begin(), CallArgs.end()); + args.push_back(getInt32(DeoptArgs.size())); + args.insert(args.end(), DeoptArgs.begin(), DeoptArgs.end()); + args.insert(args.end(), GCArgs.begin(), GCArgs.end()); + + return createCallHelper(FnStatepoint, args, this, Name); +} + +CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint, + Type *ResultType, + const Twine &Name) { + Intrinsic::ID ID; + if (ResultType->isIntegerTy()) { + ID = Intrinsic::experimental_gc_result_int; + } else if (ResultType->isFloatingPointTy()) { + ID = Intrinsic::experimental_gc_result_float; + } else if (ResultType->isPointerTy()) { + ID = Intrinsic::experimental_gc_result_ptr; + } else { + llvm_unreachable("unimplemented result type for gc.result"); + } + Module *M = BB->getParent()->getParent(); + Type *Types[] = {ResultType}; + Value *FnGCResult = Intrinsic::getDeclaration(M, ID, Types); + + Value *Args[] = {Statepoint}; + return createCallHelper(FnGCResult, Args, this, Name); +} + +CallInst *IRBuilderBase::CreateGCRelocate(Instruction *Statepoint, + int BaseOffset, + int DerivedOffset, + Type *ResultType, + const Twine &Name) { + Module *M = BB->getParent()->getParent(); + Type *Types[] = {ResultType}; + Value *FnGCRelocate = + Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_relocate, Types); + + Value *Args[] = {Statepoint, + getInt32(BaseOffset), + getInt32(DerivedOffset)}; + return createCallHelper(FnGCRelocate, Args, this, Name); +} diff --git a/lib/IR/IRPrintingPasses.cpp b/lib/IR/IRPrintingPasses.cpp index c8a1747..91ccfbb 100644 --- a/lib/IR/IRPrintingPasses.cpp +++ b/lib/IR/IRPrintingPasses.cpp @@ -24,8 +24,8 @@ PrintModulePass::PrintModulePass() : OS(dbgs()) {} PrintModulePass::PrintModulePass(raw_ostream &OS, const std::string &Banner) : OS(OS), Banner(Banner) {} -PreservedAnalyses PrintModulePass::run(Module *M) { - OS << Banner << *M; +PreservedAnalyses PrintModulePass::run(Module &M) { + OS << Banner << M; return PreservedAnalyses::all(); } @@ -33,8 +33,8 @@ PrintFunctionPass::PrintFunctionPass() : OS(dbgs()) {} PrintFunctionPass::PrintFunctionPass(raw_ostream &OS, const std::string &Banner) : OS(OS), Banner(Banner) {} -PreservedAnalyses PrintFunctionPass::run(Function *F) { - OS << Banner << static_cast(*F); +PreservedAnalyses PrintFunctionPass::run(Function &F) { + OS << Banner << static_cast(F); return PreservedAnalyses::all(); } @@ -50,7 +50,7 @@ public: : ModulePass(ID), P(OS, Banner) {} bool runOnModule(Module &M) override { - P.run(&M); + P.run(M); return false; } @@ -70,7 +70,7 @@ public: // This pass just prints a banner followed by the function as it's processed. bool runOnFunction(Function &F) override { - P.run(&F); + P.run(F); return false; } diff --git a/lib/IR/InlineAsm.cpp b/lib/IR/InlineAsm.cpp index a3e1da3..16d874f3 100644 --- a/lib/IR/InlineAsm.cpp +++ b/lib/IR/InlineAsm.cpp @@ -91,6 +91,10 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str, if (*I == '~') { Type = isClobber; ++I; + + // '{' must immediately follow '~'. + if (I != E && *I != '{') + return true; } else if (*I == '=') { ++I; Type = isOutput; diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp index 86421c4..92c6e9f 100644 --- a/lib/IR/Instruction.cpp +++ b/lib/IR/Instruction.cpp @@ -15,7 +15,6 @@ #include "llvm/IR/CallSite.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" @@ -24,8 +23,6 @@ using namespace llvm; Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps, Instruction *InsertBefore) : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) { - // Make sure that we get added to a basicblock - LeakDetector::addGarbageObject(this); // If requested, insert this instruction into a basic block... if (InsertBefore) { @@ -42,8 +39,6 @@ const DataLayout *Instruction::getDataLayout() const { Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) : User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(nullptr) { - // Make sure that we get added to a basicblock - LeakDetector::addGarbageObject(this); // append this instruction into the basic block assert(InsertAtEnd && "Basic block to append to may not be NULL!"); @@ -60,12 +55,6 @@ Instruction::~Instruction() { void Instruction::setParent(BasicBlock *P) { - if (getParent()) { - if (!P) LeakDetector::addGarbageObject(this); - } else { - if (P) LeakDetector::removeGarbageObject(this); - } - Parent = P; } @@ -143,6 +132,11 @@ void Instruction::setFastMathFlags(FastMathFlags FMF) { cast(this)->setFastMathFlags(FMF); } +void Instruction::copyFastMathFlags(FastMathFlags FMF) { + assert(isa(this) && "copying fast-math flag on invalid op"); + cast(this)->copyFastMathFlags(FMF); +} + /// Determine whether the unsafe-algebra flag is set. bool Instruction::hasUnsafeAlgebra() const { assert(isa(this) && "getting fast-math flag on invalid op"); @@ -175,7 +169,7 @@ bool Instruction::hasAllowReciprocal() const { /// Convenience function for getting all the fast-math flags, which must be an /// operator which supports these flags. See LangRef.html for the meaning of -/// these flats. +/// these flags. FastMathFlags Instruction::getFastMathFlags() const { assert(isa(this) && "getting fast-math flag on invalid op"); return cast(this)->getFastMathFlags(); @@ -183,7 +177,7 @@ FastMathFlags Instruction::getFastMathFlags() const { /// Copy I's fast-math flags void Instruction::copyFastMathFlags(const Instruction *I) { - setFastMathFlags(I->getFastMathFlags()); + copyFastMathFlags(I->getFastMathFlags()); } @@ -438,6 +432,21 @@ bool Instruction::mayWriteToMemory() const { } } +bool Instruction::isAtomic() const { + switch (getOpcode()) { + default: + return false; + case Instruction::AtomicCmpXchg: + case Instruction::AtomicRMW: + case Instruction::Fence: + return true; + case Instruction::Load: + return cast(this)->getOrdering() != NotAtomic; + case Instruction::Store: + return cast(this)->getOrdering() != NotAtomic; + } +} + bool Instruction::mayThrow() const { if (const CallInst *CI = dyn_cast(this)) return !CI->doesNotThrow(); @@ -528,7 +537,7 @@ Instruction *Instruction::clone() const { // Otherwise, enumerate and copy over metadata from the old instruction to the // new one. - SmallVector, 4> TheMDs; + SmallVector, 4> TheMDs; getAllMetadataOtherThanDebugLoc(TheMDs); for (const auto &MD : TheMDs) New->setMetadata(MD.first, MD.second); diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 9553252..132800e 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -364,8 +364,9 @@ bool CallInst::paramHasAttr(unsigned i, Attribute::AttrKind A) const { /// IsConstantOne - Return true only if val is constant int 1 static bool IsConstantOne(Value *val) { - assert(val && "IsConstantOne does not work with NULL val"); - return isa(val) && cast(val)->isOne(); + assert(val && "IsConstantOne does not work with nullptr val"); + const ConstantInt *CVal = dyn_cast(val); + return CVal && CVal->isOne(); } static Instruction *createMalloc(Instruction *InsertBefore, @@ -418,7 +419,7 @@ static Instruction *createMalloc(Instruction *InsertBefore, Value *MallocFunc = MallocF; if (!MallocFunc) // prototype malloc as "void *malloc(size_t)" - MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, NULL); + MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, nullptr); PointerType *AllocPtrType = PointerType::getUnqual(AllocTy); CallInst *MCall = nullptr; Instruction *Result = nullptr; @@ -491,7 +492,7 @@ static Instruction* createFree(Value* Source, Instruction *InsertBefore, Type *VoidTy = Type::getVoidTy(M->getContext()); Type *IntPtrTy = Type::getInt8PtrTy(M->getContext()); // prototype free as "void free(void*)" - Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, NULL); + Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, nullptr); CallInst* Result = nullptr; Value *PtrCast = Source; if (InsertBefore) { @@ -795,11 +796,8 @@ void BranchInst::swapSuccessors() { return; // The first operand is the name. Fetch them backwards and build a new one. - Value *Ops[] = { - ProfileData->getOperand(0), - ProfileData->getOperand(2), - ProfileData->getOperand(1) - }; + Metadata *Ops[] = {ProfileData->getOperand(0), ProfileData->getOperand(2), + ProfileData->getOperand(1)}; setMetadata(LLVMContext::MD_prof, MDNode::get(ProfileData->getContext(), Ops)); } @@ -2030,6 +2028,39 @@ bool BinaryOperator::isExact() const { return cast(this)->isExact(); } +void BinaryOperator::copyIRFlags(const Value *V) { + // Copy the wrapping flags. + if (auto *OB = dyn_cast(V)) { + setHasNoSignedWrap(OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(OB->hasNoUnsignedWrap()); + } + + // Copy the exact flag. + if (auto *PE = dyn_cast(V)) + setIsExact(PE->isExact()); + + // Copy the fast-math flags. + if (auto *FP = dyn_cast(V)) + copyFastMathFlags(FP->getFastMathFlags()); +} + +void BinaryOperator::andIRFlags(const Value *V) { + if (auto *OB = dyn_cast(V)) { + setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap()); + setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap()); + } + + if (auto *PE = dyn_cast(V)) + setIsExact(isExact() & PE->isExact()); + + if (auto *FP = dyn_cast(V)) { + FastMathFlags FM = getFastMathFlags(); + FM &= FP->getFastMathFlags(); + copyFastMathFlags(FM); + } +} + + //===----------------------------------------------------------------------===// // FPMathOperator Class //===----------------------------------------------------------------------===// @@ -2039,10 +2070,10 @@ bool BinaryOperator::isExact() const { /// default precision. float FPMathOperator::getFPAccuracy() const { const MDNode *MD = - cast(this)->getMetadata(LLVMContext::MD_fpmath); + cast(this)->getMetadata(LLVMContext::MD_fpmath); if (!MD) return 0.0; - ConstantFP *Accuracy = cast(MD->getOperand(0)); + ConstantFP *Accuracy = mdconst::extract(MD->getOperand(0)); return Accuracy->getValueAPF().convertToFloat(); } @@ -2525,6 +2556,17 @@ CastInst *CastInst::CreatePointerBitCastOrAddrSpaceCast( return Create(Instruction::BitCast, S, Ty, Name, InsertBefore); } +CastInst *CastInst::CreateBitOrPointerCast(Value *S, Type *Ty, + const Twine &Name, + Instruction *InsertBefore) { + if (S->getType()->isPointerTy() && Ty->isIntegerTy()) + return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore); + if (S->getType()->isIntegerTy() && Ty->isPointerTy()) + return Create(Instruction::IntToPtr, S, Ty, Name, InsertBefore); + + return Create(Instruction::BitCast, S, Ty, Name, InsertBefore); +} + CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty, bool isSigned, const Twine &Name, Instruction *InsertBefore) { @@ -2682,6 +2724,18 @@ bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) { return true; } +bool CastInst::isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy, + const DataLayout *DL) { + if (auto *PtrTy = dyn_cast(SrcTy)) + if (auto *IntTy = dyn_cast(DestTy)) + return DL && IntTy->getBitWidth() == DL->getPointerTypeSizeInBits(PtrTy); + if (auto *PtrTy = dyn_cast(DestTy)) + if (auto *IntTy = dyn_cast(SrcTy)) + return DL && IntTy->getBitWidth() == DL->getPointerTypeSizeInBits(PtrTy); + + return isBitCastable(SrcTy, DestTy); +} + // Provide a way to get a "cast" where the cast opcode is inferred from the // types and size of the operand. This, basically, is a parallel of the // logic in the castIsValid function below. This axiom should hold: diff --git a/lib/IR/IntrinsicInst.cpp b/lib/IR/IntrinsicInst.cpp index 5725284..b9b5a29 100644 --- a/lib/IR/IntrinsicInst.cpp +++ b/lib/IR/IntrinsicInst.cpp @@ -49,15 +49,25 @@ Value *DbgInfoIntrinsic::StripCast(Value *C) { return dyn_cast(C); } +static Value *getValueImpl(Value *Op) { + auto *MD = cast(Op)->getMetadata(); + if (auto *V = dyn_cast(MD)) + return V->getValue(); + + // When the value goes to null, it gets replaced by an empty MDNode. + assert(!cast(MD)->getNumOperands() && "Expected an empty MDNode"); + return nullptr; +} + //===----------------------------------------------------------------------===// /// DbgDeclareInst - This represents the llvm.dbg.declare instruction. /// Value *DbgDeclareInst::getAddress() const { - if (MDNode* MD = cast_or_null(getArgOperand(0))) - return MD->getOperand(0); - else + if (!getArgOperand(0)) return nullptr; + + return getValueImpl(getArgOperand(0)); } //===----------------------------------------------------------------------===// @@ -65,9 +75,7 @@ Value *DbgDeclareInst::getAddress() const { /// const Value *DbgValueInst::getValue() const { - return cast(getArgOperand(0))->getOperand(0); + return const_cast(this)->getValue(); } -Value *DbgValueInst::getValue() { - return cast(getArgOperand(0))->getOperand(0); -} +Value *DbgValueInst::getValue() { return getValueImpl(getArgOperand(0)); } diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp index de825f0..b6d95c4 100644 --- a/lib/IR/LLVMContext.cpp +++ b/lib/IR/LLVMContext.cpp @@ -66,6 +66,33 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) { unsigned InvariantLdId = getMDKindID("invariant.load"); assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted"); (void)InvariantLdId; + + // Create the 'alias.scope' metadata kind. + unsigned AliasScopeID = getMDKindID("alias.scope"); + assert(AliasScopeID == MD_alias_scope && "alias.scope kind id drifted"); + (void)AliasScopeID; + + // Create the 'noalias' metadata kind. + unsigned NoAliasID = getMDKindID("noalias"); + assert(NoAliasID == MD_noalias && "noalias kind id drifted"); + (void)NoAliasID; + + // Create the 'nontemporal' metadata kind. + unsigned NonTemporalID = getMDKindID("nontemporal"); + assert(NonTemporalID == MD_nontemporal && "nontemporal kind id drifted"); + (void)NonTemporalID; + + // Create the 'llvm.mem.parallel_loop_access' metadata kind. + unsigned MemParallelLoopAccessID = getMDKindID("llvm.mem.parallel_loop_access"); + assert(MemParallelLoopAccessID == MD_mem_parallel_loop_access && + "mem_parallel_loop_access kind id drifted"); + (void)MemParallelLoopAccessID; + + + // Create the 'nonnull' metadata kind. + unsigned NonNullID = getMDKindID("nonnull"); + assert(NonNullID == MD_nonnull && "nonnull kind id drifted"); + (void)NonNullID; } LLVMContext::~LLVMContext() { delete pImpl; } @@ -102,9 +129,11 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const { } void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler, - void *DiagnosticContext) { + void *DiagnosticContext, + bool RespectFilters) { pImpl->DiagnosticHandler = DiagnosticHandler; pImpl->DiagnosticContext = DiagnosticContext; + pImpl->RespectDiagnosticFilters = RespectFilters; } LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const { @@ -135,13 +164,7 @@ void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) { diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr)); } -void LLVMContext::diagnose(const DiagnosticInfo &DI) { - // If there is a report handler, use it. - if (pImpl->DiagnosticHandler) { - pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext); - return; - } - +static bool isDiagnosticEnabled(const DiagnosticInfo &DI) { // Optimization remarks are selective. They need to check whether the regexp // pattern, passed via one of the -pass-remarks* flags, matches the name of // the pass that is emitting the diagnostic. If there is no match, ignore the @@ -149,19 +172,32 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) { switch (DI.getKind()) { case llvm::DK_OptimizationRemark: if (!cast(DI).isEnabled()) - return; + return false; break; case llvm::DK_OptimizationRemarkMissed: if (!cast(DI).isEnabled()) - return; + return false; break; case llvm::DK_OptimizationRemarkAnalysis: if (!cast(DI).isEnabled()) - return; + return false; break; default: break; } + return true; +} + +void LLVMContext::diagnose(const DiagnosticInfo &DI) { + // If there is a report handler, use it. + if (pImpl->DiagnosticHandler) { + if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) + pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext); + return; + } + + if (!isDiagnosticEnabled(DI)) + return; // Otherwise, print the message with a prefix based on the severity. std::string MsgStorage; @@ -193,33 +229,16 @@ void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) { // Metadata Kind Uniquing //===----------------------------------------------------------------------===// -#ifndef NDEBUG -/// isValidName - Return true if Name is a valid custom metadata handler name. -static bool isValidName(StringRef MDName) { - if (MDName.empty()) - return false; - - if (!std::isalpha(static_cast(MDName[0]))) - return false; - - for (StringRef::iterator I = MDName.begin() + 1, E = MDName.end(); I != E; - ++I) { - if (!std::isalnum(static_cast(*I)) && *I != '_' && - *I != '-' && *I != '.') - return false; - } - return true; -} -#endif - /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. unsigned LLVMContext::getMDKindID(StringRef Name) const { - assert(isValidName(Name) && "Invalid MDNode name"); + assert(!std::isdigit(Name.front()) && + "Named metadata may not start with a digit"); // If this is new, assign it its ID. - return - pImpl->CustomMDKindNames.GetOrCreateValue( - Name, pImpl->CustomMDKindNames.size()).second; + return pImpl->CustomMDKindNames.insert(std::make_pair( + Name, + pImpl->CustomMDKindNames.size())) + .first->second; } /// getHandlerNames - Populate client supplied smallvector using custome diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 4c2791f..01a0e6c 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -40,6 +40,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C) InlineAsmDiagContext = nullptr; DiagnosticHandler = nullptr; DiagnosticContext = nullptr; + RespectDiagnosticFilters = false; YieldCallback = nullptr; YieldOpaqueHandle = nullptr; NamedStructTypesUniqueID = 0; @@ -71,11 +72,34 @@ LLVMContextImpl::~LLVMContextImpl() { // the container. Avoid iterators during this operation: while (!OwnedModules.empty()) delete *OwnedModules.begin(); - + + // Drop references for MDNodes. Do this before Values get deleted to avoid + // unnecessary RAUW when nodes are still unresolved. + for (auto *I : DistinctMDNodes) + I->dropAllReferences(); + for (auto *I : MDTuples) + I->dropAllReferences(); + for (auto *I : MDLocations) + I->dropAllReferences(); + + // Also drop references that come from the Value bridges. + for (auto &Pair : ValuesAsMetadata) + Pair.second->dropUsers(); + for (auto &Pair : MetadataAsValues) + Pair.second->dropUse(); + + // Destroy MDNodes. + for (UniquableMDNode *I : DistinctMDNodes) + I->deleteAsSubclass(); + for (MDTuple *I : MDTuples) + delete I; + for (MDLocation *I : MDLocations) + delete I; + // Free the constants. This is important to do here to ensure that they are // freed before the LeakDetector is torn down. std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(), - DropReferences()); + DropFirst()); std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(), DropFirst()); std::for_each(StructConstants.map_begin(), StructConstants.map_end(), @@ -119,22 +143,23 @@ LLVMContextImpl::~LLVMContextImpl() { delete &*Elem; } - // Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet - // and the NonUniquedMDNodes sets, so copy the values out first. - SmallVector MDNodes; - MDNodes.reserve(MDNodeSet.size() + NonUniquedMDNodes.size()); - for (FoldingSetIterator I = MDNodeSet.begin(), E = MDNodeSet.end(); - I != E; ++I) - MDNodes.push_back(&*I); - MDNodes.append(NonUniquedMDNodes.begin(), NonUniquedMDNodes.end()); - for (SmallVectorImpl::iterator I = MDNodes.begin(), - E = MDNodes.end(); I != E; ++I) - (*I)->destroy(); - assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() && - "Destroying all MDNodes didn't empty the Context's sets."); + // Destroy MetadataAsValues. + { + SmallVector MDVs; + MDVs.reserve(MetadataAsValues.size()); + for (auto &Pair : MetadataAsValues) + MDVs.push_back(Pair.second); + MetadataAsValues.clear(); + for (auto *V : MDVs) + delete V; + } + + // Destroy ValuesAsMetadata. + for (auto &Pair : ValuesAsMetadata) + delete Pair.second; // Destroy MDStrings. - DeleteContainerSeconds(MDStringCache); + MDStringCache.clear(); } // ConstantsContext anchors diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 808c239..6ebc567 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_LLVMCONTEXT_IMPL_H -#define LLVM_LLVMCONTEXT_IMPL_H +#ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H +#define LLVM_LIB_IR_LLVMCONTEXTIMPL_H #include "AttributeImpl.h" #include "ConstantsContext.h" @@ -22,6 +22,7 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallPtrSet.h" @@ -45,55 +46,32 @@ class Type; class Value; struct DenseMapAPIntKeyInfo { - struct KeyTy { - APInt val; - Type* type; - KeyTy(const APInt& V, Type* Ty) : val(V), type(Ty) {} - bool operator==(const KeyTy& that) const { - return type == that.type && this->val == that.val; - } - bool operator!=(const KeyTy& that) const { - return !this->operator==(that); - } - friend hash_code hash_value(const KeyTy &Key) { - return hash_combine(Key.type, Key.val); - } - }; - static inline KeyTy getEmptyKey() { return KeyTy(APInt(1,0), nullptr); } - static inline KeyTy getTombstoneKey() { return KeyTy(APInt(1,1), nullptr); } - static unsigned getHashValue(const KeyTy &Key) { + static inline APInt getEmptyKey() { + APInt V(nullptr, 0); + V.VAL = 0; + return V; + } + static inline APInt getTombstoneKey() { + APInt V(nullptr, 0); + V.VAL = 1; + return V; + } + static unsigned getHashValue(const APInt &Key) { return static_cast(hash_value(Key)); } - static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) { - return LHS == RHS; + static bool isEqual(const APInt &LHS, const APInt &RHS) { + return LHS.getBitWidth() == RHS.getBitWidth() && LHS == RHS; } }; struct DenseMapAPFloatKeyInfo { - struct KeyTy { - APFloat val; - KeyTy(const APFloat& V) : val(V){} - bool operator==(const KeyTy& that) const { - return this->val.bitwiseIsEqual(that.val); - } - bool operator!=(const KeyTy& that) const { - return !this->operator==(that); - } - friend hash_code hash_value(const KeyTy &Key) { - return hash_combine(Key.val); - } - }; - static inline KeyTy getEmptyKey() { - return KeyTy(APFloat(APFloat::Bogus,1)); - } - static inline KeyTy getTombstoneKey() { - return KeyTy(APFloat(APFloat::Bogus,2)); - } - static unsigned getHashValue(const KeyTy &Key) { + static inline APFloat getEmptyKey() { return APFloat(APFloat::Bogus, 1); } + static inline APFloat getTombstoneKey() { return APFloat(APFloat::Bogus, 2); } + static unsigned getHashValue(const APFloat &Key) { return static_cast(hash_value(Key)); } - static bool isEqual(const KeyTy &LHS, const KeyTy &RHS) { - return LHS == RHS; + static bool isEqual(const APFloat &LHS, const APFloat &RHS) { + return LHS.bitwiseIsEqual(RHS); } }; @@ -103,9 +81,8 @@ struct AnonStructTypeKeyInfo { bool isPacked; KeyTy(const ArrayRef& E, bool P) : ETypes(E), isPacked(P) {} - KeyTy(const StructType* ST) : - ETypes(ArrayRef(ST->element_begin(), ST->element_end())), - isPacked(ST->isPacked()) {} + KeyTy(const StructType *ST) + : ETypes(ST->elements()), isPacked(ST->isPacked()) {} bool operator==(const KeyTy& that) const { if (isPacked != that.isPacked) return false; @@ -148,10 +125,9 @@ struct FunctionTypeKeyInfo { bool isVarArg; KeyTy(const Type* R, const ArrayRef& P, bool V) : ReturnType(R), Params(P), isVarArg(V) {} - KeyTy(const FunctionType* FT) : - ReturnType(FT->getReturnType()), - Params(ArrayRef(FT->param_begin(), FT->param_end())), - isVarArg(FT->isVarArg()) {} + KeyTy(const FunctionType *FT) + : ReturnType(FT->getReturnType()), Params(FT->params()), + isVarArg(FT->isVarArg()) {} bool operator==(const KeyTy& that) const { if (ReturnType != that.ReturnType) return false; @@ -190,49 +166,97 @@ struct FunctionTypeKeyInfo { } }; -// Provide a FoldingSetTrait::Equals specialization for MDNode that can use a -// shortcut to avoid comparing all operands. -template<> struct FoldingSetTrait : DefaultFoldingSetTrait { - static bool Equals(const MDNode &X, const FoldingSetNodeID &ID, - unsigned IDHash, FoldingSetNodeID &TempID) { - assert(!X.isNotUniqued() && "Non-uniqued MDNode in FoldingSet?"); - // First, check if the cached hashes match. If they don't we can skip the - // expensive operand walk. - if (X.Hash != IDHash) - return false; +/// \brief DenseMapInfo for MDTuple. +/// +/// Note that we don't need the is-function-local bit, since that's implicit in +/// the operands. +struct MDTupleInfo { + struct KeyTy { + ArrayRef RawOps; + ArrayRef Ops; + unsigned Hash; + + KeyTy(ArrayRef Ops) + : RawOps(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {} + + KeyTy(MDTuple *N) + : Ops(N->op_begin(), N->op_end()), Hash(N->getHash()) {} - // If they match we have to compare the operands. - X.Profile(TempID); - return TempID == ID; + bool operator==(const MDTuple *RHS) const { + if (RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + if (Hash != RHS->getHash()) + return false; + assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?"); + return RawOps.empty() ? compareOps(Ops, RHS) : compareOps(RawOps, RHS); + } + template + static bool compareOps(ArrayRef Ops, const MDTuple *RHS) { + if (Ops.size() != RHS->getNumOperands()) + return false; + return std::equal(Ops.begin(), Ops.end(), RHS->op_begin()); + } + }; + static inline MDTuple *getEmptyKey() { + return DenseMapInfo::getEmptyKey(); + } + static inline MDTuple *getTombstoneKey() { + return DenseMapInfo::getTombstoneKey(); } - static unsigned ComputeHash(const MDNode &X, FoldingSetNodeID &) { - return X.Hash; // Return cached hash. + static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; } + static unsigned getHashValue(const MDTuple *U) { + return U->getHash(); + } + static bool isEqual(const KeyTy &LHS, const MDTuple *RHS) { + return LHS == RHS; + } + static bool isEqual(const MDTuple *LHS, const MDTuple *RHS) { + return LHS == RHS; } }; -/// DebugRecVH - This is a CallbackVH used to keep the Scope -> index maps -/// up to date as MDNodes mutate. This class is implemented in DebugLoc.cpp. -class DebugRecVH : public CallbackVH { - /// Ctx - This is the LLVM Context being referenced. - LLVMContextImpl *Ctx; - - /// Idx - The index into either ScopeRecordIdx or ScopeInlinedAtRecords that - /// this reference lives in. If this is zero, then it represents a - /// non-canonical entry that has no DenseMap value. This can happen due to - /// RAUW. - int Idx; -public: - DebugRecVH(MDNode *n, LLVMContextImpl *ctx, int idx) - : CallbackVH(n), Ctx(ctx), Idx(idx) {} - - MDNode *get() const { - return cast_or_null(getValPtr()); - } +/// \brief DenseMapInfo for MDLocation. +struct MDLocationInfo { + struct KeyTy { + unsigned Line; + unsigned Column; + Metadata *Scope; + Metadata *InlinedAt; - void deleted() override; - void allUsesReplacedWith(Value *VNew) override; + KeyTy(unsigned Line, unsigned Column, Metadata *Scope, Metadata *InlinedAt) + : Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt) {} + + KeyTy(const MDLocation *L) + : Line(L->getLine()), Column(L->getColumn()), Scope(L->getScope()), + InlinedAt(L->getInlinedAt()) {} + + bool operator==(const MDLocation *RHS) const { + if (RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + return Line == RHS->getLine() && Column == RHS->getColumn() && + Scope == RHS->getScope() && InlinedAt == RHS->getInlinedAt(); + } + }; + static inline MDLocation *getEmptyKey() { + return DenseMapInfo::getEmptyKey(); + } + static inline MDLocation *getTombstoneKey() { + return DenseMapInfo::getTombstoneKey(); + } + static unsigned getHashValue(const KeyTy &Key) { + return hash_combine(Key.Line, Key.Column, Key.Scope, Key.InlinedAt); + } + static unsigned getHashValue(const MDLocation *U) { + return getHashValue(KeyTy(U)); + } + static bool isEqual(const KeyTy &LHS, const MDLocation *RHS) { + return LHS == RHS; + } + static bool isEqual(const MDLocation *LHS, const MDLocation *RHS) { + return LHS == RHS; + } }; - + class LLVMContextImpl { public: /// OwnedModules - The set of modules instantiated in this context, and which @@ -244,41 +268,43 @@ public: LLVMContext::DiagnosticHandlerTy DiagnosticHandler; void *DiagnosticContext; + bool RespectDiagnosticFilters; LLVMContext::YieldCallbackTy YieldCallback; void *YieldOpaqueHandle; - typedef DenseMap IntMapTy; + typedef DenseMap IntMapTy; IntMapTy IntConstants; - - typedef DenseMap FPMapTy; + + typedef DenseMap FPMapTy; FPMapTy FPConstants; FoldingSet AttrsSet; FoldingSet AttrsLists; FoldingSet AttrsSetNodes; - StringMap MDStringCache; + StringMap MDStringCache; + DenseMap ValuesAsMetadata; + DenseMap MetadataAsValues; - FoldingSet MDNodeSet; + DenseSet MDTuples; + DenseSet MDLocations; // MDNodes may be uniqued or not uniqued. When they're not uniqued, they // aren't in the MDNodeSet, but they're still shared between objects, so no // one object can destroy them. This set allows us to at least destroy them // on Context destruction. - SmallPtrSet NonUniquedMDNodes; - + SmallPtrSet DistinctMDNodes; + DenseMap CAZConstants; - typedef ConstantAggrUniqueMap ArrayConstantsTy; + typedef ConstantUniqueMap ArrayConstantsTy; ArrayConstantsTy ArrayConstants; - typedef ConstantAggrUniqueMap StructConstantsTy; + typedef ConstantUniqueMap StructConstantsTy; StructConstantsTy StructConstants; - typedef ConstantAggrUniqueMap VectorConstantsTy; + typedef ConstantUniqueMap VectorConstantsTy; VectorConstantsTy VectorConstants; DenseMap CPNConstants; @@ -289,17 +315,16 @@ public: DenseMap, BlockAddress *> BlockAddresses; - ConstantUniqueMap - ExprConstants; + ConstantUniqueMap ExprConstants; + + ConstantUniqueMap InlineAsms; - ConstantUniqueMap InlineAsms; - ConstantInt *TheTrueVal; ConstantInt *TheFalseVal; LeakDetectorImpl LLVMObjects; - + LeakDetectorImpl LLVMMDObjects; + // Basic type instances. Type VoidTy, LabelTy, HalfTy, FloatTy, DoubleTy, MetadataTy; Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy; @@ -311,11 +336,11 @@ public: BumpPtrAllocator TypeAllocator; DenseMap IntegerTypes; - - typedef DenseMap FunctionTypeMap; - FunctionTypeMap FunctionTypes; - typedef DenseMap StructTypeMap; - StructTypeMap AnonStructTypes; + + typedef DenseSet FunctionTypeSet; + FunctionTypeSet FunctionTypes; + typedef DenseSet StructTypeSet; + StructTypeSet AnonStructTypes; StringMap NamedStructTypes; unsigned NamedStructTypesUniqueID; @@ -333,32 +358,14 @@ public: /// CustomMDKindNames - Map to hold the metadata string to ID mapping. StringMap CustomMDKindNames; - - typedef std::pair > MDPairTy; + + typedef std::pair MDPairTy; typedef SmallVector MDMapTy; /// MetadataStore - Collection of per-instruction metadata used in this /// context. DenseMap MetadataStore; - /// ScopeRecordIdx - This is the index in ScopeRecords for an MDNode scope - /// entry with no "inlined at" element. - DenseMap ScopeRecordIdx; - - /// ScopeRecords - These are the actual mdnodes (in a value handle) for an - /// index. The ValueHandle ensures that ScopeRecordIdx stays up to date if - /// the MDNode is RAUW'd. - std::vector ScopeRecords; - - /// ScopeInlinedAtIdx - This is the index in ScopeInlinedAtRecords for an - /// scope/inlined-at pair. - DenseMap, int> ScopeInlinedAtIdx; - - /// ScopeInlinedAtRecords - These are the actual mdnodes (in value handles) - /// for an index. The ValueHandle ensures that ScopeINlinedAtIdx stays up - /// to date. - std::vector > ScopeInlinedAtRecords; - /// DiscriminatorTable - This table maps file:line locations to an /// integer representing the next DWARF path discriminator to assign to /// instructions in different blocks at the same location. @@ -374,6 +381,12 @@ public: typedef DenseMap PrefixDataMapTy; PrefixDataMapTy PrefixDataMap; + /// \brief Mapping from a function to its prologue data, which is stored as + /// the operand of an unparented ReturnInst so that the prologue data has a + /// Use. + typedef DenseMap PrologueDataMapTy; + PrologueDataMapTy PrologueDataMap; + int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx); int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx); diff --git a/lib/IR/LeakDetector.cpp b/lib/IR/LeakDetector.cpp deleted file mode 100644 index 6f71627..0000000 --- a/lib/IR/LeakDetector.cpp +++ /dev/null @@ -1,69 +0,0 @@ -//===-- LeakDetector.cpp - Implement LeakDetector interface ---------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the LeakDetector class. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/LeakDetector.h" -#include "LLVMContextImpl.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/IR/Value.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Mutex.h" -#include "llvm/Support/Threading.h" -using namespace llvm; - -static ManagedStatic > ObjectsLock; -static ManagedStatic > Objects; - -static void clearGarbage(LLVMContext &Context) { - Objects->clear(); - Context.pImpl->LLVMObjects.clear(); -} - -void LeakDetector::addGarbageObjectImpl(void *Object) { - sys::SmartScopedLock Lock(*ObjectsLock); - Objects->addGarbage(Object); -} - -void LeakDetector::addGarbageObjectImpl(const Value *Object) { - LLVMContextImpl *pImpl = Object->getContext().pImpl; - pImpl->LLVMObjects.addGarbage(Object); -} - -void LeakDetector::removeGarbageObjectImpl(void *Object) { - sys::SmartScopedLock Lock(*ObjectsLock); - Objects->removeGarbage(Object); -} - -void LeakDetector::removeGarbageObjectImpl(const Value *Object) { - LLVMContextImpl *pImpl = Object->getContext().pImpl; - pImpl->LLVMObjects.removeGarbage(Object); -} - -void LeakDetector::checkForGarbageImpl(LLVMContext &Context, - const std::string &Message) { - LLVMContextImpl *pImpl = Context.pImpl; - sys::SmartScopedLock Lock(*ObjectsLock); - - Objects->setName("GENERIC"); - pImpl->LLVMObjects.setName("LLVM"); - - // use non-short-circuit version so that both checks are performed - if (Objects->hasGarbage(Message) | - pImpl->LLVMObjects.hasGarbage(Message)) - errs() << "\nThis is probably because you removed an object, but didn't " - << "delete it. Please check your code for memory leaks.\n"; - - // Clear out results so we don't get duplicate warnings on - // next call... - clearGarbage(Context); -} diff --git a/lib/IR/LeaksContext.h b/lib/IR/LeaksContext.h index 52ac170..47704fa 100644 --- a/lib/IR/LeaksContext.h +++ b/lib/IR/LeaksContext.h @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_IR_LEAKSCONTEXT_H -#define LLVM_IR_LEAKSCONTEXT_H +#ifndef LLVM_LIB_IR_LEAKSCONTEXT_H +#define LLVM_LIB_IR_LEAKSCONTEXT_H #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Value.h" #include "llvm/Support/raw_ostream.h" @@ -31,6 +32,10 @@ struct PrinterTrait { static void print(const Value* P) { errs() << *P; } }; +template <> struct PrinterTrait { + static void print(const Metadata *P) { P->print(errs()); } +}; + template struct LeakDetectorImpl { explicit LeakDetectorImpl(const char* const name = "") : @@ -95,4 +100,4 @@ private: } -#endif // LLVM_IR_LEAKSCONTEXT_H +#endif diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp index d3f3482..b9ab256 100644 --- a/lib/IR/LegacyPassManager.cpp +++ b/lib/IR/LegacyPassManager.cpp @@ -227,10 +227,7 @@ public: Pass(PT_PassManager, ID), PMDataManager(), PMTopLevelManager(new FPPassManager()), wasRun(false) {} - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. + /// \copydoc FunctionPassManager::add() void add(Pass *P) { schedulePass(P); } @@ -398,10 +395,7 @@ public: Pass(PT_PassManager, ID), PMDataManager(), PMTopLevelManager(new MPPassManager()) {} - /// add - Add a pass to the queue of passes to run. This passes ownership of - /// the Pass to the PassManager. When the PassManager is destroyed, the pass - /// will be destroyed as well, so there is no need to delete the pass. This - /// implies that all passes MUST be allocated with 'new'. + /// \copydoc PassManager::add() void add(Pass *P) { schedulePass(P); } @@ -573,9 +567,8 @@ void PMTopLevelManager::collectLastUses(SmallVectorImpl &LastUses, return; SmallPtrSet &LU = DMI->second; - for (SmallPtrSet::iterator I = LU.begin(), - E = LU.end(); I != E; ++I) { - LastUses.push_back(*I); + for (Pass *LUP : LU) { + LastUses.push_back(LUP); } } @@ -1390,11 +1383,6 @@ FunctionPassManager::~FunctionPassManager() { delete FPM; } -/// add - Add a pass to the queue of passes to run. This passes -/// ownership of the Pass to the PassManager. When the -/// PassManager_X is destroyed, the pass will be destroyed as well, so -/// there is no need to delete the pass. (TODO delete passes.) -/// This implies that all passes MUST be allocated with 'new'. void FunctionPassManager::add(Pass *P) { FPM->add(P); } @@ -1404,11 +1392,8 @@ void FunctionPassManager::add(Pass *P) { /// so, return true. /// bool FunctionPassManager::run(Function &F) { - if (F.isMaterializable()) { - std::string errstr; - if (F.Materialize(&errstr)) - report_fatal_error("Error reading bitcode file: " + Twine(errstr)); - } + if (std::error_code EC = F.materialize()) + report_fatal_error("Error reading bitcode file: " + EC.message()); return FPM->run(F); } @@ -1684,7 +1669,7 @@ void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { if (!FoundPass) { FoundPass = RequiredPass; // This should be guaranteed to add RequiredPass to the passmanager given - // that we checked for an avaiable analysis above. + // that we checked for an available analysis above. FPP->add(RequiredPass); } // Register P as the last user of FoundPass or RequiredPass. @@ -1753,10 +1738,6 @@ PassManager::~PassManager() { delete PM; } -/// add - Add a pass to the queue of passes to run. This passes ownership of -/// the Pass to the PassManager. When the PassManager is destroyed, the pass -/// will be destroyed as well, so there is no need to delete the pass. This -/// implies that all passes MUST be allocated with 'new'. void PassManager::add(Pass *P) { PM->add(P); } diff --git a/lib/IR/MDBuilder.cpp b/lib/IR/MDBuilder.cpp index 65cdf38..c7fcf7a 100644 --- a/lib/IR/MDBuilder.cpp +++ b/lib/IR/MDBuilder.cpp @@ -21,11 +21,16 @@ MDString *MDBuilder::createString(StringRef Str) { return MDString::get(Context, Str); } +ConstantAsMetadata *MDBuilder::createConstant(Constant *C) { + return ConstantAsMetadata::get(C); +} + MDNode *MDBuilder::createFPMath(float Accuracy) { if (Accuracy == 0.0) return nullptr; assert(Accuracy > 0.0 && "Invalid fpmath accuracy!"); - Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy); + auto *Op = + createConstant(ConstantFP::get(Type::getFloatTy(Context), Accuracy)); return MDNode::get(Context, Op); } @@ -38,12 +43,12 @@ MDNode *MDBuilder::createBranchWeights(uint32_t TrueWeight, MDNode *MDBuilder::createBranchWeights(ArrayRef Weights) { assert(Weights.size() >= 2 && "Need at least two branch weights!"); - SmallVector Vals(Weights.size() + 1); + SmallVector Vals(Weights.size() + 1); Vals[0] = createString("branch_weights"); Type *Int32Ty = Type::getInt32Ty(Context); for (unsigned i = 0, e = Weights.size(); i != e; ++i) - Vals[i + 1] = ConstantInt::get(Int32Ty, Weights[i]); + Vals[i + 1] = createConstant(ConstantInt::get(Int32Ty, Weights[i])); return MDNode::get(Context, Vals); } @@ -56,14 +61,22 @@ MDNode *MDBuilder::createRange(const APInt &Lo, const APInt &Hi) { // Return the range [Lo, Hi). Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); - Value *Range[2] = {ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi)}; + Metadata *Range[2] = {createConstant(ConstantInt::get(Ty, Lo)), + createConstant(ConstantInt::get(Ty, Hi))}; return MDNode::get(Context, Range); } -MDNode *MDBuilder::createAnonymousTBAARoot() { +MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) { // To ensure uniqueness the root node is self-referential. - MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef()); - MDNode *Root = MDNode::get(Context, Dummy); + MDNode *Dummy = MDNode::getTemporary(Context, None); + + SmallVector Args(1, Dummy); + if (Extra) + Args.push_back(Extra); + if (!Name.empty()) + Args.push_back(createString(Name)); + MDNode *Root = MDNode::get(Context, Args); + // At this point we have // !0 = metadata !{} <- dummy // !1 = metadata !{metadata !0} <- root @@ -85,22 +98,31 @@ MDNode *MDBuilder::createTBAANode(StringRef Name, MDNode *Parent, bool isConstant) { if (isConstant) { Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1); - Value *Ops[3] = {createString(Name), Parent, Flags}; + Metadata *Ops[3] = {createString(Name), Parent, createConstant(Flags)}; return MDNode::get(Context, Ops); } else { - Value *Ops[2] = {createString(Name), Parent}; + Metadata *Ops[2] = {createString(Name), Parent}; return MDNode::get(Context, Ops); } } +MDNode *MDBuilder::createAliasScopeDomain(StringRef Name) { + return MDNode::get(Context, createString(Name)); +} + +MDNode *MDBuilder::createAliasScope(StringRef Name, MDNode *Domain) { + Metadata *Ops[2] = {createString(Name), Domain}; + return MDNode::get(Context, Ops); +} + /// \brief Return metadata for a tbaa.struct node with the given /// struct field descriptions. MDNode *MDBuilder::createTBAAStructNode(ArrayRef Fields) { - SmallVector Vals(Fields.size() * 3); + SmallVector Vals(Fields.size() * 3); Type *Int64 = Type::getInt64Ty(Context); for (unsigned i = 0, e = Fields.size(); i != e; ++i) { - Vals[i * 3 + 0] = ConstantInt::get(Int64, Fields[i].Offset); - Vals[i * 3 + 1] = ConstantInt::get(Int64, Fields[i].Size); + Vals[i * 3 + 0] = createConstant(ConstantInt::get(Int64, Fields[i].Offset)); + Vals[i * 3 + 1] = createConstant(ConstantInt::get(Int64, Fields[i].Size)); Vals[i * 3 + 2] = Fields[i].TBAA; } return MDNode::get(Context, Vals); @@ -110,12 +132,12 @@ MDNode *MDBuilder::createTBAAStructNode(ArrayRef Fields) { /// with the given name, a list of pairs (offset, field type in the type DAG). MDNode *MDBuilder::createTBAAStructTypeNode( StringRef Name, ArrayRef> Fields) { - SmallVector Ops(Fields.size() * 2 + 1); + SmallVector Ops(Fields.size() * 2 + 1); Type *Int64 = Type::getInt64Ty(Context); Ops[0] = createString(Name); for (unsigned i = 0, e = Fields.size(); i != e; ++i) { Ops[i * 2 + 1] = Fields[i].first; - Ops[i * 2 + 2] = ConstantInt::get(Int64, Fields[i].second); + Ops[i * 2 + 2] = createConstant(ConstantInt::get(Int64, Fields[i].second)); } return MDNode::get(Context, Ops); } @@ -125,7 +147,7 @@ MDNode *MDBuilder::createTBAAStructTypeNode( MDNode *MDBuilder::createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, uint64_t Offset) { ConstantInt *Off = ConstantInt::get(Type::getInt64Ty(Context), Offset); - Value *Ops[3] = {createString(Name), Parent, Off}; + Metadata *Ops[3] = {createString(Name), Parent, createConstant(Off)}; return MDNode::get(Context, Ops); } @@ -134,6 +156,7 @@ MDNode *MDBuilder::createTBAAScalarTypeNode(StringRef Name, MDNode *Parent, MDNode *MDBuilder::createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType, uint64_t Offset) { Type *Int64 = Type::getInt64Ty(Context); - Value *Ops[3] = {BaseType, AccessType, ConstantInt::get(Int64, Offset)}; + Metadata *Ops[3] = {BaseType, AccessType, + createConstant(ConstantInt::get(Int64, Offset))}; return MDNode::get(Context, Ops); } diff --git a/lib/IR/Mangler.cpp b/lib/IR/Mangler.cpp index 27d973b..5eeb797 100644 --- a/lib/IR/Mangler.cpp +++ b/lib/IR/Mangler.cpp @@ -22,23 +22,25 @@ using namespace llvm; static void getNameWithPrefixx(raw_ostream &OS, const Twine &GVName, Mangler::ManglerPrefixTy PrefixTy, - const DataLayout &DL, bool UseAt) { + const DataLayout &DL, char Prefix) { SmallString<256> TmpData; StringRef Name = GVName.toStringRef(TmpData); assert(!Name.empty() && "getNameWithPrefix requires non-empty name"); + // No need to do anything special if the global has the special "do not + // mangle" flag in the name. + if (Name[0] == '\1') { + OS << Name.substr(1); + return; + } + if (PrefixTy == Mangler::Private) OS << DL.getPrivateGlobalPrefix(); else if (PrefixTy == Mangler::LinkerPrivate) OS << DL.getLinkerPrivateGlobalPrefix(); - if (UseAt) { - OS << '@'; - } else { - char Prefix = DL.getGlobalPrefix(); - if (Prefix != '\0') - OS << Prefix; - } + if (Prefix != '\0') + OS << Prefix; // If this is a simple string that doesn't need escaping, just append it. OS << Name; @@ -46,7 +48,8 @@ static void getNameWithPrefixx(raw_ostream &OS, const Twine &GVName, void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName, ManglerPrefixTy PrefixTy) const { - return getNameWithPrefixx(OS, GVName, PrefixTy, *DL, false); + char Prefix = DL->getGlobalPrefix(); + return getNameWithPrefixx(OS, GVName, PrefixTy, *DL, Prefix); } void Mangler::getNameWithPrefix(SmallVectorImpl &OutName, @@ -56,11 +59,21 @@ void Mangler::getNameWithPrefix(SmallVectorImpl &OutName, return getNameWithPrefix(OS, GVName, PrefixTy); } -/// AddFastCallStdCallSuffix - Microsoft fastcall and stdcall functions require -/// a suffix on their name indicating the number of words of arguments they -/// take. -static void AddFastCallStdCallSuffix(raw_ostream &OS, const Function *F, - const DataLayout &TD) { +static bool hasByteCountSuffix(CallingConv::ID CC) { + switch (CC) { + case CallingConv::X86_FastCall: + case CallingConv::X86_StdCall: + case CallingConv::X86_VectorCall: + return true; + default: + return false; + } +} + +/// Microsoft fastcall and stdcall functions require a suffix on their name +/// indicating the number of words of arguments they take. +static void addByteCountSuffix(raw_ostream &OS, const Function *F, + const DataLayout &TD) { // Calculate arguments size total. unsigned ArgWords = 0; for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end(); @@ -69,8 +82,9 @@ static void AddFastCallStdCallSuffix(raw_ostream &OS, const Function *F, // 'Dereference' type in case of byval or inalloca parameter attribute. if (AI->hasByValOrInAllocaAttr()) Ty = cast(Ty)->getElementType(); - // Size should be aligned to DWORD boundary - ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4; + // Size should be aligned to pointer size. + unsigned PtrSize = TD.getPointerSize(); + ArgWords += RoundUpToAlignment(TD.getTypeAllocSize(Ty), PtrSize); } OS << '@' << ArgWords; @@ -99,41 +113,41 @@ void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV, } StringRef Name = GV->getName(); - - // No need to do anything special if the global has the special "do not - // mangle" flag in the name. - if (Name[0] == '\1') { - OS << Name.substr(1); - return; - } - - bool UseAt = false; - const Function *MSFunc = nullptr; - CallingConv::ID CC; - if (DL->hasMicrosoftFastStdCallMangling()) { - if ((MSFunc = dyn_cast(GV))) { - CC = MSFunc->getCallingConv(); - // fastcall functions need to start with @ instead of _. - if (CC == CallingConv::X86_FastCall) - UseAt = true; - } + char Prefix = DL->getGlobalPrefix(); + + // Mangle functions with Microsoft calling conventions specially. Only do + // this mangling for x86_64 vectorcall and 32-bit x86. + const Function *MSFunc = dyn_cast(GV); + if (Name.startswith("\01")) + MSFunc = nullptr; // Don't mangle when \01 is present. + CallingConv::ID CC = + MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C; + if (!DL->hasMicrosoftFastStdCallMangling() && + CC != CallingConv::X86_VectorCall) + MSFunc = nullptr; + if (MSFunc) { + if (CC == CallingConv::X86_FastCall) + Prefix = '@'; // fastcall functions have an @ prefix instead of _. + else if (CC == CallingConv::X86_VectorCall) + Prefix = '\0'; // vectorcall functions have no prefix. } - getNameWithPrefixx(OS, Name, PrefixTy, *DL, UseAt); + getNameWithPrefixx(OS, Name, PrefixTy, *DL, Prefix); if (!MSFunc) return; - // If we are supposed to add a microsoft-style suffix for stdcall/fastcall, - // add it. - // fastcall and stdcall functions usually need @42 at the end to specify - // the argument info. + // If we are supposed to add a microsoft-style suffix for stdcall, fastcall, + // or vectorcall, add it. These functions have a suffix of @N where N is the + // cumulative byte size of all of the parameters to the function in decimal. + if (CC == CallingConv::X86_VectorCall) + OS << '@'; // vectorcall functions use a double @ suffix. FunctionType *FT = MSFunc->getFunctionType(); - if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) && + if (hasByteCountSuffix(CC) && // "Pure" variadic functions do not receive @0 suffix. (!FT->isVarArg() || FT->getNumParams() == 0 || (FT->getNumParams() == 1 && MSFunc->hasStructRetAttr()))) - AddFastCallStdCallSuffix(OS, MSFunc, *DL); + addByteCountSuffix(OS, MSFunc, *DL); } void Mangler::getNameWithPrefix(SmallVectorImpl &OutName, diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 59137e4..2c6b332 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -22,396 +22,816 @@ #include "llvm/IR/ConstantRange.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/ValueHandle.h" + using namespace llvm; -//===----------------------------------------------------------------------===// -// MDString implementation. -// +MetadataAsValue::MetadataAsValue(Type *Ty, Metadata *MD) + : Value(Ty, MetadataAsValueVal), MD(MD) { + track(); +} -void MDString::anchor() { } +MetadataAsValue::~MetadataAsValue() { + getType()->getContext().pImpl->MetadataAsValues.erase(MD); + untrack(); +} -MDString::MDString(LLVMContext &C) - : Value(Type::getMetadataTy(C), Value::MDStringVal) {} +/// \brief Canonicalize metadata arguments to intrinsics. +/// +/// To support bitcode upgrades (and assembly semantic sugar) for \a +/// MetadataAsValue, we need to canonicalize certain metadata. +/// +/// - nullptr is replaced by an empty MDNode. +/// - An MDNode with a single null operand is replaced by an empty MDNode. +/// - An MDNode whose only operand is a \a ConstantAsMetadata gets skipped. +/// +/// This maintains readability of bitcode from when metadata was a type of +/// value, and these bridges were unnecessary. +static Metadata *canonicalizeMetadataForValue(LLVMContext &Context, + Metadata *MD) { + if (!MD) + // !{} + return MDNode::get(Context, None); + + // Return early if this isn't a single-operand MDNode. + auto *N = dyn_cast(MD); + if (!N || N->getNumOperands() != 1) + return MD; + + if (!N->getOperand(0)) + // !{} + return MDNode::get(Context, None); + + if (auto *C = dyn_cast(N->getOperand(0))) + // Look through the MDNode. + return C; + + return MD; +} -MDString *MDString::get(LLVMContext &Context, StringRef Str) { - LLVMContextImpl *pImpl = Context.pImpl; - StringMapEntry &Entry = - pImpl->MDStringCache.GetOrCreateValue(Str); - Value *&S = Entry.getValue(); - if (!S) S = new MDString(Context); - S->setValueName(&Entry); - return cast(S); +MetadataAsValue *MetadataAsValue::get(LLVMContext &Context, Metadata *MD) { + MD = canonicalizeMetadataForValue(Context, MD); + auto *&Entry = Context.pImpl->MetadataAsValues[MD]; + if (!Entry) + Entry = new MetadataAsValue(Type::getMetadataTy(Context), MD); + return Entry; } -//===----------------------------------------------------------------------===// -// MDNodeOperand implementation. -// +MetadataAsValue *MetadataAsValue::getIfExists(LLVMContext &Context, + Metadata *MD) { + MD = canonicalizeMetadataForValue(Context, MD); + auto &Store = Context.pImpl->MetadataAsValues; + auto I = Store.find(MD); + return I == Store.end() ? nullptr : I->second; +} -// Use CallbackVH to hold MDNode operands. -namespace llvm { -class MDNodeOperand : public CallbackVH { - MDNode *getParent() { - MDNodeOperand *Cur = this; +void MetadataAsValue::handleChangedMetadata(Metadata *MD) { + LLVMContext &Context = getContext(); + MD = canonicalizeMetadataForValue(Context, MD); + auto &Store = Context.pImpl->MetadataAsValues; + + // Stop tracking the old metadata. + Store.erase(this->MD); + untrack(); + this->MD = nullptr; + + // Start tracking MD, or RAUW if necessary. + auto *&Entry = Store[MD]; + if (Entry) { + replaceAllUsesWith(Entry); + delete this; + return; + } + + this->MD = MD; + track(); + Entry = this; +} + +void MetadataAsValue::track() { + if (MD) + MetadataTracking::track(&MD, *MD, *this); +} + +void MetadataAsValue::untrack() { + if (MD) + MetadataTracking::untrack(MD); +} + +void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) { + bool WasInserted = + UseMap.insert(std::make_pair(Ref, std::make_pair(Owner, NextIndex))) + .second; + (void)WasInserted; + assert(WasInserted && "Expected to add a reference"); + + ++NextIndex; + assert(NextIndex != 0 && "Unexpected overflow"); +} + +void ReplaceableMetadataImpl::dropRef(void *Ref) { + bool WasErased = UseMap.erase(Ref); + (void)WasErased; + assert(WasErased && "Expected to drop a reference"); +} + +void ReplaceableMetadataImpl::moveRef(void *Ref, void *New, + const Metadata &MD) { + auto I = UseMap.find(Ref); + assert(I != UseMap.end() && "Expected to move a reference"); + auto OwnerAndIndex = I->second; + UseMap.erase(I); + bool WasInserted = UseMap.insert(std::make_pair(New, OwnerAndIndex)).second; + (void)WasInserted; + assert(WasInserted && "Expected to add a reference"); + + // Check that the references are direct if there's no owner. + (void)MD; + assert((OwnerAndIndex.first || *static_cast(Ref) == &MD) && + "Reference without owner must be direct"); + assert((OwnerAndIndex.first || *static_cast(New) == &MD) && + "Reference without owner must be direct"); +} + +void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) { + assert(!(MD && isa(MD)) && "Expected non-temp node"); + + if (UseMap.empty()) + return; + + // Copy out uses since UseMap will get touched below. + typedef std::pair> UseTy; + SmallVector Uses(UseMap.begin(), UseMap.end()); + std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) { + return L.second.second < R.second.second; + }); + for (const auto &Pair : Uses) { + // Check that this Ref hasn't disappeared after RAUW (when updating a + // previous Ref). + if (!UseMap.count(Pair.first)) + continue; + + OwnerTy Owner = Pair.second.first; + if (!Owner) { + // Update unowned tracking references directly. + Metadata *&Ref = *static_cast(Pair.first); + Ref = MD; + if (MD) + MetadataTracking::track(Ref); + UseMap.erase(Pair.first); + continue; + } + + // Check for MetadataAsValue. + if (Owner.is()) { + Owner.get()->handleChangedMetadata(MD); + continue; + } + + // There's a Metadata owner -- dispatch. + Metadata *OwnerMD = Owner.get(); + switch (OwnerMD->getMetadataID()) { +#define HANDLE_METADATA_LEAF(CLASS) \ + case Metadata::CLASS##Kind: \ + cast(OwnerMD)->handleChangedOperand(Pair.first, MD); \ + continue; +#include "llvm/IR/Metadata.def" + default: + llvm_unreachable("Invalid metadata subclass"); + } + } + assert(UseMap.empty() && "Expected all uses to be replaced"); +} + +void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) { + if (UseMap.empty()) + return; + + if (!ResolveUsers) { + UseMap.clear(); + return; + } + + // Copy out uses since UseMap could get touched below. + typedef std::pair> UseTy; + SmallVector Uses(UseMap.begin(), UseMap.end()); + std::sort(Uses.begin(), Uses.end(), [](const UseTy &L, const UseTy &R) { + return L.second.second < R.second.second; + }); + UseMap.clear(); + for (const auto &Pair : Uses) { + auto Owner = Pair.second.first; + if (!Owner) + continue; + if (Owner.is()) + continue; - while (Cur->getValPtrInt() != 1) - --Cur; + // Resolve UniquableMDNodes that point at this. + auto *OwnerMD = dyn_cast(Owner.get()); + if (!OwnerMD) + continue; + if (OwnerMD->isResolved()) + continue; + OwnerMD->decrementUnresolvedOperandCount(); + } +} - assert(Cur->getValPtrInt() == 1 && - "Couldn't find the beginning of the operand list!"); - return reinterpret_cast(Cur) - 1; +static Function *getLocalFunction(Value *V) { + assert(V && "Expected value"); + if (auto *A = dyn_cast(V)) + return A->getParent(); + if (BasicBlock *BB = cast(V)->getParent()) + return BB->getParent(); + return nullptr; +} + +ValueAsMetadata *ValueAsMetadata::get(Value *V) { + assert(V && "Unexpected null Value"); + + auto &Context = V->getContext(); + auto *&Entry = Context.pImpl->ValuesAsMetadata[V]; + if (!Entry) { + assert((isa(V) || isa(V) || isa(V)) && + "Expected constant or function-local value"); + assert(!V->NameAndIsUsedByMD.getInt() && + "Expected this to be the only metadata use"); + V->NameAndIsUsedByMD.setInt(true); + if (auto *C = dyn_cast(V)) + Entry = new ConstantAsMetadata(C); + else + Entry = new LocalAsMetadata(V); } -public: - MDNodeOperand(Value *V) : CallbackVH(V) {} - virtual ~MDNodeOperand(); + return Entry; +} + +ValueAsMetadata *ValueAsMetadata::getIfExists(Value *V) { + assert(V && "Unexpected null Value"); + return V->getContext().pImpl->ValuesAsMetadata.lookup(V); +} - void set(Value *V) { - unsigned IsFirst = this->getValPtrInt(); - this->setValPtr(V); - this->setAsFirstOperand(IsFirst); +void ValueAsMetadata::handleDeletion(Value *V) { + assert(V && "Expected valid value"); + + auto &Store = V->getType()->getContext().pImpl->ValuesAsMetadata; + auto I = Store.find(V); + if (I == Store.end()) + return; + + // Remove old entry from the map. + ValueAsMetadata *MD = I->second; + assert(MD && "Expected valid metadata"); + assert(MD->getValue() == V && "Expected valid mapping"); + Store.erase(I); + + // Delete the metadata. + MD->replaceAllUsesWith(nullptr); + delete MD; +} + +void ValueAsMetadata::handleRAUW(Value *From, Value *To) { + assert(From && "Expected valid value"); + assert(To && "Expected valid value"); + assert(From != To && "Expected changed value"); + assert(From->getType() == To->getType() && "Unexpected type change"); + + LLVMContext &Context = From->getType()->getContext(); + auto &Store = Context.pImpl->ValuesAsMetadata; + auto I = Store.find(From); + if (I == Store.end()) { + assert(!From->NameAndIsUsedByMD.getInt() && + "Expected From not to be used by metadata"); + return; + } + + // Remove old entry from the map. + assert(From->NameAndIsUsedByMD.getInt() && + "Expected From to be used by metadata"); + From->NameAndIsUsedByMD.setInt(false); + ValueAsMetadata *MD = I->second; + assert(MD && "Expected valid metadata"); + assert(MD->getValue() == From && "Expected valid mapping"); + Store.erase(I); + + if (isa(MD)) { + if (auto *C = dyn_cast(To)) { + // Local became a constant. + MD->replaceAllUsesWith(ConstantAsMetadata::get(C)); + delete MD; + return; + } + if (getLocalFunction(From) && getLocalFunction(To) && + getLocalFunction(From) != getLocalFunction(To)) { + // Function changed. + MD->replaceAllUsesWith(nullptr); + delete MD; + return; + } + } else if (!isa(To)) { + // Changed to function-local value. + MD->replaceAllUsesWith(nullptr); + delete MD; + return; } - /// setAsFirstOperand - Accessor method to mark the operand as the first in - /// the list. - void setAsFirstOperand(unsigned V) { this->setValPtrInt(V); } + auto *&Entry = Store[To]; + if (Entry) { + // The target already exists. + MD->replaceAllUsesWith(Entry); + delete MD; + return; + } - void deleted() override; - void allUsesReplacedWith(Value *NV) override; -}; -} // end namespace llvm. + // Update MD in place (and update the map entry). + assert(!To->NameAndIsUsedByMD.getInt() && + "Expected this to be the only metadata use"); + To->NameAndIsUsedByMD.setInt(true); + MD->V = To; + Entry = MD; +} -// Provide out-of-line definition to prevent weak vtable. -MDNodeOperand::~MDNodeOperand() {} +//===----------------------------------------------------------------------===// +// MDString implementation. +// -void MDNodeOperand::deleted() { - getParent()->replaceOperand(this, nullptr); +MDString *MDString::get(LLVMContext &Context, StringRef Str) { + auto &Store = Context.pImpl->MDStringCache; + auto I = Store.find(Str); + if (I != Store.end()) + return &I->second; + + auto *Entry = + StringMapEntry::Create(Str, Store.getAllocator(), MDString()); + bool WasInserted = Store.insert(Entry); + (void)WasInserted; + assert(WasInserted && "Expected entry to be inserted"); + Entry->second.Entry = Entry; + return &Entry->second; } -void MDNodeOperand::allUsesReplacedWith(Value *NV) { - getParent()->replaceOperand(this, NV); +StringRef MDString::getString() const { + assert(Entry && "Expected to find string map entry"); + return Entry->first(); } //===----------------------------------------------------------------------===// // MDNode implementation. // -/// getOperandPtr - Helper function to get the MDNodeOperand's coallocated on -/// the end of the MDNode. -static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) { - // Use <= instead of < to permit a one-past-the-end address. - assert(Op <= N->getNumOperands() && "Invalid operand number"); - return reinterpret_cast(N + 1) + Op; +void *MDNode::operator new(size_t Size, unsigned NumOps) { + void *Ptr = ::operator new(Size + NumOps * sizeof(MDOperand)); + MDOperand *O = static_cast(Ptr); + for (MDOperand *E = O + NumOps; O != E; ++O) + (void)new (O) MDOperand; + return O; } -void MDNode::replaceOperandWith(unsigned i, Value *Val) { - MDNodeOperand *Op = getOperandPtr(this, i); - replaceOperand(Op, Val); +void MDNode::operator delete(void *Mem) { + MDNode *N = static_cast(Mem); + MDOperand *O = static_cast(Mem); + for (MDOperand *E = O - N->NumOperands; O != E; --O) + (O - 1)->~MDOperand(); + ::operator delete(O); } -MDNode::MDNode(LLVMContext &C, ArrayRef Vals, bool isFunctionLocal) -: Value(Type::getMetadataTy(C), Value::MDNodeVal) { - NumOperands = Vals.size(); +MDNode::MDNode(LLVMContext &Context, unsigned ID, ArrayRef MDs) + : Metadata(ID), Context(Context), NumOperands(MDs.size()), + MDNodeSubclassData(0) { + for (unsigned I = 0, E = MDs.size(); I != E; ++I) + setOperand(I, MDs[I]); +} - if (isFunctionLocal) - setValueSubclassData(getSubclassDataFromValue() | FunctionLocalBit); +bool MDNode::isResolved() const { + if (isa(this)) + return false; + return cast(this)->isResolved(); +} - // Initialize the operand list, which is co-allocated on the end of the node. - unsigned i = 0; - for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands; - Op != E; ++Op, ++i) { - new (Op) MDNodeOperand(Vals[i]); +static bool isOperandUnresolved(Metadata *Op) { + if (auto *N = dyn_cast_or_null(Op)) + return !N->isResolved(); + return false; +} - // Mark the first MDNodeOperand as being the first in the list of operands. - if (i == 0) - Op->setAsFirstOperand(1); - } +UniquableMDNode::UniquableMDNode(LLVMContext &C, unsigned ID, + ArrayRef Vals, bool AllowRAUW) + : MDNode(C, ID, Vals) { + if (!AllowRAUW) + return; + + // Check whether any operands are unresolved, requiring re-uniquing. + unsigned NumUnresolved = 0; + for (const auto &Op : operands()) + NumUnresolved += unsigned(isOperandUnresolved(Op)); + + if (!NumUnresolved) + return; + + ReplaceableUses.reset(new ReplaceableMetadataImpl); + SubclassData32 = NumUnresolved; } -/// ~MDNode - Destroy MDNode. -MDNode::~MDNode() { - assert((getSubclassDataFromValue() & DestroyFlag) != 0 && - "Not being destroyed through destroy()?"); - LLVMContextImpl *pImpl = getType()->getContext().pImpl; - if (isNotUniqued()) { - pImpl->NonUniquedMDNodes.erase(this); - } else { - pImpl->MDNodeSet.RemoveNode(this); - } +void UniquableMDNode::resolve() { + assert(!isResolved() && "Expected this to be unresolved"); + + // Move the map, so that this immediately looks resolved. + auto Uses = std::move(ReplaceableUses); + SubclassData32 = 0; + assert(isResolved() && "Expected this to be resolved"); - // Destroy the operands. - for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands; - Op != E; ++Op) - Op->~MDNodeOperand(); + // Drop RAUW support. + Uses->resolveAllUses(); } -static const Function *getFunctionForValue(Value *V) { - if (!V) return nullptr; - if (Instruction *I = dyn_cast(V)) { - BasicBlock *BB = I->getParent(); - return BB ? BB->getParent() : nullptr; - } - if (Argument *A = dyn_cast(V)) - return A->getParent(); - if (BasicBlock *BB = dyn_cast(V)) - return BB->getParent(); - if (MDNode *MD = dyn_cast(V)) - return MD->getFunction(); - return nullptr; +void UniquableMDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) { + assert(SubclassData32 != 0 && "Expected unresolved operands"); + + // Check if an operand was resolved. + if (!isOperandUnresolved(Old)) { + if (isOperandUnresolved(New)) + // An operand was un-resolved! + ++SubclassData32; + } else if (!isOperandUnresolved(New)) + decrementUnresolvedOperandCount(); } -#ifndef NDEBUG -static const Function *assertLocalFunction(const MDNode *N) { - if (!N->isFunctionLocal()) return nullptr; - - // FIXME: This does not handle cyclic function local metadata. - const Function *F = nullptr, *NewF = nullptr; - for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { - if (Value *V = N->getOperand(i)) { - if (MDNode *MD = dyn_cast(V)) - NewF = assertLocalFunction(MD); - else - NewF = getFunctionForValue(V); - } - if (!F) - F = NewF; - else - assert((NewF == nullptr || F == NewF) && - "inconsistent function-local metadata"); +void UniquableMDNode::decrementUnresolvedOperandCount() { + if (!--SubclassData32) + // Last unresolved operand has just been resolved. + resolve(); +} + +void UniquableMDNode::resolveCycles() { + if (isResolved()) + return; + + // Resolve this node immediately. + resolve(); + + // Resolve all operands. + for (const auto &Op : operands()) { + if (!Op) + continue; + assert(!isa(Op) && + "Expected all forward declarations to be resolved"); + if (auto *N = dyn_cast(Op)) + if (!N->isResolved()) + N->resolveCycles(); } - return F; } -#endif -// getFunction - If this metadata is function-local and recursively has a -// function-local operand, return the first such operand's parent function. -// Otherwise, return null. getFunction() should not be used for performance- -// critical code because it recursively visits all the MDNode's operands. -const Function *MDNode::getFunction() const { +void MDTuple::recalculateHash() { + setHash(hash_combine_range(op_begin(), op_end())); #ifndef NDEBUG - return assertLocalFunction(this); -#else - if (!isFunctionLocal()) return nullptr; - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (const Function *F = getFunctionForValue(getOperand(i))) - return F; - return nullptr; + { + SmallVector MDs(op_begin(), op_end()); + unsigned RawHash = hash_combine_range(MDs.begin(), MDs.end()); + assert(getHash() == RawHash && + "Expected hash of MDOperand to equal hash of Metadata*"); + } #endif } -// destroy - Delete this node. Only when there are no uses. -void MDNode::destroy() { - setValueSubclassData(getSubclassDataFromValue() | DestroyFlag); - // Placement delete, then free the memory. - this->~MDNode(); - free(this); +void MDNode::dropAllReferences() { + for (unsigned I = 0, E = NumOperands; I != E; ++I) + setOperand(I, nullptr); + if (auto *N = dyn_cast(this)) + if (!N->isResolved()) { + N->ReplaceableUses->resolveAllUses(/* ResolveUsers */ false); + N->ReplaceableUses.reset(); + } } -/// isFunctionLocalValue - Return true if this is a value that would require a -/// function-local MDNode. -static bool isFunctionLocalValue(Value *V) { - return isa(V) || isa(V) || isa(V) || - (isa(V) && cast(V)->isFunctionLocal()); +namespace llvm { +/// \brief Make MDOperand transparent for hashing. +/// +/// This overload of an implementation detail of the hashing library makes +/// MDOperand hash to the same value as a \a Metadata pointer. +/// +/// Note that overloading \a hash_value() as follows: +/// +/// \code +/// size_t hash_value(const MDOperand &X) { return hash_value(X.get()); } +/// \endcode +/// +/// does not cause MDOperand to be transparent. In particular, a bare pointer +/// doesn't get hashed before it's combined, whereas \a MDOperand would. +static const Metadata *get_hashable_data(const MDOperand &X) { return X.get(); } } -MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef Vals, - FunctionLocalness FL, bool Insert) { - LLVMContextImpl *pImpl = Context.pImpl; +void UniquableMDNode::handleChangedOperand(void *Ref, Metadata *New) { + unsigned Op = static_cast(Ref) - op_begin(); + assert(Op < getNumOperands() && "Expected valid operand"); - // Add all the operand pointers. Note that we don't have to add the - // isFunctionLocal bit because that's implied by the operands. - // Note that if the operands are later nulled out, the node will be - // removed from the uniquing map. - FoldingSetNodeID ID; - for (Value *V : Vals) - ID.AddPointer(V); + if (isStoredDistinctInContext()) { + assert(isResolved() && "Expected distinct node to be resolved"); - void *InsertPoint; - MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint); + // This node is not uniqued. Just set the operand and be done with it. + setOperand(Op, New); + return; + } - if (N || !Insert) - return N; + // This node is uniqued. + eraseFromStore(); - bool isFunctionLocal = false; - switch (FL) { - case FL_Unknown: - for (Value *V : Vals) { - if (!V) continue; - if (isFunctionLocalValue(V)) { - isFunctionLocal = true; - break; - } - } - break; - case FL_No: - isFunctionLocal = false; + Metadata *Old = getOperand(Op); + setOperand(Op, New); + + // Drop uniquing for self-reference cycles. + if (New == this) { + storeDistinctInContext(); + if (!isResolved()) + resolve(); + return; + } + + // Re-unique the node. + auto *Uniqued = uniquify(); + if (Uniqued == this) { + if (!isResolved()) + resolveAfterOperandChange(Old, New); + return; + } + + // Collision. + if (!isResolved()) { + // Still unresolved, so RAUW. + // + // First, clear out all operands to prevent any recursion (similar to + // dropAllReferences(), but we still need the use-list). + for (unsigned O = 0, E = getNumOperands(); O != E; ++O) + setOperand(O, nullptr); + ReplaceableUses->replaceAllUsesWith(Uniqued); + deleteAsSubclass(); + return; + } + + // Store in non-uniqued form if RAUW isn't possible. + storeDistinctInContext(); +} + +void UniquableMDNode::deleteAsSubclass() { + switch (getMetadataID()) { + default: + llvm_unreachable("Invalid subclass of UniquableMDNode"); +#define HANDLE_UNIQUABLE_LEAF(CLASS) \ + case CLASS##Kind: \ + delete cast(this); \ break; - case FL_Yes: - isFunctionLocal = true; +#include "llvm/IR/Metadata.def" + } +} + +UniquableMDNode *UniquableMDNode::uniquify() { + switch (getMetadataID()) { + default: + llvm_unreachable("Invalid subclass of UniquableMDNode"); +#define HANDLE_UNIQUABLE_LEAF(CLASS) \ + case CLASS##Kind: \ + return cast(this)->uniquifyImpl(); +#include "llvm/IR/Metadata.def" + } +} + +void UniquableMDNode::eraseFromStore() { + switch (getMetadataID()) { + default: + llvm_unreachable("Invalid subclass of UniquableMDNode"); +#define HANDLE_UNIQUABLE_LEAF(CLASS) \ + case CLASS##Kind: \ + cast(this)->eraseFromStoreImpl(); \ break; +#include "llvm/IR/Metadata.def" } +} - // Coallocate space for the node and Operands together, then placement new. - void *Ptr = malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand)); - N = new (Ptr) MDNode(Context, Vals, isFunctionLocal); +MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef MDs, + bool ShouldCreate) { + MDTupleInfo::KeyTy Key(MDs); - // Cache the operand hash. - N->Hash = ID.ComputeHash(); + auto &Store = Context.pImpl->MDTuples; + auto I = Store.find_as(Key); + if (I != Store.end()) + return *I; + if (!ShouldCreate) + return nullptr; - // InsertPoint will have been set by the FindNodeOrInsertPos call. - pImpl->MDNodeSet.InsertNode(N, InsertPoint); + // Coallocate space for the node and Operands together, then placement new. + auto *N = new (MDs.size()) MDTuple(Context, MDs, /* AllowRAUW */ true); + N->setHash(Key.Hash); + Store.insert(N); + return N; +} +MDTuple *MDTuple::getDistinct(LLVMContext &Context, ArrayRef MDs) { + auto *N = new (MDs.size()) MDTuple(Context, MDs, /* AllowRAUW */ false); + N->storeDistinctInContext(); return N; } -MDNode *MDNode::get(LLVMContext &Context, ArrayRef Vals) { - return getMDNode(Context, Vals, FL_Unknown); +MDTuple *MDTuple::uniquifyImpl() { + recalculateHash(); + MDTupleInfo::KeyTy Key(this); + + auto &Store = getContext().pImpl->MDTuples; + auto I = Store.find_as(Key); + if (I == Store.end()) { + Store.insert(this); + return this; + } + return *I; } -MDNode *MDNode::getWhenValsUnresolved(LLVMContext &Context, - ArrayRef Vals, - bool isFunctionLocal) { - return getMDNode(Context, Vals, isFunctionLocal ? FL_Yes : FL_No); +void MDTuple::eraseFromStoreImpl() { getContext().pImpl->MDTuples.erase(this); } + +MDLocation::MDLocation(LLVMContext &C, unsigned Line, unsigned Column, + ArrayRef MDs, bool AllowRAUW) + : UniquableMDNode(C, MDLocationKind, MDs, AllowRAUW) { + assert((MDs.size() == 1 || MDs.size() == 2) && + "Expected a scope and optional inlined-at"); + + // Set line and column. + assert(Line < (1u << 24) && "Expected 24-bit line"); + assert(Column < (1u << 8) && "Expected 8-bit column"); + + MDNodeSubclassData = Line; + SubclassData16 = Column; } -MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef Vals) { - return getMDNode(Context, Vals, FL_Unknown, false); +MDLocation *MDLocation::constructHelper(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, bool AllowRAUW) { + SmallVector Ops; + Ops.push_back(Scope); + if (InlinedAt) + Ops.push_back(InlinedAt); + return new (Ops.size()) MDLocation(Context, Line, Column, Ops, AllowRAUW); } -MDNode *MDNode::getTemporary(LLVMContext &Context, ArrayRef Vals) { - MDNode *N = - (MDNode *)malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand)); - N = new (N) MDNode(Context, Vals, FL_No); - N->setValueSubclassData(N->getSubclassDataFromValue() | - NotUniquedBit); - LeakDetector::addGarbageObject(N); +static void adjustLine(unsigned &Line) { + // Set to unknown on overflow. Still use 24 bits for now. + if (Line >= (1u << 24)) + Line = 0; +} + +static void adjustColumn(unsigned &Column) { + // Set to unknown on overflow. Still use 8 bits for now. + if (Column >= (1u << 8)) + Column = 0; +} + +MDLocation *MDLocation::getImpl(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt, bool ShouldCreate) { + // Fixup line/column. + adjustLine(Line); + adjustColumn(Column); + + MDLocationInfo::KeyTy Key(Line, Column, Scope, InlinedAt); + + auto &Store = Context.pImpl->MDLocations; + auto I = Store.find_as(Key); + if (I != Store.end()) + return *I; + if (!ShouldCreate) + return nullptr; + + auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt, + /* AllowRAUW */ true); + Store.insert(N); return N; } -void MDNode::deleteTemporary(MDNode *N) { - assert(N->use_empty() && "Temporary MDNode has uses!"); - assert(!N->getContext().pImpl->MDNodeSet.RemoveNode(N) && - "Deleting a non-temporary uniqued node!"); - assert(!N->getContext().pImpl->NonUniquedMDNodes.erase(N) && - "Deleting a non-temporary non-uniqued node!"); - assert((N->getSubclassDataFromValue() & NotUniquedBit) && - "Temporary MDNode does not have NotUniquedBit set!"); - assert((N->getSubclassDataFromValue() & DestroyFlag) == 0 && - "Temporary MDNode has DestroyFlag set!"); - LeakDetector::removeGarbageObject(N); - N->destroy(); -} - -/// getOperand - Return specified operand. -Value *MDNode::getOperand(unsigned i) const { - assert(i < getNumOperands() && "Invalid operand number"); - return *getOperandPtr(const_cast(this), i); -} - -void MDNode::Profile(FoldingSetNodeID &ID) const { - // Add all the operand pointers. Note that we don't have to add the - // isFunctionLocal bit because that's implied by the operands. - // Note that if the operands are later nulled out, the node will be - // removed from the uniquing map. - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - ID.AddPointer(getOperand(i)); -} - -void MDNode::setIsNotUniqued() { - setValueSubclassData(getSubclassDataFromValue() | NotUniquedBit); - LLVMContextImpl *pImpl = getType()->getContext().pImpl; - pImpl->NonUniquedMDNodes.insert(this); -} - -// Replace value from this node's operand list. -void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) { - Value *From = *Op; - - // If is possible that someone did GV->RAUW(inst), replacing a global variable - // with an instruction or some other function-local object. If this is a - // non-function-local MDNode, it can't point to a function-local object. - // Handle this case by implicitly dropping the MDNode reference to null. - // Likewise if the MDNode is function-local but for a different function. - if (To && isFunctionLocalValue(To)) { - if (!isFunctionLocal()) - To = nullptr; - else { - const Function *F = getFunction(); - const Function *FV = getFunctionForValue(To); - // Metadata can be function-local without having an associated function. - // So only consider functions to have changed if non-null. - if (F && FV && F != FV) - To = nullptr; - } +MDLocation *MDLocation::getDistinct(LLVMContext &Context, unsigned Line, + unsigned Column, Metadata *Scope, + Metadata *InlinedAt) { + // Fixup line/column. + adjustLine(Line); + adjustColumn(Column); + + auto *N = constructHelper(Context, Line, Column, Scope, InlinedAt, + /* AllowRAUW */ false); + N->storeDistinctInContext(); + return N; +} + +MDLocation *MDLocation::uniquifyImpl() { + MDLocationInfo::KeyTy Key(this); + + auto &Store = getContext().pImpl->MDLocations; + auto I = Store.find_as(Key); + if (I == Store.end()) { + Store.insert(this); + return this; } - - if (From == To) - return; + return *I; +} - // Update the operand. - Op->set(To); +void MDLocation::eraseFromStoreImpl() { + getContext().pImpl->MDLocations.erase(this); +} - // If this node is already not being uniqued (because one of the operands - // already went to null), then there is nothing else to do here. - if (isNotUniqued()) return; +MDNodeFwdDecl *MDNode::getTemporary(LLVMContext &Context, + ArrayRef MDs) { + return MDNodeFwdDecl::get(Context, MDs); +} - LLVMContextImpl *pImpl = getType()->getContext().pImpl; +void MDNode::deleteTemporary(MDNode *N) { delete cast(N); } - // Remove "this" from the context map. FoldingSet doesn't have to reprofile - // this node to remove it, so we don't care what state the operands are in. - pImpl->MDNodeSet.RemoveNode(this); +void UniquableMDNode::storeDistinctInContext() { + assert(!IsDistinctInContext && "Expected newly distinct metadata"); + IsDistinctInContext = true; + if (auto *T = dyn_cast(this)) + T->setHash(0); + getContext().pImpl->DistinctMDNodes.insert(this); +} - // If we are dropping an argument to null, we choose to not unique the MDNode - // anymore. This commonly occurs during destruction, and uniquing these - // brings little reuse. Also, this means we don't need to include - // isFunctionLocal bits in FoldingSetNodeIDs for MDNodes. - if (!To) { - setIsNotUniqued(); +void MDNode::replaceOperandWith(unsigned I, Metadata *New) { + if (getOperand(I) == New) return; - } - // Now that the node is out of the folding set, get ready to reinsert it. - // First, check to see if another node with the same operands already exists - // in the set. If so, then this node is redundant. - FoldingSetNodeID ID; - Profile(ID); - void *InsertPoint; - if (MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint)) { - replaceAllUsesWith(N); - destroy(); + if (isDistinct()) { + setOperand(I, New); return; } - // Cache the operand hash. - Hash = ID.ComputeHash(); - // InsertPoint will have been set by the FindNodeOrInsertPos call. - pImpl->MDNodeSet.InsertNode(this, InsertPoint); - - // If this MDValue was previously function-local but no longer is, clear - // its function-local flag. - if (isFunctionLocal() && !isFunctionLocalValue(To)) { - bool isStillFunctionLocal = false; - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { - Value *V = getOperand(i); - if (!V) continue; - if (isFunctionLocalValue(V)) { - isStillFunctionLocal = true; + cast(this)->handleChangedOperand(mutable_begin() + I, New); +} + +void MDNode::setOperand(unsigned I, Metadata *New) { + assert(I < NumOperands); + if (isStoredDistinctInContext() || isa(this)) + // No need for a callback, this isn't uniqued. + mutable_begin()[I].reset(New, nullptr); + else + mutable_begin()[I].reset(New, this); +} + +/// \brief Get a node, or a self-reference that looks like it. +/// +/// Special handling for finding self-references, for use by \a +/// MDNode::concatenate() and \a MDNode::intersect() to maintain behaviour from +/// when self-referencing nodes were still uniqued. If the first operand has +/// the same operands as \c Ops, return the first operand instead. +static MDNode *getOrSelfReference(LLVMContext &Context, + ArrayRef Ops) { + if (!Ops.empty()) + if (MDNode *N = dyn_cast_or_null(Ops[0])) + if (N->getNumOperands() == Ops.size() && N == N->getOperand(0)) { + for (unsigned I = 1, E = Ops.size(); I != E; ++I) + if (Ops[I] != N->getOperand(I)) + return MDNode::get(Context, Ops); + return N; + } + + return MDNode::get(Context, Ops); +} + +MDNode *MDNode::concatenate(MDNode *A, MDNode *B) { + if (!A) + return B; + if (!B) + return A; + + SmallVector MDs(A->getNumOperands() + B->getNumOperands()); + + unsigned j = 0; + for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) + MDs[j++] = A->getOperand(i); + for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i) + MDs[j++] = B->getOperand(i); + + // FIXME: This preserves long-standing behaviour, but is it really the right + // behaviour? Or was that an unintended side-effect of node uniquing? + return getOrSelfReference(A->getContext(), MDs); +} + +MDNode *MDNode::intersect(MDNode *A, MDNode *B) { + if (!A || !B) + return nullptr; + + SmallVector MDs; + for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) { + Metadata *MD = A->getOperand(i); + for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j) + if (MD == B->getOperand(j)) { + MDs.push_back(MD); break; } - } - if (!isStillFunctionLocal) - setValueSubclassData(getSubclassDataFromValue() & ~FunctionLocalBit); } + + // FIXME: This preserves long-standing behaviour, but is it really the right + // behaviour? Or was that an unintended side-effect of node uniquing? + return getOrSelfReference(A->getContext(), MDs); } MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) { if (!A || !B) return nullptr; - APFloat AVal = cast(A->getOperand(0))->getValueAPF(); - APFloat BVal = cast(B->getOperand(0))->getValueAPF(); + APFloat AVal = mdconst::extract(A->getOperand(0))->getValueAPF(); + APFloat BVal = mdconst::extract(B->getOperand(0))->getValueAPF(); if (AVal.compare(BVal) == APFloat::cmpLessThan) return A; return B; @@ -425,25 +845,27 @@ static bool canBeMerged(const ConstantRange &A, const ConstantRange &B) { return !A.intersectWith(B).isEmptySet() || isContiguous(A, B); } -static bool tryMergeRange(SmallVectorImpl &EndPoints, ConstantInt *Low, - ConstantInt *High) { +static bool tryMergeRange(SmallVectorImpl &EndPoints, + ConstantInt *Low, ConstantInt *High) { ConstantRange NewRange(Low->getValue(), High->getValue()); unsigned Size = EndPoints.size(); - APInt LB = cast(EndPoints[Size - 2])->getValue(); - APInt LE = cast(EndPoints[Size - 1])->getValue(); + APInt LB = EndPoints[Size - 2]->getValue(); + APInt LE = EndPoints[Size - 1]->getValue(); ConstantRange LastRange(LB, LE); if (canBeMerged(NewRange, LastRange)) { ConstantRange Union = LastRange.unionWith(NewRange); Type *Ty = High->getType(); - EndPoints[Size - 2] = ConstantInt::get(Ty, Union.getLower()); - EndPoints[Size - 1] = ConstantInt::get(Ty, Union.getUpper()); + EndPoints[Size - 2] = + cast(ConstantInt::get(Ty, Union.getLower())); + EndPoints[Size - 1] = + cast(ConstantInt::get(Ty, Union.getUpper())); return true; } return false; } -static void addRange(SmallVectorImpl &EndPoints, ConstantInt *Low, - ConstantInt *High) { +static void addRange(SmallVectorImpl &EndPoints, + ConstantInt *Low, ConstantInt *High) { if (!EndPoints.empty()) if (tryMergeRange(EndPoints, Low, High)) return; @@ -465,31 +887,33 @@ MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) { // First, walk both lists in older of the lower boundary of each interval. // At each step, try to merge the new interval to the last one we adedd. - SmallVector EndPoints; + SmallVector EndPoints; int AI = 0; int BI = 0; int AN = A->getNumOperands() / 2; int BN = B->getNumOperands() / 2; while (AI < AN && BI < BN) { - ConstantInt *ALow = cast(A->getOperand(2 * AI)); - ConstantInt *BLow = cast(B->getOperand(2 * BI)); + ConstantInt *ALow = mdconst::extract(A->getOperand(2 * AI)); + ConstantInt *BLow = mdconst::extract(B->getOperand(2 * BI)); if (ALow->getValue().slt(BLow->getValue())) { - addRange(EndPoints, ALow, cast(A->getOperand(2 * AI + 1))); + addRange(EndPoints, ALow, + mdconst::extract(A->getOperand(2 * AI + 1))); ++AI; } else { - addRange(EndPoints, BLow, cast(B->getOperand(2 * BI + 1))); + addRange(EndPoints, BLow, + mdconst::extract(B->getOperand(2 * BI + 1))); ++BI; } } while (AI < AN) { - addRange(EndPoints, cast(A->getOperand(2 * AI)), - cast(A->getOperand(2 * AI + 1))); + addRange(EndPoints, mdconst::extract(A->getOperand(2 * AI)), + mdconst::extract(A->getOperand(2 * AI + 1))); ++AI; } while (BI < BN) { - addRange(EndPoints, cast(B->getOperand(2 * BI)), - cast(B->getOperand(2 * BI + 1))); + addRange(EndPoints, mdconst::extract(B->getOperand(2 * BI)), + mdconst::extract(B->getOperand(2 * BI + 1))); ++BI; } @@ -497,8 +921,8 @@ MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) { // the last and first ones. unsigned Size = EndPoints.size(); if (Size > 4) { - ConstantInt *FB = cast(EndPoints[0]); - ConstantInt *FE = cast(EndPoints[1]); + ConstantInt *FB = EndPoints[0]; + ConstantInt *FE = EndPoints[1]; if (tryMergeRange(EndPoints, FB, FE)) { for (unsigned i = 0; i < Size - 2; ++i) { EndPoints[i] = EndPoints[i + 2]; @@ -510,63 +934,60 @@ MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) { // If in the end we have a single range, it is possible that it is now the // full range. Just drop the metadata in that case. if (EndPoints.size() == 2) { - ConstantRange Range(cast(EndPoints[0])->getValue(), - cast(EndPoints[1])->getValue()); + ConstantRange Range(EndPoints[0]->getValue(), EndPoints[1]->getValue()); if (Range.isFullSet()) return nullptr; } - return MDNode::get(A->getContext(), EndPoints); + SmallVector MDs; + MDs.reserve(EndPoints.size()); + for (auto *I : EndPoints) + MDs.push_back(ConstantAsMetadata::get(I)); + return MDNode::get(A->getContext(), MDs); } //===----------------------------------------------------------------------===// // NamedMDNode implementation. // -static SmallVector, 4> &getNMDOps(void *Operands) { - return *(SmallVector, 4>*)Operands; +static SmallVector &getNMDOps(void *Operands) { + return *(SmallVector *)Operands; } NamedMDNode::NamedMDNode(const Twine &N) - : Name(N.str()), Parent(nullptr), - Operands(new SmallVector, 4>()) { -} + : Name(N.str()), Parent(nullptr), + Operands(new SmallVector()) {} NamedMDNode::~NamedMDNode() { dropAllReferences(); delete &getNMDOps(Operands); } -/// getNumOperands - Return number of NamedMDNode operands. unsigned NamedMDNode::getNumOperands() const { return (unsigned)getNMDOps(Operands).size(); } -/// getOperand - Return specified operand. MDNode *NamedMDNode::getOperand(unsigned i) const { assert(i < getNumOperands() && "Invalid Operand number!"); - return dyn_cast(&*getNMDOps(Operands)[i]); + auto *N = getNMDOps(Operands)[i].get(); + return cast_or_null(N); } -/// addOperand - Add metadata Operand. -void NamedMDNode::addOperand(MDNode *M) { - assert(!M->isFunctionLocal() && - "NamedMDNode operands must not be function-local!"); - getNMDOps(Operands).push_back(TrackingVH(M)); +void NamedMDNode::addOperand(MDNode *M) { getNMDOps(Operands).emplace_back(M); } + +void NamedMDNode::setOperand(unsigned I, MDNode *New) { + assert(I < getNumOperands() && "Invalid operand number"); + getNMDOps(Operands)[I].reset(New); } -/// eraseFromParent - Drop all references and remove the node from parent -/// module. void NamedMDNode::eraseFromParent() { getParent()->eraseNamedMetadata(this); } -/// dropAllReferences - Remove all uses and clear node vector. void NamedMDNode::dropAllReferences() { getNMDOps(Operands).clear(); } -/// getName - Return a constant reference to this named metadata's name. StringRef NamedMDNode::getName() const { return StringRef(Name); } @@ -576,7 +997,8 @@ StringRef NamedMDNode::getName() const { // void Instruction::setMetadata(StringRef Kind, MDNode *Node) { - if (!Node && !hasMetadata()) return; + if (!Node && !hasMetadata()) + return; setMetadata(getContext().getMDKindID(Kind), Node); } @@ -615,7 +1037,7 @@ void Instruction::dropUnknownMetadata(ArrayRef KnownIDs) { continue; } - Info[I] = Info.back(); + Info[I] = std::move(Info.back()); Info.pop_back(); --E; } @@ -632,7 +1054,8 @@ void Instruction::dropUnknownMetadata(ArrayRef KnownIDs) { /// node. This updates/replaces metadata if already present, or removes it if /// Node is null. void Instruction::setMetadata(unsigned KindID, MDNode *Node) { - if (!Node && !hasMetadata()) return; + if (!Node && !hasMetadata()) + return; // Handle 'dbg' as a special case since it is not stored in the hash table. if (KindID == LLVMContext::MD_dbg) { @@ -651,13 +1074,14 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) { // Handle replacement of an existing value. for (auto &P : Info) if (P.first == KindID) { - P.second = Node; + P.second.reset(Node); return; } } // No replacement, just add it to the list. - Info.push_back(std::make_pair(KindID, Node)); + Info.emplace_back(std::piecewise_construct, std::make_tuple(KindID), + std::make_tuple(Node)); return; } @@ -679,7 +1103,7 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) { // Handle removal of an existing value. for (unsigned i = 0, e = Info.size(); i != e; ++i) if (Info[i].first == KindID) { - Info[i] = Info.back(); + Info[i] = std::move(Info.back()); Info.pop_back(); assert(!Info.empty() && "Removing last entry should be handled above"); return; @@ -687,11 +1111,17 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) { // Otherwise, removing an entry that doesn't exist on the instruction. } +void Instruction::setAAMetadata(const AAMDNodes &N) { + setMetadata(LLVMContext::MD_tbaa, N.TBAA); + setMetadata(LLVMContext::MD_alias_scope, N.Scope); + setMetadata(LLVMContext::MD_noalias, N.NoAlias); +} + MDNode *Instruction::getMetadataImpl(unsigned KindID) const { // Handle 'dbg' as a special case since it is not stored in the hash table. if (KindID == LLVMContext::MD_dbg) - return DbgLoc.getAsMDNode(getContext()); - + return DbgLoc.getAsMDNode(); + if (!hasMetadataHashEntry()) return nullptr; LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this]; @@ -703,14 +1133,14 @@ MDNode *Instruction::getMetadataImpl(unsigned KindID) const { return nullptr; } -void Instruction::getAllMetadataImpl(SmallVectorImpl > &Result) const { +void Instruction::getAllMetadataImpl( + SmallVectorImpl> &Result) const { Result.clear(); // Handle 'dbg' as a special case since it is not stored in the hash table. if (!DbgLoc.isUnknown()) { - Result.push_back(std::make_pair((unsigned)LLVMContext::MD_dbg, - DbgLoc.getAsMDNode(getContext()))); + Result.push_back( + std::make_pair((unsigned)LLVMContext::MD_dbg, DbgLoc.getAsMDNode())); if (!hasMetadataHashEntry()) return; } @@ -721,16 +1151,17 @@ void Instruction::getAllMetadataImpl(SmallVectorImplMetadataStore.find(this)->second; assert(!Info.empty() && "Shouldn't have called this"); - Result.append(Info.begin(), Info.end()); + Result.reserve(Result.size() + Info.size()); + for (auto &I : Info) + Result.push_back(std::make_pair(I.first, cast(I.second.get()))); // Sort the resulting array so it is stable. if (Result.size() > 1) array_pod_sort(Result.begin(), Result.end()); } -void Instruction:: -getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl > &Result) const { +void Instruction::getAllMetadataOtherThanDebugLocImpl( + SmallVectorImpl> &Result) const { Result.clear(); assert(hasMetadataHashEntry() && getContext().pImpl->MetadataStore.count(this) && @@ -738,7 +1169,9 @@ getAllMetadataOtherThanDebugLocImpl(SmallVectorImplMetadataStore.find(this)->second; assert(!Info.empty() && "Shouldn't have called this"); - Result.append(Info.begin(), Info.end()); + Result.reserve(Result.size() + Info.size()); + for (auto &I : Info) + Result.push_back(std::make_pair(I.first, cast(I.second.get()))); // Sort the resulting array so it is stable. if (Result.size() > 1) @@ -752,4 +1185,3 @@ void Instruction::clearMetadataHashEntries() { getContext().pImpl->MetadataStore.erase(this); setHasMetadataHashEntry(false); } - diff --git a/lib/IR/MetadataTracking.cpp b/lib/IR/MetadataTracking.cpp new file mode 100644 index 0000000..ba97ca0 --- /dev/null +++ b/lib/IR/MetadataTracking.cpp @@ -0,0 +1,58 @@ +//===- MetadataTracking.cpp - Implement metadata tracking -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements Metadata tracking. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/MetadataTracking.h" +#include "llvm/IR/Metadata.h" + +using namespace llvm; + +ReplaceableMetadataImpl *ReplaceableMetadataImpl::get(Metadata &MD) { + if (auto *N = dyn_cast(&MD)) { + if (auto *U = dyn_cast(N)) + return U->ReplaceableUses.get(); + return cast(N); + } + return dyn_cast(&MD); +} + +bool MetadataTracking::track(void *Ref, Metadata &MD, OwnerTy Owner) { + assert(Ref && "Expected live reference"); + assert((Owner || *static_cast(Ref) == &MD) && + "Reference without owner must be direct"); + if (auto *R = ReplaceableMetadataImpl::get(MD)) { + R->addRef(Ref, Owner); + return true; + } + return false; +} + +void MetadataTracking::untrack(void *Ref, Metadata &MD) { + assert(Ref && "Expected live reference"); + if (auto *R = ReplaceableMetadataImpl::get(MD)) + R->dropRef(Ref); +} + +bool MetadataTracking::retrack(void *Ref, Metadata &MD, void *New) { + assert(Ref && "Expected live reference"); + assert(New && "Expected live reference"); + assert(Ref != New && "Expected change"); + if (auto *R = ReplaceableMetadataImpl::get(MD)) { + R->moveRef(Ref, New, MD); + return true; + } + return false; +} + +bool MetadataTracking::isReplaceable(const Metadata &MD) { + return ReplaceableMetadataImpl::get(const_cast(MD)); +} diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index f1b1f9a..d32ffcd 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -22,7 +22,7 @@ #include "llvm/IR/GVMaterializer.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/IR/LeakDetector.h" +#include "llvm/IR/TypeFinder.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Path.h" #include "llvm/Support/RandomNumberGenerator.h" @@ -46,7 +46,7 @@ template class llvm::SymbolTableListTraits; // Module::Module(StringRef MID, LLVMContext &C) - : Context(C), Materializer(), ModuleID(MID), RNG(nullptr), DL("") { + : Context(C), Materializer(), ModuleID(MID), DL("") { ValSymTab = new ValueSymbolTable(); NamedMDSymTab = new StringMap(); Context.addModule(this); @@ -61,9 +61,27 @@ Module::~Module() { NamedMDList.clear(); delete ValSymTab; delete static_cast *>(NamedMDSymTab); - delete RNG; } +RandomNumberGenerator *Module::createRNG(const Pass* P) const { + SmallString<32> Salt(P->getPassName()); + + // This RNG is guaranteed to produce the same random stream only + // when the Module ID and thus the input filename is the same. This + // might be problematic if the input filename extension changes + // (e.g. from .c to .bc or .ll). + // + // We could store this salt in NamedMetadata, but this would make + // the parameter non-const. This would unfortunately make this + // interface unusable by any Machine passes, since they only have a + // const reference to their IR Module. Alternatively we can always + // store salt metadata from the Module constructor. + Salt += sys::path::filename(getModuleIdentifier()); + + return new RandomNumberGenerator(Salt); +} + + /// getNamedValue - Return the first global value in the module with /// the specified name, of arbitrary type. This method returns null /// if a global with the specified name is not found. @@ -259,6 +277,17 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) { NamedMDList.erase(NMD); } +bool Module::isValidModFlagBehavior(Metadata *MD, ModFlagBehavior &MFB) { + if (ConstantInt *Behavior = mdconst::dyn_extract(MD)) { + uint64_t Val = Behavior->getLimitedValue(); + if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) { + MFB = static_cast(Val); + return true; + } + } + return false; +} + /// getModuleFlagsMetadata - Returns the module flags in the provided vector. void Module:: getModuleFlagsMetadata(SmallVectorImpl &Flags) const { @@ -266,22 +295,22 @@ getModuleFlagsMetadata(SmallVectorImpl &Flags) const { if (!ModFlags) return; for (const MDNode *Flag : ModFlags->operands()) { - if (Flag->getNumOperands() >= 3 && isa(Flag->getOperand(0)) && + ModFlagBehavior MFB; + if (Flag->getNumOperands() >= 3 && + isValidModFlagBehavior(Flag->getOperand(0), MFB) && isa(Flag->getOperand(1))) { // Check the operands of the MDNode before accessing the operands. // The verifier will actually catch these failures. - ConstantInt *Behavior = cast(Flag->getOperand(0)); MDString *Key = cast(Flag->getOperand(1)); - Value *Val = Flag->getOperand(2); - Flags.push_back(ModuleFlagEntry(ModFlagBehavior(Behavior->getZExtValue()), - Key, Val)); + Metadata *Val = Flag->getOperand(2); + Flags.push_back(ModuleFlagEntry(MFB, Key, Val)); } } } /// Return the corresponding value if Key appears in module flags, otherwise /// return null. -Value *Module::getModuleFlag(StringRef Key) const { +Metadata *Module::getModuleFlag(StringRef Key) const { SmallVector ModuleFlags; getModuleFlagsMetadata(ModuleFlags); for (const ModuleFlagEntry &MFE : ModuleFlags) { @@ -309,14 +338,18 @@ NamedMDNode *Module::getOrInsertModuleFlagsMetadata() { /// metadata. It will create the module-level flags named metadata if it doesn't /// already exist. void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key, - Value *Val) { + Metadata *Val) { Type *Int32Ty = Type::getInt32Ty(Context); - Value *Ops[3] = { - ConstantInt::get(Int32Ty, Behavior), MDString::get(Context, Key), Val - }; + Metadata *Ops[3] = { + ConstantAsMetadata::get(ConstantInt::get(Int32Ty, Behavior)), + MDString::get(Context, Key), Val}; getOrInsertModuleFlagsMetadata()->addOperand(MDNode::get(Context, Ops)); } void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key, + Constant *Val) { + addModuleFlag(Behavior, Key, ConstantAsMetadata::get(Val)); +} +void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key, uint32_t Val) { Type *Int32Ty = Type::getInt32Ty(Context); addModuleFlag(Behavior, Key, ConstantInt::get(Int32Ty, Val)); @@ -324,7 +357,7 @@ void Module::addModuleFlag(ModFlagBehavior Behavior, StringRef Key, void Module::addModuleFlag(MDNode *Node) { assert(Node->getNumOperands() == 3 && "Invalid number of operands for module flag!"); - assert(isa(Node->getOperand(0)) && + assert(mdconst::hasa(Node->getOperand(0)) && isa(Node->getOperand(1)) && "Invalid operand types for module flag!"); getOrInsertModuleFlagsMetadata()->addOperand(Node); @@ -358,16 +391,6 @@ const DataLayout *Module::getDataLayout() const { return &DL; } -// We want reproducible builds, but ModuleID may be a full path so we just use -// the filename to salt the RNG (although it is not guaranteed to be unique). -RandomNumberGenerator &Module::getRNG() const { - if (RNG == nullptr) { - StringRef Salt = sys::path::filename(ModuleID); - RNG = new RandomNumberGenerator(Salt); - } - return *RNG; -} - //===----------------------------------------------------------------------===// // Methods to control the materialization of GlobalValues in the Module. // @@ -378,28 +401,17 @@ void Module::setMaterializer(GVMaterializer *GVM) { Materializer.reset(GVM); } -bool Module::isMaterializable(const GlobalValue *GV) const { - if (Materializer) - return Materializer->isMaterializable(GV); - return false; -} - bool Module::isDematerializable(const GlobalValue *GV) const { if (Materializer) return Materializer->isDematerializable(GV); return false; } -bool Module::Materialize(GlobalValue *GV, std::string *ErrInfo) { +std::error_code Module::materialize(GlobalValue *GV) { if (!Materializer) - return false; + return std::error_code(); - std::error_code EC = Materializer->Materialize(GV); - if (!EC) - return false; - if (ErrInfo) - *ErrInfo = EC.message(); - return true; + return Materializer->materialize(GV); } void Module::Dematerialize(GlobalValue *GV) { @@ -413,13 +425,10 @@ std::error_code Module::materializeAll() { return Materializer->MaterializeModule(this); } -std::error_code Module::materializeAllPermanently(bool ReleaseBuffer) { +std::error_code Module::materializeAllPermanently() { if (std::error_code EC = materializeAll()) return EC; - if (ReleaseBuffer) - Materializer->releaseBuffer(); - Materializer.reset(); return std::error_code(); } @@ -428,6 +437,19 @@ std::error_code Module::materializeAllPermanently(bool ReleaseBuffer) { // Other module related stuff. // +std::vector Module::getIdentifiedStructTypes() const { + // If we have a materializer, it is possible that some unread function + // uses a type that is currently not visible to a TypeFinder, so ask + // the materializer which types it created. + if (Materializer) + return Materializer->getIdentifiedStructTypes(); + + std::vector Ret; + TypeFinder SrcStructTypes; + SrcStructTypes.run(*this, true); + Ret.assign(SrcStructTypes.begin(), SrcStructTypes.end()); + return Ret; +} // dropAllReferences() - This function causes all the subelements to "let go" // of all references that they are maintaining. This allows one to 'delete' a @@ -448,16 +470,28 @@ void Module::dropAllReferences() { } unsigned Module::getDwarfVersion() const { - Value *Val = getModuleFlag("Dwarf Version"); + auto *Val = cast_or_null(getModuleFlag("Dwarf Version")); if (!Val) return dwarf::DWARF_VERSION; - return cast(Val)->getZExtValue(); + return cast(Val->getValue())->getZExtValue(); } Comdat *Module::getOrInsertComdat(StringRef Name) { - Comdat C; - StringMapEntry &Entry = - ComdatSymTab.GetOrCreateValue(Name, std::move(C)); + auto &Entry = *ComdatSymTab.insert(std::make_pair(Name, Comdat())).first; Entry.second.Name = &Entry; return &Entry.second; } + +PICLevel::Level Module::getPICLevel() const { + auto *Val = cast_or_null(getModuleFlag("PIC Level")); + + if (Val == NULL) + return PICLevel::Default; + + return static_cast( + cast(Val->getValue())->getZExtValue()); +} + +void Module::setPICLevel(PICLevel::Level PL) { + addModuleFlag(ModFlagBehavior::Error, "PIC Level", PL); +} diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp index 2e2a7cb..a5f407c 100644 --- a/lib/IR/PassManager.cpp +++ b/lib/IR/PassManager.cpp @@ -10,174 +10,13 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/PassManager.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" using namespace llvm; -static cl::opt -DebugPM("debug-pass-manager", cl::Hidden, - cl::desc("Print pass management debugging information")); - -PreservedAnalyses ModulePassManager::run(Module *M, ModuleAnalysisManager *AM) { - PreservedAnalyses PA = PreservedAnalyses::all(); - - if (DebugPM) - dbgs() << "Starting module pass manager run.\n"; - - for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { - if (DebugPM) - dbgs() << "Running module pass: " << Passes[Idx]->name() << "\n"; - - PreservedAnalyses PassPA = Passes[Idx]->run(M, AM); - if (AM) - AM->invalidate(M, PassPA); - PA.intersect(std::move(PassPA)); - - M->getContext().yield(); - } - - if (DebugPM) - dbgs() << "Finished module pass manager run.\n"; - - return PA; -} - -ModuleAnalysisManager::ResultConceptT & -ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) { - ModuleAnalysisResultMapT::iterator RI; - bool Inserted; - std::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair( - PassID, std::unique_ptr>())); - - // If we don't have a cached result for this module, look up the pass and run - // it to produce a result, which we then add to the cache. - if (Inserted) - RI->second = lookupPass(PassID).run(M, this); - - return *RI->second; -} - -ModuleAnalysisManager::ResultConceptT * -ModuleAnalysisManager::getCachedResultImpl(void *PassID, Module *M) const { - ModuleAnalysisResultMapT::const_iterator RI = - ModuleAnalysisResults.find(PassID); - return RI == ModuleAnalysisResults.end() ? nullptr : &*RI->second; -} - -void ModuleAnalysisManager::invalidateImpl(void *PassID, Module *M) { - ModuleAnalysisResults.erase(PassID); -} - -void ModuleAnalysisManager::invalidateImpl(Module *M, - const PreservedAnalyses &PA) { - // FIXME: This is a total hack based on the fact that erasure doesn't - // invalidate iteration for DenseMap. - for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(), - E = ModuleAnalysisResults.end(); - I != E; ++I) - if (I->second->invalidate(M, PA)) - ModuleAnalysisResults.erase(I); -} - -PreservedAnalyses FunctionPassManager::run(Function *F, - FunctionAnalysisManager *AM) { - PreservedAnalyses PA = PreservedAnalyses::all(); - - if (DebugPM) - dbgs() << "Starting function pass manager run.\n"; - - for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) { - if (DebugPM) - dbgs() << "Running function pass: " << Passes[Idx]->name() << "\n"; - - PreservedAnalyses PassPA = Passes[Idx]->run(F, AM); - if (AM) - AM->invalidate(F, PassPA); - PA.intersect(std::move(PassPA)); - - F->getContext().yield(); - } - - if (DebugPM) - dbgs() << "Finished function pass manager run.\n"; - - return PA; -} - -bool FunctionAnalysisManager::empty() const { - assert(FunctionAnalysisResults.empty() == - FunctionAnalysisResultLists.empty() && - "The storage and index of analysis results disagree on how many there " - "are!"); - return FunctionAnalysisResults.empty(); -} - -void FunctionAnalysisManager::clear() { - FunctionAnalysisResults.clear(); - FunctionAnalysisResultLists.clear(); -} - -FunctionAnalysisManager::ResultConceptT & -FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) { - FunctionAnalysisResultMapT::iterator RI; - bool Inserted; - std::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair( - std::make_pair(PassID, F), FunctionAnalysisResultListT::iterator())); - - // If we don't have a cached result for this function, look up the pass and - // run it to produce a result, which we then add to the cache. - if (Inserted) { - FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F]; - ResultList.emplace_back(PassID, lookupPass(PassID).run(F, this)); - RI->second = std::prev(ResultList.end()); - } - - return *RI->second->second; -} - -FunctionAnalysisManager::ResultConceptT * -FunctionAnalysisManager::getCachedResultImpl(void *PassID, Function *F) const { - FunctionAnalysisResultMapT::const_iterator RI = - FunctionAnalysisResults.find(std::make_pair(PassID, F)); - return RI == FunctionAnalysisResults.end() ? nullptr : &*RI->second->second; -} - -void FunctionAnalysisManager::invalidateImpl(void *PassID, Function *F) { - FunctionAnalysisResultMapT::iterator RI = - FunctionAnalysisResults.find(std::make_pair(PassID, F)); - if (RI == FunctionAnalysisResults.end()) - return; - - FunctionAnalysisResultLists[F].erase(RI->second); -} - -void FunctionAnalysisManager::invalidateImpl(Function *F, - const PreservedAnalyses &PA) { - // Clear all the invalidated results associated specifically with this - // function. - SmallVector InvalidatedPassIDs; - FunctionAnalysisResultListT &ResultsList = FunctionAnalysisResultLists[F]; - for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(), - E = ResultsList.end(); - I != E;) - if (I->second->invalidate(F, PA)) { - InvalidatedPassIDs.push_back(I->first); - I = ResultsList.erase(I); - } else { - ++I; - } - while (!InvalidatedPassIDs.empty()) - FunctionAnalysisResults.erase( - std::make_pair(InvalidatedPassIDs.pop_back_val(), F)); - if (ResultsList.empty()) - FunctionAnalysisResultLists.erase(F); -} - char FunctionAnalysisManagerModuleProxy::PassID; FunctionAnalysisManagerModuleProxy::Result -FunctionAnalysisManagerModuleProxy::run(Module *M) { +FunctionAnalysisManagerModuleProxy::run(Module &M) { assert(FAM->empty() && "Function analyses ran prior to the module proxy!"); return Result(*FAM); } @@ -189,7 +28,7 @@ FunctionAnalysisManagerModuleProxy::Result::~Result() { } bool FunctionAnalysisManagerModuleProxy::Result::invalidate( - Module *M, const PreservedAnalyses &PA) { + Module &M, const PreservedAnalyses &PA) { // If this proxy isn't marked as preserved, then we can't even invalidate // individual function analyses, there may be an invalid set of Function // objects in the cache making it impossible to incrementally preserve them. diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp index 91940a9..b879fef 100644 --- a/lib/IR/PassRegistry.cpp +++ b/lib/IR/PassRegistry.cpp @@ -36,8 +36,7 @@ PassRegistry *PassRegistry::getPassRegistry() { // Accessors // -PassRegistry::~PassRegistry() { -} +PassRegistry::~PassRegistry() {} const PassInfo *PassRegistry::getPassInfo(const void *TI) const { sys::SmartScopedReader Guard(Lock); @@ -58,77 +57,62 @@ const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const { void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) { sys::SmartScopedWriter Guard(Lock); bool Inserted = - PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second; + PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second; assert(Inserted && "Pass registered multiple times!"); (void)Inserted; PassInfoStringMap[PI.getPassArgument()] = &PI; - + // Notify any listeners. - for (std::vector::iterator - I = Listeners.begin(), E = Listeners.end(); I != E; ++I) - (*I)->passRegistered(&PI); - - if (ShouldFree) ToFree.push_back(std::unique_ptr(&PI)); -} + for (auto *Listener : Listeners) + Listener->passRegistered(&PI); -void PassRegistry::unregisterPass(const PassInfo &PI) { - sys::SmartScopedWriter Guard(Lock); - MapType::iterator I = PassInfoMap.find(PI.getTypeInfo()); - assert(I != PassInfoMap.end() && "Pass registered but not in map!"); - - // Remove pass from the map. - PassInfoMap.erase(I); - PassInfoStringMap.erase(PI.getPassArgument()); + if (ShouldFree) + ToFree.push_back(std::unique_ptr(&PI)); } void PassRegistry::enumerateWith(PassRegistrationListener *L) { sys::SmartScopedReader Guard(Lock); - for (auto I = PassInfoMap.begin(), E = PassInfoMap.end(); I != E; ++I) - L->passEnumerate(I->second); + for (auto PassInfoPair : PassInfoMap) + L->passEnumerate(PassInfoPair.second); } - /// Analysis Group Mechanisms. -void PassRegistry::registerAnalysisGroup(const void *InterfaceID, +void PassRegistry::registerAnalysisGroup(const void *InterfaceID, const void *PassID, - PassInfo& Registeree, - bool isDefault, + PassInfo &Registeree, bool isDefault, bool ShouldFree) { - PassInfo *InterfaceInfo = const_cast(getPassInfo(InterfaceID)); + PassInfo *InterfaceInfo = const_cast(getPassInfo(InterfaceID)); if (!InterfaceInfo) { // First reference to Interface, register it now. registerPass(Registeree); InterfaceInfo = &Registeree; } - assert(Registeree.isAnalysisGroup() && + assert(Registeree.isAnalysisGroup() && "Trying to join an analysis group that is a normal pass!"); if (PassID) { - PassInfo *ImplementationInfo = const_cast(getPassInfo(PassID)); + PassInfo *ImplementationInfo = const_cast(getPassInfo(PassID)); assert(ImplementationInfo && "Must register pass before adding to AnalysisGroup!"); sys::SmartScopedWriter Guard(Lock); - + // Make sure we keep track of the fact that the implementation implements // the interface. ImplementationInfo->addInterfaceImplemented(InterfaceInfo); - AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo]; - assert(AGI.Implementations.count(ImplementationInfo) == 0 && - "Cannot add a pass to the same analysis group more than once!"); - AGI.Implementations.insert(ImplementationInfo); if (isDefault) { assert(InterfaceInfo->getNormalCtor() == nullptr && "Default implementation for analysis group already specified!"); - assert(ImplementationInfo->getNormalCtor() && - "Cannot specify pass as default if it does not have a default ctor"); + assert( + ImplementationInfo->getNormalCtor() && + "Cannot specify pass as default if it does not have a default ctor"); InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor()); InterfaceInfo->setTargetMachineCtor( ImplementationInfo->getTargetMachineCtor()); } } - + if (ShouldFree) ToFree.push_back(std::unique_ptr(&Registeree)); } @@ -140,7 +124,7 @@ void PassRegistry::addRegistrationListener(PassRegistrationListener *L) { void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) { sys::SmartScopedWriter Guard(Lock); - + auto I = std::find(Listeners.begin(), Listeners.end(), L); Listeners.erase(I); } diff --git a/lib/IR/Statepoint.cpp b/lib/IR/Statepoint.cpp new file mode 100644 index 0000000..270c016 --- /dev/null +++ b/lib/IR/Statepoint.cpp @@ -0,0 +1,61 @@ +//===-- IR/Statepoint.cpp -- gc.statepoint utilities --- -----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/Function.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Statepoint.h" +#include "llvm/Support/CommandLine.h" + +using namespace std; +using namespace llvm; + +bool llvm::isStatepoint(const ImmutableCallSite &CS) { + const Function *F = CS.getCalledFunction(); + return (F && F->getIntrinsicID() == Intrinsic::experimental_gc_statepoint); +} +bool llvm::isStatepoint(const Instruction *inst) { + if (isa(inst) || isa(inst)) { + ImmutableCallSite CS(inst); + return isStatepoint(CS); + } + return false; +} +bool llvm::isStatepoint(const Instruction &inst) { + return isStatepoint(&inst); +} + +bool llvm::isGCRelocate(const ImmutableCallSite &CS) { + return isGCRelocate(CS.getInstruction()); +} +bool llvm::isGCRelocate(const Instruction *inst) { + if (const CallInst *call = dyn_cast(inst)) { + if (const Function *F = call->getCalledFunction()) { + return F->getIntrinsicID() == Intrinsic::experimental_gc_relocate; + } + } + return false; +} + +bool llvm::isGCResult(const ImmutableCallSite &CS) { + return isGCResult(CS.getInstruction()); +} +bool llvm::isGCResult(const Instruction *inst) { + if (const CallInst *call = dyn_cast(inst)) { + if (Function *F = call->getCalledFunction()) { + return (F->getIntrinsicID() == Intrinsic::experimental_gc_result_int || + F->getIntrinsicID() == Intrinsic::experimental_gc_result_float || + F->getIntrinsicID() == Intrinsic::experimental_gc_result_ptr); + } + } + return false; +} diff --git a/lib/IR/SymbolTableListTraitsImpl.h b/lib/IR/SymbolTableListTraitsImpl.h index 8302597..a18f982 100644 --- a/lib/IR/SymbolTableListTraitsImpl.h +++ b/lib/IR/SymbolTableListTraitsImpl.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYMBOLTABLELISTTRAITS_IMPL_H -#define LLVM_SYMBOLTABLELISTTRAITS_IMPL_H +#ifndef LLVM_LIB_IR_SYMBOLTABLELISTTRAITSIMPL_H +#define LLVM_LIB_IR_SYMBOLTABLELISTTRAITSIMPL_H #include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/ValueSymbolTable.h" diff --git a/lib/IR/Type.cpp b/lib/IR/Type.cpp index 1efde47..889705e 100644 --- a/lib/IR/Type.cpp +++ b/lib/IR/Type.cpp @@ -89,9 +89,13 @@ bool Type::canLosslesslyBitCastTo(Type *Ty) const { // At this point we have only various mismatches of the first class types // remaining and ptr->ptr. Just select the lossless conversions. Everything - // else is not lossless. - if (this->isPointerTy()) - return Ty->isPointerTy(); + // else is not lossless. Conservatively assume we can't losslessly convert + // between pointers with different address spaces. + if (const PointerType *PTy = dyn_cast(this)) { + if (const PointerType *OtherPTy = dyn_cast(Ty)) + return PTy->getAddressSpace() == OtherPTy->getAddressSpace(); + return false; + } return false; // Other types have no identity values } @@ -155,7 +159,7 @@ int Type::getFPMantissaWidth() const { /// isSizedDerivedType - Derived types like structures and arrays are sized /// iff all of the members of the type are sized as well. Since asking for /// their size is relatively uncommon, move this operation out of line. -bool Type::isSizedDerivedType(SmallPtrSet *Visited) const { +bool Type::isSizedDerivedType(SmallPtrSetImpl *Visited) const { if (const ArrayType *ATy = dyn_cast(this)) return ATy->getElementType()->isSized(Visited); @@ -356,8 +360,7 @@ FunctionType *FunctionType::get(Type *ReturnType, ArrayRef Params, bool isVarArg) { LLVMContextImpl *pImpl = ReturnType->getContext().pImpl; FunctionTypeKeyInfo::KeyTy Key(ReturnType, Params, isVarArg); - LLVMContextImpl::FunctionTypeMap::iterator I = - pImpl->FunctionTypes.find_as(Key); + auto I = pImpl->FunctionTypes.find_as(Key); FunctionType *FT; if (I == pImpl->FunctionTypes.end()) { @@ -365,9 +368,9 @@ FunctionType *FunctionType::get(Type *ReturnType, Allocate(sizeof(FunctionType) + sizeof(Type*) * (Params.size() + 1), AlignOf::Alignment); new (FT) FunctionType(ReturnType, Params, isVarArg); - pImpl->FunctionTypes[FT] = true; + pImpl->FunctionTypes.insert(FT); } else { - FT = I->first; + FT = *I; } return FT; @@ -400,8 +403,7 @@ StructType *StructType::get(LLVMContext &Context, ArrayRef ETypes, bool isPacked) { LLVMContextImpl *pImpl = Context.pImpl; AnonStructTypeKeyInfo::KeyTy Key(ETypes, isPacked); - LLVMContextImpl::StructTypeMap::iterator I = - pImpl->AnonStructTypes.find_as(Key); + auto I = pImpl->AnonStructTypes.find_as(Key); StructType *ST; if (I == pImpl->AnonStructTypes.end()) { @@ -409,9 +411,9 @@ StructType *StructType::get(LLVMContext &Context, ArrayRef ETypes, ST = new (Context.pImpl->TypeAllocator) StructType(Context); ST->setSubclassData(SCDB_IsLiteral); // Literal struct. ST->setBody(ETypes, isPacked); - Context.pImpl->AnonStructTypes[ST] = true; + Context.pImpl->AnonStructTypes.insert(ST); } else { - ST = I->first; + ST = *I; } return ST; @@ -454,10 +456,11 @@ void StructType::setName(StringRef Name) { } // Look up the entry for the name. - EntryTy *Entry = &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name); - + auto IterBool = + getContext().pImpl->NamedStructTypes.insert(std::make_pair(Name, this)); + // While we have a name collision, try a random rename. - if (Entry->getValue()) { + if (!IterBool.second) { SmallString<64> TempStr(Name); TempStr.push_back('.'); raw_svector_ostream TmpStream(TempStr); @@ -467,19 +470,16 @@ void StructType::setName(StringRef Name) { TempStr.resize(NameSize + 1); TmpStream.resync(); TmpStream << getContext().pImpl->NamedStructTypesUniqueID++; - - Entry = &getContext().pImpl-> - NamedStructTypes.GetOrCreateValue(TmpStream.str()); - } while (Entry->getValue()); - } - // Okay, we found an entry that isn't used. It's us! - Entry->setValue(this); + IterBool = getContext().pImpl->NamedStructTypes.insert( + std::make_pair(TmpStream.str(), this)); + } while (!IterBool.second); + } // Delete the old string data. if (SymbolTableEntry) ((EntryTy *)SymbolTableEntry)->Destroy(SymbolTable.getAllocator()); - SymbolTableEntry = Entry; + SymbolTableEntry = &*IterBool.first; } //===----------------------------------------------------------------------===// @@ -506,7 +506,9 @@ StructType *StructType::get(Type *type, ...) { StructFields.push_back(type); type = va_arg(ap, llvm::Type*); } - return llvm::StructType::get(Ctx, StructFields); + auto *Ret = llvm::StructType::get(Ctx, StructFields); + va_end(ap); + return Ret; } StructType *StructType::create(LLVMContext &Context, ArrayRef Elements, @@ -547,16 +549,18 @@ StructType *StructType::create(StringRef Name, Type *type, ...) { StructFields.push_back(type); type = va_arg(ap, llvm::Type*); } - return llvm::StructType::create(Ctx, StructFields, Name); + auto *Ret = llvm::StructType::create(Ctx, StructFields, Name); + va_end(ap); + return Ret; } -bool StructType::isSized(SmallPtrSet *Visited) const { +bool StructType::isSized(SmallPtrSetImpl *Visited) const { if ((getSubclassData() & SCDB_IsSized) != 0) return true; if (isOpaque()) return false; - if (Visited && !Visited->insert(this)) + if (Visited && !Visited->insert(this).second) return false; // Okay, our struct is sized if all of the elements are, but if one of the @@ -591,6 +595,7 @@ void StructType::setBody(Type *type, ...) { type = va_arg(ap, llvm::Type*); } setBody(StructFields); + va_end(ap); } bool StructType::isValidElementType(Type *ElemTy) { diff --git a/lib/IR/TypeFinder.cpp b/lib/IR/TypeFinder.cpp index 689b903..e2fb8f8 100644 --- a/lib/IR/TypeFinder.cpp +++ b/lib/IR/TypeFinder.cpp @@ -40,13 +40,16 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { } // Get types from functions. - SmallVector, 4> MDForInst; + SmallVector, 4> MDForInst; for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) { incorporateType(FI->getType()); if (FI->hasPrefixData()) incorporateValue(FI->getPrefixData()); + if (FI->hasPrologueData()) + incorporateValue(FI->getPrologueData()); + // First incorporate the arguments. for (Function::const_arg_iterator AI = FI->arg_begin(), AE = FI->arg_end(); AI != AE; ++AI) @@ -122,8 +125,13 @@ void TypeFinder::incorporateType(Type *Ty) { /// other ways. GlobalValues, basic blocks, instructions, and inst operands are /// all explicitly enumerated. void TypeFinder::incorporateValue(const Value *V) { - if (const MDNode *M = dyn_cast(V)) - return incorporateMDNode(M); + if (const auto *M = dyn_cast(V)) { + if (const auto *N = dyn_cast(M->getMetadata())) + return incorporateMDNode(N); + if (const auto *MDV = dyn_cast(M->getMetadata())) + return incorporateValue(MDV->getValue()); + return; + } if (!isa(V) || isa(V)) return; @@ -149,11 +157,21 @@ void TypeFinder::incorporateValue(const Value *V) { /// find types hiding within. void TypeFinder::incorporateMDNode(const MDNode *V) { // Already visited? - if (!VisitedConstants.insert(V).second) + if (!VisitedMetadata.insert(V).second) return; // Look in operands for types. - for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i) - if (Value *Op = V->getOperand(i)) - incorporateValue(Op); + for (unsigned i = 0, e = V->getNumOperands(); i != e; ++i) { + Metadata *Op = V->getOperand(i); + if (!Op) + continue; + if (auto *N = dyn_cast(Op)) { + incorporateMDNode(N); + continue; + } + if (auto *C = dyn_cast(Op)) { + incorporateValue(C->getValue()); + continue; + } + } } diff --git a/lib/IR/Use.cpp b/lib/IR/Use.cpp index 047861c..cae845d 100644 --- a/lib/IR/Use.cpp +++ b/lib/IR/Use.cpp @@ -52,7 +52,7 @@ unsigned Use::getOperandNo() const { // Sets up the waymarking algorithm's tags for a series of Uses. See the // algorithm details here: // -// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout +// http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm // Use *Use::initTags(Use *const Start, Use *Stop) { ptrdiff_t Done = 0; diff --git a/lib/IR/UseListOrder.cpp b/lib/IR/UseListOrder.cpp new file mode 100644 index 0000000..d064e67 --- /dev/null +++ b/lib/IR/UseListOrder.cpp @@ -0,0 +1,43 @@ +//===- UseListOrder.cpp - Implement Use List Order ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Implement structures and command-line options for preserving use-list order. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/UseListOrder.h" +#include "llvm/Support/CommandLine.h" + +using namespace llvm; + +static cl::opt PreserveBitcodeUseListOrder( + "preserve-bc-use-list-order", + cl::desc("Experimental support to preserve bitcode use-list order."), + cl::init(false), cl::Hidden); + +static cl::opt PreserveAssemblyUseListOrder( + "preserve-ll-use-list-order", + cl::desc("Experimental support to preserve assembly use-list order."), + cl::init(false), cl::Hidden); + +bool llvm::shouldPreserveBitcodeUseListOrder() { + return PreserveBitcodeUseListOrder; +} + +bool llvm::shouldPreserveAssemblyUseListOrder() { + return PreserveAssemblyUseListOrder; +} + +void llvm::setPreserveBitcodeUseListOrder(bool ShouldPreserve) { + PreserveBitcodeUseListOrder = ShouldPreserve; +} + +void llvm::setPreserveAssemblyUseListOrder(bool ShouldPreserve) { + PreserveAssemblyUseListOrder = ShouldPreserve; +} diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp index 9406828..ee83eacf 100644 --- a/lib/IR/User.cpp +++ b/lib/IR/User.cpp @@ -20,9 +20,6 @@ namespace llvm { void User::anchor() {} -// replaceUsesOfWith - Replaces all references to the "From" definition with -// references to the "To" definition. -// void User::replaceUsesOfWith(Value *From, Value *To) { if (From == To) return; // Duh what? diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 1ab2183..5f7e258 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -23,7 +23,6 @@ #include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/LeakDetector.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/ValueHandle.h" @@ -44,8 +43,8 @@ static inline Type *checkType(Type *Ty) { } Value::Value(Type *ty, unsigned scid) - : VTy(checkType(ty)), UseList(nullptr), Name(nullptr), SubclassID(scid), - HasValueHandle(0), SubclassOptionalData(0), SubclassData(0) { + : VTy(checkType(ty)), UseList(nullptr), SubclassID(scid), HasValueHandle(0), + SubclassOptionalData(0), SubclassData(0), NumOperands(0) { // FIXME: Why isn't this in the subclass gunk?? // Note, we cannot call isa before the CallInst has been // constructed. @@ -62,6 +61,8 @@ Value::~Value() { // Notify all ValueHandles (if present) that this value is going away. if (HasValueHandle) ValueHandleBase::ValueIsDeleted(this); + if (isUsedByMetadata()) + ValueAsMetadata::handleDeletion(this); #ifndef NDEBUG // Only in -g mode... // Check to make sure that there are no uses of this value that are still @@ -81,15 +82,16 @@ Value::~Value() { // If this value is named, destroy the name. This should not be in a symtab // at this point. - if (Name && SubclassID != MDStringVal) - Name->Destroy(); + destroyValueName(); +} - // There should be no uses of this object anymore, remove it. - LeakDetector::removeGarbageObject(this); +void Value::destroyValueName() { + ValueName *Name = getValueName(); + if (Name) + Name->Destroy(); + setValueName(nullptr); } -/// hasNUses - Return true if this Value has exactly N users. -/// bool Value::hasNUses(unsigned N) const { const_use_iterator UI = use_begin(), E = use_end(); @@ -98,9 +100,6 @@ bool Value::hasNUses(unsigned N) const { return UI == E; } -/// hasNUsesOrMore - Return true if this value has N users or more. This is -/// logically equivalent to getNumUses() >= N. -/// bool Value::hasNUsesOrMore(unsigned N) const { const_use_iterator UI = use_begin(), E = use_end(); @@ -110,8 +109,6 @@ bool Value::hasNUsesOrMore(unsigned N) const { return true; } -/// isUsedInBasicBlock - Return true if this value is used in the specified -/// basic block. bool Value::isUsedInBasicBlock(const BasicBlock *BB) const { // This can be computed either by scanning the instructions in BB, or by // scanning the use list of this Value. Both lists can be very long, but @@ -133,10 +130,6 @@ bool Value::isUsedInBasicBlock(const BasicBlock *BB) const { return false; } - -/// getNumUses - This method computes the number of uses of this Value. This -/// is a linear time operation. Use hasOneUse or hasNUses to check for specific -/// values. unsigned Value::getNumUses() const { return (unsigned)std::distance(use_begin(), use_end()); } @@ -156,9 +149,7 @@ static bool getSymTab(Value *V, ValueSymbolTable *&ST) { } else if (Argument *A = dyn_cast(V)) { if (Function *P = A->getParent()) ST = &P->getValueSymbolTable(); - } else if (isa(V)) - return true; - else { + } else { assert(isa(V) && "Unknown value type!"); return true; // no name is setable for this. } @@ -169,14 +160,12 @@ StringRef Value::getName() const { // Make sure the empty string is still a C string. For historical reasons, // some clients want to call .data() on the result and expect it to be null // terminated. - if (!Name) return StringRef("", 0); - return Name->getKey(); + if (!getValueName()) + return StringRef("", 0); + return getValueName()->getKey(); } void Value::setName(const Twine &NewName) { - assert(SubclassID != MDStringVal && - "Cannot set the name of MDString with this method!"); - // Fast path for common IRBuilder case of setName("") when there is no name. if (NewName.isTriviallyEmpty() && !hasName()) return; @@ -203,20 +192,17 @@ void Value::setName(const Twine &NewName) { if (!ST) { // No symbol table to update? Just do the change. if (NameRef.empty()) { // Free the name for this value. - Name->Destroy(); - Name = nullptr; + destroyValueName(); return; } - if (Name) - Name->Destroy(); - // NOTE: Could optimize for the case the name is shrinking to not deallocate // then reallocated. + destroyValueName(); // Create the new name. - Name = ValueName::Create(NameRef); - Name->setValue(this); + setValueName(ValueName::Create(NameRef)); + getValueName()->setValue(this); return; } @@ -224,24 +210,18 @@ void Value::setName(const Twine &NewName) { // then reallocated. if (hasName()) { // Remove old name. - ST->removeValueName(Name); - Name->Destroy(); - Name = nullptr; + ST->removeValueName(getValueName()); + destroyValueName(); if (NameRef.empty()) return; } // Name is changing to something new. - Name = ST->createValueName(NameRef, this); + setValueName(ST->createValueName(NameRef, this)); } - -/// takeName - transfer the name from V to this value, setting V's name to -/// empty. It is an error to call V->takeName(V). void Value::takeName(Value *V) { - assert(SubclassID != MDStringVal && "Cannot take the name of an MDString!"); - ValueSymbolTable *ST = nullptr; // If this value has a name, drop it. if (hasName()) { @@ -255,9 +235,8 @@ void Value::takeName(Value *V) { // Remove old name. if (ST) - ST->removeValueName(Name); - Name->Destroy(); - Name = nullptr; + ST->removeValueName(getValueName()); + destroyValueName(); } // Now we know that this has no name. @@ -283,9 +262,9 @@ void Value::takeName(Value *V) { // This works even if both values have no symtab yet. if (ST == VST) { // Take the name! - Name = V->Name; - V->Name = nullptr; - Name->setValue(this); + setValueName(V->getValueName()); + V->setValueName(nullptr); + getValueName()->setValue(this); return; } @@ -293,19 +272,19 @@ void Value::takeName(Value *V) { // then reinsert it into ST. if (VST) - VST->removeValueName(V->Name); - Name = V->Name; - V->Name = nullptr; - Name->setValue(this); + VST->removeValueName(V->getValueName()); + setValueName(V->getValueName()); + V->setValueName(nullptr); + getValueName()->setValue(this); if (ST) ST->reinsertValue(this); } #ifndef NDEBUG -static bool contains(SmallPtrSet &Cache, ConstantExpr *Expr, +static bool contains(SmallPtrSetImpl &Cache, ConstantExpr *Expr, Constant *C) { - if (!Cache.insert(Expr)) + if (!Cache.insert(Expr).second) return false; for (auto &O : Expr->operands()) { @@ -347,6 +326,8 @@ void Value::replaceAllUsesWith(Value *New) { // Notify all ValueHandles (if present) that this value is going away. if (HasValueHandle) ValueHandleBase::ValueIsRAUWd(this, New); + if (isUsedByMetadata()) + ValueAsMetadata::handleRAUW(this, New); while (!use_empty()) { Use &U = *UseList; @@ -366,6 +347,28 @@ void Value::replaceAllUsesWith(Value *New) { BB->replaceSuccessorsPhiUsesWith(cast(New)); } +// Like replaceAllUsesWith except it does not handle constants or basic blocks. +// This routine leaves uses within BB. +void Value::replaceUsesOutsideBlock(Value *New, BasicBlock *BB) { + assert(New && "Value::replaceUsesOutsideBlock(, BB) is invalid!"); + assert(!contains(New, this) && + "this->replaceUsesOutsideBlock(expr(this), BB) is NOT valid!"); + assert(New->getType() == getType() && + "replaceUses of value with new value of different type!"); + assert(BB && "Basic block that may contain a use of 'New' must be defined\n"); + + use_iterator UI = use_begin(), E = use_end(); + for (; UI != E;) { + Use &U = *UI; + ++UI; + auto *Usr = dyn_cast(U.getUser()); + if (Usr && Usr->getParent() == BB) + continue; + U.set(New); + } + return; +} + namespace { // Various metrics for how much to strip off of pointers. enum PointerStripKind { @@ -414,7 +417,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) { return V; } assert(V->getType()->isPointerTy() && "Unexpected operand type!"); - } while (Visited.insert(V)); + } while (Visited.insert(V).second); return V; } @@ -464,7 +467,7 @@ Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL, return V; } assert(V->getType()->isPointerTy() && "Unexpected operand type!"); - } while (Visited.insert(V)); + } while (Visited.insert(V).second); return V; } @@ -473,10 +476,12 @@ Value *Value::stripInBoundsOffsets() { return stripPointerCastsAndOffsets(this); } -/// isDereferenceablePointer - Test if this value is always a pointer to -/// allocated and suitably aligned memory for a simple load or store. +/// \brief Check if Value is always a dereferenceable pointer. +/// +/// Test if V is always a pointer to allocated and suitably aligned memory for +/// a simple load or store. static bool isDereferenceablePointer(const Value *V, const DataLayout *DL, - SmallPtrSet &Visited) { + SmallPtrSetImpl &Visited) { // Note that it is not safe to speculate into a malloc'd region because // malloc may return null. @@ -533,7 +538,7 @@ static bool isDereferenceablePointer(const Value *V, const DataLayout *DL, // For GEPs, determine if the indexing lands within the allocated object. if (const GEPOperator *GEP = dyn_cast(V)) { // Conservatively require that the base pointer be fully dereferenceable. - if (!Visited.insert(GEP->getOperand(0))) + if (!Visited.insert(GEP->getOperand(0)).second) return false; if (!isDereferenceablePointer(GEP->getOperand(0), DL, Visited)) return false; @@ -572,8 +577,6 @@ static bool isDereferenceablePointer(const Value *V, const DataLayout *DL, return false; } -/// isDereferenceablePointer - Test if this value is always a pointer to -/// allocated and suitably aligned memory for a simple load or store. bool Value::isDereferenceablePointer(const DataLayout *DL) const { // When dereferenceability information is provided by a dereferenceable // attribute, we know exactly how many bytes are dereferenceable. If we can @@ -600,10 +603,6 @@ bool Value::isDereferenceablePointer(const DataLayout *DL) const { return ::isDereferenceablePointer(this, DL, Visited); } -/// DoPHITranslation - If this value is a PHI node with CurBB as its parent, -/// return the value in the PHI node corresponding to PredBB. If not, return -/// ourself. This is useful if you want to know the value something has in a -/// predecessor block. Value *Value::DoPHITranslation(const BasicBlock *CurBB, const BasicBlock *PredBB) { PHINode *PN = dyn_cast(this); @@ -614,12 +613,29 @@ Value *Value::DoPHITranslation(const BasicBlock *CurBB, LLVMContext &Value::getContext() const { return VTy->getContext(); } +void Value::reverseUseList() { + if (!UseList || !UseList->Next) + // No need to reverse 0 or 1 uses. + return; + + Use *Head = UseList; + Use *Current = UseList->Next; + Head->Next = nullptr; + while (Current) { + Use *Next = Current->Next; + Current->Next = Head; + Head->setPrev(&Current->Next); + Head = Current; + Current = Next; + } + UseList = Head; + Head->setPrev(&UseList); +} + //===----------------------------------------------------------------------===// // ValueHandleBase Class //===----------------------------------------------------------------------===// -/// AddToExistingUseList - Add this ValueHandle to the use list for VP, where -/// List is known to point into the existing use list. void ValueHandleBase::AddToExistingUseList(ValueHandleBase **List) { assert(List && "Handle list is null?"); @@ -629,7 +645,7 @@ void ValueHandleBase::AddToExistingUseList(ValueHandleBase **List) { setPrevPtr(List); if (Next) { Next->setPrevPtr(&Next); - assert(VP.getPointer() == Next->VP.getPointer() && "Added to wrong list?"); + assert(V == Next->V && "Added to wrong list?"); } } @@ -643,16 +659,15 @@ void ValueHandleBase::AddToExistingUseListAfter(ValueHandleBase *List) { Next->setPrevPtr(&Next); } -/// AddToUseList - Add this ValueHandle to the use list for VP. void ValueHandleBase::AddToUseList() { - assert(VP.getPointer() && "Null pointer doesn't have a use list!"); + assert(V && "Null pointer doesn't have a use list!"); - LLVMContextImpl *pImpl = VP.getPointer()->getContext().pImpl; + LLVMContextImpl *pImpl = V->getContext().pImpl; - if (VP.getPointer()->HasValueHandle) { + if (V->HasValueHandle) { // If this value already has a ValueHandle, then it must be in the // ValueHandles map already. - ValueHandleBase *&Entry = pImpl->ValueHandles[VP.getPointer()]; + ValueHandleBase *&Entry = pImpl->ValueHandles[V]; assert(Entry && "Value doesn't have any handles?"); AddToExistingUseList(&Entry); return; @@ -666,10 +681,10 @@ void ValueHandleBase::AddToUseList() { DenseMap &Handles = pImpl->ValueHandles; const void *OldBucketPtr = Handles.getPointerIntoBucketsArray(); - ValueHandleBase *&Entry = Handles[VP.getPointer()]; + ValueHandleBase *&Entry = Handles[V]; assert(!Entry && "Value really did already have handles?"); AddToExistingUseList(&Entry); - VP.getPointer()->HasValueHandle = true; + V->HasValueHandle = true; // If reallocation didn't happen or if this was the first insertion, don't // walk the table. @@ -681,15 +696,14 @@ void ValueHandleBase::AddToUseList() { // Okay, reallocation did happen. Fix the Prev Pointers. for (DenseMap::iterator I = Handles.begin(), E = Handles.end(); I != E; ++I) { - assert(I->second && I->first == I->second->VP.getPointer() && + assert(I->second && I->first == I->second->V && "List invariant broken!"); I->second->setPrevPtr(&I->second); } } -/// RemoveFromUseList - Remove this ValueHandle from its current use list. void ValueHandleBase::RemoveFromUseList() { - assert(VP.getPointer() && VP.getPointer()->HasValueHandle && + assert(V && V->HasValueHandle && "Pointer doesn't have a use list!"); // Unlink this from its use list. @@ -706,11 +720,11 @@ void ValueHandleBase::RemoveFromUseList() { // If the Next pointer was null, then it is possible that this was the last // ValueHandle watching VP. If so, delete its entry from the ValueHandles // map. - LLVMContextImpl *pImpl = VP.getPointer()->getContext().pImpl; + LLVMContextImpl *pImpl = V->getContext().pImpl; DenseMap &Handles = pImpl->ValueHandles; if (Handles.isPointerIntoBucketsArray(PrevPtr)) { - Handles.erase(VP.getPointer()); - VP.getPointer()->HasValueHandle = false; + Handles.erase(V); + V->HasValueHandle = false; } } @@ -775,6 +789,8 @@ void ValueHandleBase::ValueIsDeleted(Value *V) { void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) { assert(Old->HasValueHandle &&"Should only be called if ValueHandles present"); assert(Old != New && "Changing value into itself!"); + assert(Old->getType() == New->getType() && + "replaceAllUses of value with new value of different type!"); // Get the linked list base, which is guaranteed to exist since the // HasValueHandle flag is set. diff --git a/lib/IR/ValueSymbolTable.cpp b/lib/IR/ValueSymbolTable.cpp index e9e979a..4f078f0 100644 --- a/lib/IR/ValueSymbolTable.cpp +++ b/lib/IR/ValueSymbolTable.cpp @@ -38,8 +38,8 @@ void ValueSymbolTable::reinsertValue(Value* V) { assert(V->hasName() && "Can't insert nameless Value into symbol table"); // Try inserting the name, assuming it won't conflict. - if (vmap.insert(V->Name)) { - //DEBUG(dbgs() << " Inserted value: " << V->Name << ": " << *V << "\n"); + if (vmap.insert(V->getValueName())) { + //DEBUG(dbgs() << " Inserted value: " << V->getValueName() << ": " << *V << "\n"); return; } @@ -47,8 +47,8 @@ void ValueSymbolTable::reinsertValue(Value* V) { SmallString<256> UniqueName(V->getName().begin(), V->getName().end()); // The name is too already used, just free it so we can allocate a new name. - V->Name->Destroy(); - + V->getValueName()->Destroy(); + unsigned BaseSize = UniqueName.size(); while (1) { // Trim any suffix off and append the next number. @@ -56,11 +56,10 @@ void ValueSymbolTable::reinsertValue(Value* V) { raw_svector_ostream(UniqueName) << ++LastUnique; // Try insert the vmap entry with this suffix. - ValueName &NewName = vmap.GetOrCreateValue(UniqueName); - if (!NewName.getValue()) { + auto IterBool = vmap.insert(std::make_pair(UniqueName, V)); + if (IterBool.second) { // Newly inserted name. Success! - NewName.setValue(V); - V->Name = &NewName; + V->setValueName(&*IterBool.first); //DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << "\n"); return; } @@ -78,12 +77,11 @@ void ValueSymbolTable::removeValueName(ValueName *V) { /// auto-renames the name and returns that instead. ValueName *ValueSymbolTable::createValueName(StringRef Name, Value *V) { // In the common case, the name is not already in the symbol table. - ValueName &Entry = vmap.GetOrCreateValue(Name); - if (!Entry.getValue()) { - Entry.setValue(V); + auto IterBool = vmap.insert(std::make_pair(Name, V)); + if (IterBool.second) { //DEBUG(dbgs() << " Inserted value: " << Entry.getKeyData() << ": " // << *V << "\n"); - return &Entry; + return &*IterBool.first; } // Otherwise, there is a naming conflict. Rename this value. @@ -95,12 +93,11 @@ ValueName *ValueSymbolTable::createValueName(StringRef Name, Value *V) { raw_svector_ostream(UniqueName) << ++LastUnique; // Try insert the vmap entry with this suffix. - ValueName &NewName = vmap.GetOrCreateValue(UniqueName); - if (!NewName.getValue()) { - // Newly inserted name. Success! - NewName.setValue(V); - //DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << "\n"); - return &NewName; + auto IterBool = vmap.insert(std::make_pair(UniqueName, V)); + if (IterBool.second) { + // DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << + // "\n"); + return &*IterBool.first; } } } diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 9cf911b..4bf2d1a 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -68,6 +68,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/Statepoint.h" #include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -101,6 +102,13 @@ struct VerifierSupport { } } + void WriteMetadata(const Metadata *MD) { + if (!MD) + return; + MD->printAsOperand(OS, true, M); + OS << '\n'; + } + void WriteType(Type *T) { if (!T) return; @@ -127,6 +135,24 @@ struct VerifierSupport { Broken = true; } + void CheckFailed(const Twine &Message, const Metadata *V1, const Metadata *V2, + const Metadata *V3 = nullptr, const Metadata *V4 = nullptr) { + OS << Message.str() << "\n"; + WriteMetadata(V1); + WriteMetadata(V2); + WriteMetadata(V3); + WriteMetadata(V4); + Broken = true; + } + + void CheckFailed(const Twine &Message, const Metadata *V1, + const Value *V2 = nullptr) { + OS << Message.str() << "\n"; + WriteMetadata(V1); + WriteValue(V2); + Broken = true; + } + void CheckFailed(const Twine &Message, const Value *V1, Type *T2, const Value *V3 = nullptr) { OS << Message.str() << "\n"; @@ -155,7 +181,6 @@ class Verifier : public InstVisitor, VerifierSupport { friend class InstVisitor; LLVMContext *Context; - const DataLayout *DL; DominatorTree DT; /// \brief When verifying a basic block, keep track of all of the @@ -166,17 +191,21 @@ class Verifier : public InstVisitor, VerifierSupport { SmallPtrSet InstsInThisBlock; /// \brief Keep track of the metadata nodes that have been checked already. - SmallPtrSet MDNodes; + SmallPtrSet MDNodes; /// \brief The personality function referenced by the LandingPadInsts. /// All LandingPadInsts within the same function must use the same /// personality function. const Value *PersonalityFn; + /// \brief Whether we've seen a call to @llvm.frameallocate in this function + /// already. + bool SawFrameAllocate; + public: explicit Verifier(raw_ostream &OS = dbgs()) - : VerifierSupport(OS), Context(nullptr), DL(nullptr), - PersonalityFn(nullptr) {} + : VerifierSupport(OS), Context(nullptr), PersonalityFn(nullptr), + SawFrameAllocate(false) {} bool verify(const Function &F) { M = F.getParent(); @@ -211,6 +240,7 @@ public: visit(const_cast(F)); InstsInThisBlock.clear(); PersonalityFn = nullptr; + SawFrameAllocate = false; return !Broken; } @@ -257,10 +287,12 @@ private: void visitGlobalVariable(const GlobalVariable &GV); void visitGlobalAlias(const GlobalAlias &GA); void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C); - void visitAliaseeSubExpr(SmallPtrSet &Visited, + void visitAliaseeSubExpr(SmallPtrSetImpl &Visited, const GlobalAlias &A, const Constant &C); void visitNamedMDNode(const NamedMDNode &NMD); - void visitMDNode(MDNode &MD, Function *F); + void visitMDNode(MDNode &MD); + void visitMetadataAsValue(MetadataAsValue &MD, Function *F); + void visitValueAsMetadata(ValueAsMetadata &MD, Function *F); void visitComdat(const Comdat &C); void visitModuleIdents(const Module &M); void visitModuleFlags(const Module &M); @@ -269,6 +301,8 @@ private: SmallVectorImpl &Requirements); void visitFunction(const Function &F); void visitBasicBlock(BasicBlock &BB); + void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty); + // InstVisitor overrides... using InstVisitor::visit; @@ -335,7 +369,6 @@ private: void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, const Value *V); - void VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy); void VerifyConstantExprBitcastType(const ConstantExpr *CE); }; class DebugInfoVerifier : public VerifierSupport { @@ -375,8 +408,8 @@ void Verifier::visit(Instruction &I) { void Verifier::visitGlobalValue(const GlobalValue &GV) { - Assert1(!GV.isDeclaration() || GV.isMaterializable() || - GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(), + Assert1(!GV.isDeclaration() || GV.hasExternalLinkage() || + GV.hasExternalWeakLinkage(), "Global is external, but doesn't have external or weak linkage!", &GV); @@ -478,7 +511,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) { while (!WorkStack.empty()) { const Value *V = WorkStack.pop_back_val(); - if (!Visited.insert(V)) + if (!Visited.insert(V).second) continue; if (const User *U = dyn_cast(V)) { @@ -502,13 +535,13 @@ void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) { visitAliaseeSubExpr(Visited, GA, C); } -void Verifier::visitAliaseeSubExpr(SmallPtrSet &Visited, +void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl &Visited, const GlobalAlias &GA, const Constant &C) { if (const auto *GV = dyn_cast(&C)) { Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA); if (const auto *GA2 = dyn_cast(GV)) { - Assert1(Visited.insert(GA2), "Aliases cannot form a cycle", &GA); + Assert1(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA); Assert1(!GA2->mayBeOverridden(), "Alias cannot point to a weak alias", &GA); @@ -557,46 +590,77 @@ void Verifier::visitNamedMDNode(const NamedMDNode &NMD) { if (!MD) continue; - Assert1(!MD->isFunctionLocal(), - "Named metadata operand cannot be function local!", MD); - visitMDNode(*MD, nullptr); + visitMDNode(*MD); } } -void Verifier::visitMDNode(MDNode &MD, Function *F) { +void Verifier::visitMDNode(MDNode &MD) { // Only visit each node once. Metadata can be mutually recursive, so this // avoids infinite recursion here, as well as being an optimization. - if (!MDNodes.insert(&MD)) + if (!MDNodes.insert(&MD).second) return; for (unsigned i = 0, e = MD.getNumOperands(); i != e; ++i) { - Value *Op = MD.getOperand(i); + Metadata *Op = MD.getOperand(i); if (!Op) continue; - if (isa(Op) || isa(Op)) + Assert2(!isa(Op), "Invalid operand for global metadata!", + &MD, Op); + if (auto *N = dyn_cast(Op)) { + visitMDNode(*N); continue; - if (MDNode *N = dyn_cast(Op)) { - Assert2(MD.isFunctionLocal() || !N->isFunctionLocal(), - "Global metadata operand cannot be function local!", &MD, N); - visitMDNode(*N, F); + } + if (auto *V = dyn_cast(Op)) { + visitValueAsMetadata(*V, nullptr); continue; } - Assert2(MD.isFunctionLocal(), "Invalid operand for global metadata!", &MD, Op); - - // If this was an instruction, bb, or argument, verify that it is in the - // function that we expect. - Function *ActualF = nullptr; - if (Instruction *I = dyn_cast(Op)) - ActualF = I->getParent()->getParent(); - else if (BasicBlock *BB = dyn_cast(Op)) - ActualF = BB->getParent(); - else if (Argument *A = dyn_cast(Op)) - ActualF = A->getParent(); - assert(ActualF && "Unimplemented function local metadata case!"); - - Assert2(ActualF == F, "function-local metadata used in wrong function", - &MD, Op); } + + // Check these last, so we diagnose problems in operands first. + Assert1(!isa(MD), "Expected no forward declarations!", &MD); + Assert1(MD.isResolved(), "All nodes should be resolved!", &MD); +} + +void Verifier::visitValueAsMetadata(ValueAsMetadata &MD, Function *F) { + Assert1(MD.getValue(), "Expected valid value", &MD); + Assert2(!MD.getValue()->getType()->isMetadataTy(), + "Unexpected metadata round-trip through values", &MD, MD.getValue()); + + auto *L = dyn_cast(&MD); + if (!L) + return; + + Assert1(F, "function-local metadata used outside a function", L); + + // If this was an instruction, bb, or argument, verify that it is in the + // function that we expect. + Function *ActualF = nullptr; + if (Instruction *I = dyn_cast(L->getValue())) { + Assert2(I->getParent(), "function-local metadata not in basic block", L, I); + ActualF = I->getParent()->getParent(); + } else if (BasicBlock *BB = dyn_cast(L->getValue())) + ActualF = BB->getParent(); + else if (Argument *A = dyn_cast(L->getValue())) + ActualF = A->getParent(); + assert(ActualF && "Unimplemented function local metadata case!"); + + Assert1(ActualF == F, "function-local metadata used in wrong function", L); +} + +void Verifier::visitMetadataAsValue(MetadataAsValue &MDV, Function *F) { + Metadata *MD = MDV.getMetadata(); + if (auto *N = dyn_cast(MD)) { + visitMDNode(*N); + return; + } + + // Only visit each node once. Metadata can be mutually recursive, so this + // avoids infinite recursion here, as well as being an optimization. + if (!MDNodes.insert(MD).second) + return; + + if (auto *V = dyn_cast(MD)) + visitValueAsMetadata(*V, F); } void Verifier::visitComdat(const Comdat &C) { @@ -647,7 +711,7 @@ void Verifier::visitModuleFlags(const Module &M) { for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { const MDNode *Requirement = Requirements[I]; const MDString *Flag = cast(Requirement->getOperand(0)); - const Value *ReqValue = Requirement->getOperand(1); + const Metadata *ReqValue = Requirement->getOperand(1); const MDNode *Op = SeenIDs.lookup(Flag); if (!Op) { @@ -673,24 +737,23 @@ Verifier::visitModuleFlag(const MDNode *Op, // constant int), the flag ID (an MDString), and the value. Assert1(Op->getNumOperands() == 3, "incorrect number of operands in module flag", Op); - ConstantInt *Behavior = dyn_cast(Op->getOperand(0)); + Module::ModFlagBehavior MFB; + if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { + Assert1( + mdconst::dyn_extract(Op->getOperand(0)), + "invalid behavior operand in module flag (expected constant integer)", + Op->getOperand(0)); + Assert1(false, + "invalid behavior operand in module flag (unexpected constant)", + Op->getOperand(0)); + } MDString *ID = dyn_cast(Op->getOperand(1)); - Assert1(Behavior, - "invalid behavior operand in module flag (expected constant integer)", - Op->getOperand(0)); - unsigned BehaviorValue = Behavior->getZExtValue(); Assert1(ID, "invalid ID operand in module flag (expected metadata string)", Op->getOperand(1)); // Sanity check the values for behaviors with additional requirements. - switch (BehaviorValue) { - default: - Assert1(false, - "invalid behavior operand in module flag (unexpected constant)", - Op->getOperand(0)); - break; - + switch (MFB) { case Module::Error: case Module::Warning: case Module::Override: @@ -726,7 +789,7 @@ Verifier::visitModuleFlag(const MDNode *Op, } // Unless this is a "requires" flag, check the ID is unique. - if (BehaviorValue != Module::Require) { + if (MFB != Module::Require) { bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; Assert1(Inserted, "module flag identifiers must be unique (or of 'require' type)", @@ -959,48 +1022,13 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs, } } -void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) { - // Get the size of the types in bits, we'll need this later - unsigned SrcBitSize = SrcTy->getPrimitiveSizeInBits(); - unsigned DestBitSize = DestTy->getPrimitiveSizeInBits(); - - // BitCast implies a no-op cast of type only. No bits change. - // However, you can't cast pointers to anything but pointers. - Assert1(SrcTy->isPointerTy() == DestTy->isPointerTy(), - "Bitcast requires both operands to be pointer or neither", V); - Assert1(SrcBitSize == DestBitSize, - "Bitcast requires types of same width", V); - - // Disallow aggregates. - Assert1(!SrcTy->isAggregateType(), - "Bitcast operand must not be aggregate", V); - Assert1(!DestTy->isAggregateType(), - "Bitcast type must not be aggregate", V); - - // Without datalayout, assume all address spaces are the same size. - // Don't check if both types are not pointers. - // Skip casts between scalars and vectors. - if (!DL || - !SrcTy->isPtrOrPtrVectorTy() || - !DestTy->isPtrOrPtrVectorTy() || - SrcTy->isVectorTy() != DestTy->isVectorTy()) { +void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) { + if (CE->getOpcode() != Instruction::BitCast) return; - } - - unsigned SrcAS = SrcTy->getPointerAddressSpace(); - unsigned DstAS = DestTy->getPointerAddressSpace(); - - Assert1(SrcAS == DstAS, - "Bitcasts between pointers of different address spaces is not legal." - "Use AddrSpaceCast instead.", V); -} -void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) { - if (CE->getOpcode() == Instruction::BitCast) { - Type *SrcTy = CE->getOperand(0)->getType(); - Type *DstTy = CE->getType(); - VerifyBitcastType(CE, DstTy, SrcTy); - } + Assert1(CastInst::castIsValid(Instruction::BitCast, CE->getOperand(0), + CE->getType()), + "Invalid bitcast", CE); } bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) { @@ -1055,20 +1083,19 @@ void Verifier::visitFunction(const Function &F) { "Attribute 'builtin' can only be applied to a callsite.", &F); // Check that this function meets the restrictions on this calling convention. + // Sometimes varargs is used for perfectly forwarding thunks, so some of these + // restrictions can be lifted. switch (F.getCallingConv()) { default: - break; case CallingConv::C: break; case CallingConv::Fast: case CallingConv::Cold: - case CallingConv::X86_FastCall: - case CallingConv::X86_ThisCall: case CallingConv::Intel_OCL_BI: case CallingConv::PTX_Kernel: case CallingConv::PTX_Device: - Assert1(!F.isVarArg(), - "Varargs functions must have C calling conventions!", &F); + Assert1(!F.isVarArg(), "Calling convention does not support varargs or " + "perfect forwarding!", &F); break; } @@ -1101,7 +1128,7 @@ void Verifier::visitFunction(const Function &F) { // Check the entry node const BasicBlock *Entry = &F.getEntryBlock(); - Assert1(pred_begin(Entry) == pred_end(Entry), + Assert1(pred_empty(Entry), "Entry block to function must not have predecessors!", Entry); // The address of the entry block cannot be taken, unless it is dead. @@ -1176,6 +1203,12 @@ void Verifier::visitBasicBlock(BasicBlock &BB) { } } } + + // Check that all instructions have their parent pointers set up correctly. + for (auto &I : BB) + { + Assert(I.getParent() == &BB, "Instruction has bogus parent pointer!"); + } } void Verifier::visitTerminatorInst(TerminatorInst &I) { @@ -1218,7 +1251,7 @@ void Verifier::visitSwitchInst(SwitchInst &SI) { for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) { Assert1(i.getCaseValue()->getType() == SwitchTy, "Switch constants must all be same type as switch value!", &SI); - Assert2(Constants.insert(i.getCaseValue()), + Assert2(Constants.insert(i.getCaseValue()).second, "Duplicate integer as switch case", &SI, i.getCaseValue()); } @@ -1476,9 +1509,9 @@ void Verifier::visitIntToPtrInst(IntToPtrInst &I) { } void Verifier::visitBitCastInst(BitCastInst &I) { - Type *SrcTy = I.getOperand(0)->getType(); - Type *DestTy = I.getType(); - VerifyBitcastType(&I, DestTy, SrcTy); + Assert1( + CastInst::castIsValid(Instruction::BitCast, I.getOperand(0), I.getType()), + "Invalid bitcast", &I); visitInstruction(I); } @@ -1887,6 +1920,57 @@ static bool isContiguous(const ConstantRange &A, const ConstantRange &B) { return A.getUpper() == B.getLower() || A.getLower() == B.getUpper(); } +void Verifier::visitRangeMetadata(Instruction& I, + MDNode* Range, Type* Ty) { + assert(Range && + Range == I.getMetadata(LLVMContext::MD_range) && + "precondition violation"); + + unsigned NumOperands = Range->getNumOperands(); + Assert1(NumOperands % 2 == 0, "Unfinished range!", Range); + unsigned NumRanges = NumOperands / 2; + Assert1(NumRanges >= 1, "It should have at least one range!", Range); + + ConstantRange LastRange(1); // Dummy initial value + for (unsigned i = 0; i < NumRanges; ++i) { + ConstantInt *Low = + mdconst::dyn_extract(Range->getOperand(2 * i)); + Assert1(Low, "The lower limit must be an integer!", Low); + ConstantInt *High = + mdconst::dyn_extract(Range->getOperand(2 * i + 1)); + Assert1(High, "The upper limit must be an integer!", High); + Assert1(High->getType() == Low->getType() && + High->getType() == Ty, "Range types must match instruction type!", + &I); + + APInt HighV = High->getValue(); + APInt LowV = Low->getValue(); + ConstantRange CurRange(LowV, HighV); + Assert1(!CurRange.isEmptySet() && !CurRange.isFullSet(), + "Range must not be empty!", Range); + if (i != 0) { + Assert1(CurRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert1(LowV.sgt(LastRange.getLower()), "Intervals are not in order", + Range); + Assert1(!isContiguous(CurRange, LastRange), "Intervals are contiguous", + Range); + } + LastRange = ConstantRange(LowV, HighV); + } + if (NumRanges > 2) { + APInt FirstLow = + mdconst::dyn_extract(Range->getOperand(0))->getValue(); + APInt FirstHigh = + mdconst::dyn_extract(Range->getOperand(1))->getValue(); + ConstantRange FirstRange(FirstLow, FirstHigh); + Assert1(FirstRange.intersectWith(LastRange).isEmptySet(), + "Intervals are overlapping", Range); + Assert1(!isContiguous(FirstRange, LastRange), "Intervals are contiguous", + Range); + } +} + void Verifier::visitLoadInst(LoadInst &LI) { PointerType *PTy = dyn_cast(LI.getOperand(0)->getType()); Assert1(PTy, "Load operand must be a pointer.", &LI); @@ -1914,52 +1998,6 @@ void Verifier::visitLoadInst(LoadInst &LI) { "Non-atomic load cannot have SynchronizationScope specified", &LI); } - if (MDNode *Range = LI.getMetadata(LLVMContext::MD_range)) { - unsigned NumOperands = Range->getNumOperands(); - Assert1(NumOperands % 2 == 0, "Unfinished range!", Range); - unsigned NumRanges = NumOperands / 2; - Assert1(NumRanges >= 1, "It should have at least one range!", Range); - - ConstantRange LastRange(1); // Dummy initial value - for (unsigned i = 0; i < NumRanges; ++i) { - ConstantInt *Low = dyn_cast(Range->getOperand(2*i)); - Assert1(Low, "The lower limit must be an integer!", Low); - ConstantInt *High = dyn_cast(Range->getOperand(2*i + 1)); - Assert1(High, "The upper limit must be an integer!", High); - Assert1(High->getType() == Low->getType() && - High->getType() == ElTy, "Range types must match load type!", - &LI); - - APInt HighV = High->getValue(); - APInt LowV = Low->getValue(); - ConstantRange CurRange(LowV, HighV); - Assert1(!CurRange.isEmptySet() && !CurRange.isFullSet(), - "Range must not be empty!", Range); - if (i != 0) { - Assert1(CurRange.intersectWith(LastRange).isEmptySet(), - "Intervals are overlapping", Range); - Assert1(LowV.sgt(LastRange.getLower()), "Intervals are not in order", - Range); - Assert1(!isContiguous(CurRange, LastRange), "Intervals are contiguous", - Range); - } - LastRange = ConstantRange(LowV, HighV); - } - if (NumRanges > 2) { - APInt FirstLow = - dyn_cast(Range->getOperand(0))->getValue(); - APInt FirstHigh = - dyn_cast(Range->getOperand(1))->getValue(); - ConstantRange FirstRange(FirstLow, FirstHigh); - Assert1(FirstRange.intersectWith(LastRange).isEmptySet(), - "Intervals are overlapping", Range); - Assert1(!isContiguous(FirstRange, LastRange), "Intervals are contiguous", - Range); - } - - - } - visitInstruction(LI); } @@ -2214,11 +2252,15 @@ void Verifier::visitInstruction(Instruction &I) { if (Function *F = dyn_cast(I.getOperand(i))) { // Check to make sure that the "address of" an intrinsic function is never // taken. - Assert1(!F->isIntrinsic() || i == (isa(I) ? e-1 : 0), + Assert1(!F->isIntrinsic() || i == (isa(I) ? e-1 : + isa(I) ? e-3 : 0), "Cannot take the address of an intrinsic!", &I); Assert1(!F->isIntrinsic() || isa(I) || - F->getIntrinsicID() == Intrinsic::donothing, - "Cannot invoke an intrinsinc other than donothing", &I); + F->getIntrinsicID() == Intrinsic::donothing || + F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void || + F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64, + "Cannot invoke an intrinsinc other than" + " donothing or patchpoint", &I); Assert1(F->getParent() == M, "Referencing function in another module!", &I); } else if (BasicBlock *OpBB = dyn_cast(I.getOperand(i))) { @@ -2246,7 +2288,7 @@ void Verifier::visitInstruction(Instruction &I) { while (!Stack.empty()) { const ConstantExpr *V = Stack.pop_back_val(); - if (!Visited.insert(V)) + if (!Visited.insert(V).second) continue; VerifyConstantExprBitcastType(V); @@ -2264,8 +2306,8 @@ void Verifier::visitInstruction(Instruction &I) { Assert1(I.getType()->isFPOrFPVectorTy(), "fpmath requires a floating point result!", &I); Assert1(MD->getNumOperands() == 1, "fpmath takes one operand!", &I); - Value *Op0 = MD->getOperand(0); - if (ConstantFP *CFP0 = dyn_cast_or_null(Op0)) { + if (ConstantFP *CFP0 = + mdconst::dyn_extract_or_null(MD->getOperand(0))) { APFloat Accuracy = CFP0->getValueAPF(); Assert1(Accuracy.isFiniteNonZero() && !Accuracy.isNegative(), "fpmath accuracy not a positive number!", &I); @@ -2274,9 +2316,19 @@ void Verifier::visitInstruction(Instruction &I) { } } - MDNode *MD = I.getMetadata(LLVMContext::MD_range); - Assert1(!MD || isa(I) || isa(I) || isa(I), - "Ranges are only for loads, calls and invokes!", &I); + if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) { + Assert1(isa(I) || isa(I) || isa(I), + "Ranges are only for loads, calls and invokes!", &I); + visitRangeMetadata(I, Range, I.getType()); + } + + if (I.getMetadata(LLVMContext::MD_nonnull)) { + Assert1(I.getType()->isPointerTy(), + "nonnull applies only to pointer types", &I); + Assert1(isa(I), + "nonnull applies only to load instructions, use attributes" + " for calls or invokes", &I); + } InstsInThisBlock.insert(&I); } @@ -2382,6 +2434,26 @@ bool Verifier::VerifyIntrinsicType(Type *Ty, !isa(ArgTys[D.getArgumentNumber()]) || VectorType::getHalfElementsVectorType( cast(ArgTys[D.getArgumentNumber()])) != Ty; + case IITDescriptor::SameVecWidthArgument: { + if (D.getArgumentNumber() >= ArgTys.size()) + return true; + VectorType * ReferenceType = + dyn_cast(ArgTys[D.getArgumentNumber()]); + VectorType *ThisArgType = dyn_cast(Ty); + if (!ThisArgType || !ReferenceType || + (ReferenceType->getVectorNumElements() != + ThisArgType->getVectorNumElements())) + return true; + return VerifyIntrinsicType(ThisArgType->getVectorElementType(), + Infos, ArgTys); + } + case IITDescriptor::PtrToArgument: { + if (D.getArgumentNumber() >= ArgTys.size()) + return true; + Type * ReferenceType = ArgTys[D.getArgumentNumber()]; + PointerType *ThisArgType = dyn_cast(Ty); + return (!ThisArgType || ThisArgType->getElementType() != ReferenceType); + } } llvm_unreachable("unhandled"); } @@ -2459,8 +2531,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { // If the intrinsic takes MDNode arguments, verify that they are either global // or are local to *this* function. for (unsigned i = 0, e = CI.getNumArgOperands(); i != e; ++i) - if (MDNode *MD = dyn_cast(CI.getArgOperand(i))) - visitMDNode(*MD, CI.getParent()->getParent()); + if (auto *MD = dyn_cast(CI.getArgOperand(i))) + visitMetadataAsValue(*MD, CI.getParent()->getParent()); switch (ID) { default: @@ -2472,11 +2544,8 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { "constant int", &CI); break; case Intrinsic::dbg_declare: { // llvm.dbg.declare - Assert1(CI.getArgOperand(0) && isa(CI.getArgOperand(0)), - "invalid llvm.dbg.declare intrinsic call 1", &CI); - MDNode *MD = cast(CI.getArgOperand(0)); - Assert1(MD->getNumOperands() == 1, - "invalid llvm.dbg.declare intrinsic call 2", &CI); + Assert1(CI.getArgOperand(0) && isa(CI.getArgOperand(0)), + "invalid llvm.dbg.declare intrinsic call 1", &CI); } break; case Intrinsic::memcpy: case Intrinsic::memmove: @@ -2536,7 +2605,189 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { Assert1(isa(CI.getArgOperand(1)), "llvm.invariant.end parameter #2 must be a constant integer", &CI); break; + + case Intrinsic::frameallocate: { + BasicBlock *BB = CI.getParent(); + Assert1(BB == &BB->getParent()->front(), + "llvm.frameallocate used outside of entry block", &CI); + Assert1(!SawFrameAllocate, + "multiple calls to llvm.frameallocate in one function", &CI); + SawFrameAllocate = true; + Assert1(isa(CI.getArgOperand(0)), + "llvm.frameallocate argument must be constant integer size", &CI); + break; + } + case Intrinsic::framerecover: { + Value *FnArg = CI.getArgOperand(0)->stripPointerCasts(); + Function *Fn = dyn_cast(FnArg); + Assert1(Fn && !Fn->isDeclaration(), "llvm.framerecover first " + "argument must be function defined in this module", &CI); + break; + } + + case Intrinsic::experimental_gc_statepoint: { + Assert1(!CI.doesNotAccessMemory() && + !CI.onlyReadsMemory(), + "gc.statepoint must read and write memory to preserve " + "reordering restrictions required by safepoint semantics", &CI); + Assert1(!CI.isInlineAsm(), + "gc.statepoint support for inline assembly unimplemented", &CI); + + const Value *Target = CI.getArgOperand(0); + const PointerType *PT = dyn_cast(Target->getType()); + Assert2(PT && PT->getElementType()->isFunctionTy(), + "gc.statepoint callee must be of function pointer type", + &CI, Target); + FunctionType *TargetFuncType = cast(PT->getElementType()); + Assert1(!TargetFuncType->isVarArg(), + "gc.statepoint support for var arg functions not implemented", &CI); + + const Value *NumCallArgsV = CI.getArgOperand(1); + Assert1(isa(NumCallArgsV), + "gc.statepoint number of arguments to underlying call " + "must be constant integer", &CI); + const int NumCallArgs = cast(NumCallArgsV)->getZExtValue(); + Assert1(NumCallArgs >= 0, + "gc.statepoint number of arguments to underlying call " + "must be positive", &CI); + Assert1(NumCallArgs == (int)TargetFuncType->getNumParams(), + "gc.statepoint mismatch in number of call args", &CI); + + const Value *Unused = CI.getArgOperand(2); + Assert1(isa(Unused) && + cast(Unused)->isNullValue(), + "gc.statepoint parameter #3 must be zero", &CI); + + // Verify that the types of the call parameter arguments match + // the type of the wrapped callee. + for (int i = 0; i < NumCallArgs; i++) { + Type *ParamType = TargetFuncType->getParamType(i); + Type *ArgType = CI.getArgOperand(3+i)->getType(); + Assert1(ArgType == ParamType, + "gc.statepoint call argument does not match wrapped " + "function type", &CI); + } + const int EndCallArgsInx = 2+NumCallArgs; + const Value *NumDeoptArgsV = CI.getArgOperand(EndCallArgsInx+1); + Assert1(isa(NumDeoptArgsV), + "gc.statepoint number of deoptimization arguments " + "must be constant integer", &CI); + const int NumDeoptArgs = cast(NumDeoptArgsV)->getZExtValue(); + Assert1(NumDeoptArgs >= 0, + "gc.statepoint number of deoptimization arguments " + "must be positive", &CI); + + Assert1(4 + NumCallArgs + NumDeoptArgs <= (int)CI.getNumArgOperands(), + "gc.statepoint too few arguments according to length fields", &CI); + + // Check that the only uses of this gc.statepoint are gc.result or + // gc.relocate calls which are tied to this statepoint and thus part + // of the same statepoint sequence + for (User *U : CI.users()) { + const CallInst *Call = dyn_cast(U); + Assert2(Call, "illegal use of statepoint token", &CI, U); + if (!Call) continue; + Assert2(isGCRelocate(Call) || isGCResult(Call), + "gc.result or gc.relocate are the only value uses" + "of a gc.statepoint", &CI, U); + if (isGCResult(Call)) { + Assert2(Call->getArgOperand(0) == &CI, + "gc.result connected to wrong gc.statepoint", + &CI, Call); + } else if (isGCRelocate(Call)) { + Assert2(Call->getArgOperand(0) == &CI, + "gc.relocate connected to wrong gc.statepoint", + &CI, Call); + } + } + + // Note: It is legal for a single derived pointer to be listed multiple + // times. It's non-optimal, but it is legal. It can also happen after + // insertion if we strip a bitcast away. + // Note: It is really tempting to check that each base is relocated and + // that a derived pointer is never reused as a base pointer. This turns + // out to be problematic since optimizations run after safepoint insertion + // can recognize equality properties that the insertion logic doesn't know + // about. See example statepoint.ll in the verifier subdirectory + break; } + case Intrinsic::experimental_gc_result_int: + case Intrinsic::experimental_gc_result_float: + case Intrinsic::experimental_gc_result_ptr: { + // Are we tied to a statepoint properly? + CallSite StatepointCS(CI.getArgOperand(0)); + const Function *StatepointFn = + StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr; + Assert2(StatepointFn && StatepointFn->isDeclaration() && + StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, + "gc.result operand #1 must be from a statepoint", + &CI, CI.getArgOperand(0)); + + // Assert that result type matches wrapped callee. + const Value *Target = StatepointCS.getArgument(0); + const PointerType *PT = cast(Target->getType()); + const FunctionType *TargetFuncType = + cast(PT->getElementType()); + Assert1(CI.getType() == TargetFuncType->getReturnType(), + "gc.result result type does not match wrapped callee", + &CI); + break; + } + case Intrinsic::experimental_gc_relocate: { + // Are we tied to a statepoint properly? + CallSite StatepointCS(CI.getArgOperand(0)); + const Function *StatepointFn = + StatepointCS.getInstruction() ? StatepointCS.getCalledFunction() : nullptr; + Assert2(StatepointFn && StatepointFn->isDeclaration() && + StatepointFn->getIntrinsicID() == Intrinsic::experimental_gc_statepoint, + "gc.relocate operand #1 must be from a statepoint", + &CI, CI.getArgOperand(0)); + + // Both the base and derived must be piped through the safepoint + Value* Base = CI.getArgOperand(1); + Assert1(isa(Base), + "gc.relocate operand #2 must be integer offset", &CI); + + Value* Derived = CI.getArgOperand(2); + Assert1(isa(Derived), + "gc.relocate operand #3 must be integer offset", &CI); + + const int BaseIndex = cast(Base)->getZExtValue(); + const int DerivedIndex = cast(Derived)->getZExtValue(); + // Check the bounds + Assert1(0 <= BaseIndex && + BaseIndex < (int)StatepointCS.arg_size(), + "gc.relocate: statepoint base index out of bounds", &CI); + Assert1(0 <= DerivedIndex && + DerivedIndex < (int)StatepointCS.arg_size(), + "gc.relocate: statepoint derived index out of bounds", &CI); + + // Check that BaseIndex and DerivedIndex fall within the 'gc parameters' + // section of the statepoint's argument + const int NumCallArgs = + cast(StatepointCS.getArgument(1))->getZExtValue(); + const int NumDeoptArgs = + cast(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue(); + const int GCParamArgsStart = NumCallArgs + NumDeoptArgs + 4; + const int GCParamArgsEnd = StatepointCS.arg_size(); + Assert1(GCParamArgsStart <= BaseIndex && + BaseIndex < GCParamArgsEnd, + "gc.relocate: statepoint base index doesn't fall within the " + "'gc parameters' section of the statepoint call", &CI); + Assert1(GCParamArgsStart <= DerivedIndex && + DerivedIndex < GCParamArgsEnd, + "gc.relocate: statepoint derived index doesn't fall within the " + "'gc parameters' section of the statepoint call", &CI); + + + // Assert that the result type matches the type of the relocated pointer + GCRelocateOperands Operands(&CI); + Assert1(Operands.derivedPtr()->getType() == CI.getType(), + "gc.relocate: relocating a pointer shouldn't change its type", + &CI); + break; + } + }; } void DebugInfoVerifier::verifyDebugInfo() { @@ -2615,7 +2866,7 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS) { bool Broken = false; for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->isDeclaration()) + if (!I->isDeclaration() && !I->isMaterializable()) Broken |= !V.verify(*I); // Note that this function's return value is inverted from what you would @@ -2699,15 +2950,15 @@ ModulePass *llvm::createDebugInfoVerifierPass(bool FatalErrors) { return new DebugInfoVerifierLegacyPass(FatalErrors); } -PreservedAnalyses VerifierPass::run(Module *M) { - if (verifyModule(*M, &dbgs()) && FatalErrors) +PreservedAnalyses VerifierPass::run(Module &M) { + if (verifyModule(M, &dbgs()) && FatalErrors) report_fatal_error("Broken module found, compilation aborted!"); return PreservedAnalyses::all(); } -PreservedAnalyses VerifierPass::run(Function *F) { - if (verifyFunction(*F, &dbgs()) && FatalErrors) +PreservedAnalyses VerifierPass::run(Function &F) { + if (verifyFunction(F, &dbgs()) && FatalErrors) report_fatal_error("Broken function found, compilation aborted!"); return PreservedAnalyses::all(); diff --git a/lib/IRReader/IRReader.cpp b/lib/IRReader/IRReader.cpp index f8d2f5a..7bc6f07 100644 --- a/lib/IRReader/IRReader.cpp +++ b/lib/IRReader/IRReader.cpp @@ -29,28 +29,27 @@ namespace llvm { static const char *const TimeIRParsingGroupName = "LLVM IR Parsing"; static const char *const TimeIRParsingName = "Parse IR"; -static Module *getLazyIRModule(MemoryBuffer *Buffer, SMDiagnostic &Err, - LLVMContext &Context) { +static std::unique_ptr +getLazyIRModule(std::unique_ptr Buffer, SMDiagnostic &Err, + LLVMContext &Context) { if (isBitcode((const unsigned char *)Buffer->getBufferStart(), (const unsigned char *)Buffer->getBufferEnd())) { - std::string ErrMsg; - ErrorOr ModuleOrErr = getLazyBitcodeModule(Buffer, Context); + ErrorOr ModuleOrErr = + getLazyBitcodeModule(std::move(Buffer), Context); if (std::error_code EC = ModuleOrErr.getError()) { Err = SMDiagnostic(Buffer->getBufferIdentifier(), SourceMgr::DK_Error, EC.message()); - // getLazyBitcodeModule does not take ownership of the Buffer in the - // case of an error. - delete Buffer; return nullptr; } - return ModuleOrErr.get(); + return std::unique_ptr(ModuleOrErr.get()); } - return ParseAssembly(Buffer, nullptr, Err, Context); + return parseAssembly(Buffer->getMemBufferRef(), Err, Context); } -Module *llvm::getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err, - LLVMContext &Context) { +std::unique_ptr llvm::getLazyIRFileModule(StringRef Filename, + SMDiagnostic &Err, + LLVMContext &Context) { ErrorOr> FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename); if (std::error_code EC = FileOrErr.getError()) { @@ -59,33 +58,29 @@ Module *llvm::getLazyIRFileModule(const std::string &Filename, SMDiagnostic &Err return nullptr; } - return getLazyIRModule(FileOrErr.get().release(), Err, Context); + return getLazyIRModule(std::move(FileOrErr.get()), Err, Context); } -Module *llvm::ParseIR(MemoryBuffer *Buffer, SMDiagnostic &Err, - LLVMContext &Context) { +std::unique_ptr llvm::parseIR(MemoryBufferRef Buffer, SMDiagnostic &Err, + LLVMContext &Context) { NamedRegionTimer T(TimeIRParsingName, TimeIRParsingGroupName, TimePassesIsEnabled); - if (isBitcode((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd())) { + if (isBitcode((const unsigned char *)Buffer.getBufferStart(), + (const unsigned char *)Buffer.getBufferEnd())) { ErrorOr ModuleOrErr = parseBitcodeFile(Buffer, Context); - Module *M = nullptr; - if (std::error_code EC = ModuleOrErr.getError()) - Err = SMDiagnostic(Buffer->getBufferIdentifier(), SourceMgr::DK_Error, + if (std::error_code EC = ModuleOrErr.getError()) { + Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error, EC.message()); - else - M = ModuleOrErr.get(); - // parseBitcodeFile does not take ownership of the Buffer. - return M; + return nullptr; + } + return std::unique_ptr(ModuleOrErr.get()); } - return ParseAssembly(MemoryBuffer::getMemBuffer( - Buffer->getBuffer(), Buffer->getBufferIdentifier()), - nullptr, Err, Context); + return parseAssembly(Buffer, Err, Context); } -Module *llvm::ParseIRFile(const std::string &Filename, SMDiagnostic &Err, - LLVMContext &Context) { +std::unique_ptr llvm::parseIRFile(StringRef Filename, SMDiagnostic &Err, + LLVMContext &Context) { ErrorOr> FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename); if (std::error_code EC = FileOrErr.getError()) { @@ -94,7 +89,7 @@ Module *llvm::ParseIRFile(const std::string &Filename, SMDiagnostic &Err, return nullptr; } - return ParseIR(FileOrErr.get().get(), Err, Context); + return parseIR(FileOrErr.get()->getMemBufferRef(), Err, Context); } //===----------------------------------------------------------------------===// @@ -107,7 +102,8 @@ LLVMBool LLVMParseIRInContext(LLVMContextRef ContextRef, SMDiagnostic Diag; std::unique_ptr MB(unwrap(MemBuf)); - *OutM = wrap(ParseIR(MB.get(), Diag, *unwrap(ContextRef))); + *OutM = + wrap(parseIR(MB->getMemBufferRef(), Diag, *unwrap(ContextRef)).release()); if(!*OutM) { if (OutMessage) { diff --git a/lib/LTO/LLVMBuild.txt b/lib/LTO/LLVMBuild.txt index c493f43..b9178e9 100644 --- a/lib/LTO/LLVMBuild.txt +++ b/lib/LTO/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = LTO parent = Libraries -required_libraries = BitReader BitWriter Core IPA IPO InstCombine Linker MC ObjCARC Object Scalar Support Target TransformUtils +required_libraries = BitReader BitWriter Core IPA IPO InstCombine Linker MC ObjCARC Object Scalar Support Target TransformUtils CodeGen diff --git a/lib/LTO/LTOCodeGenerator.cpp b/lib/LTO/LTOCodeGenerator.cpp index 45a49e4..c663d43 100644 --- a/lib/LTO/LTOCodeGenerator.cpp +++ b/lib/LTO/LTOCodeGenerator.cpp @@ -48,6 +48,7 @@ #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/ObjCARC.h" @@ -63,18 +64,30 @@ const char* LTOCodeGenerator::getVersionString() { } LTOCodeGenerator::LTOCodeGenerator() - : Context(getGlobalContext()), IRLinker(new Module("ld-temp.o", Context)), - TargetMach(nullptr), EmitDwarfDebugInfo(false), - ScopeRestrictionsDone(false), CodeModel(LTO_CODEGEN_PIC_MODEL_DEFAULT), - NativeObjectFile(nullptr), DiagHandler(nullptr), DiagContext(nullptr) { + : Context(getGlobalContext()), IRLinker(new Module("ld-temp.o", Context)) { + initialize(); +} + +LTOCodeGenerator::LTOCodeGenerator(std::unique_ptr Context) + : OwnedContext(std::move(Context)), Context(*OwnedContext), + IRLinker(new Module("ld-temp.o", *OwnedContext)) { + initialize(); +} + +void LTOCodeGenerator::initialize() { + TargetMach = nullptr; + EmitDwarfDebugInfo = false; + ScopeRestrictionsDone = false; + CodeModel = LTO_CODEGEN_PIC_MODEL_DEFAULT; + DiagHandler = nullptr; + DiagContext = nullptr; + initializeLTOPasses(); } LTOCodeGenerator::~LTOCodeGenerator() { delete TargetMach; - delete NativeObjectFile; TargetMach = nullptr; - NativeObjectFile = nullptr; IRLinker.deleteModule(); @@ -114,8 +127,11 @@ void LTOCodeGenerator::initializeLTOPasses() { initializeCFGSimplifyPassPass(R); } -bool LTOCodeGenerator::addModule(LTOModule* mod, std::string& errMsg) { - bool ret = IRLinker.linkInModule(&mod->getModule(), &errMsg); +bool LTOCodeGenerator::addModule(LTOModule *mod) { + assert(&mod->getModule().getContext() == &Context && + "Expected module in same context"); + + bool ret = IRLinker.linkInModule(&mod->getModule()); const std::vector &undefs = mod->getAsmUndefinedRefs(); for (int i = 0, e = undefs.size(); i != e; ++i) @@ -162,9 +178,9 @@ bool LTOCodeGenerator::writeMergedModules(const char *path, applyScopeRestrictions(); // create output file - std::string ErrInfo; - tool_output_file Out(path, ErrInfo, sys::fs::F_None); - if (!ErrInfo.empty()) { + std::error_code EC; + tool_output_file Out(path, EC, sys::fs::F_None); + if (EC) { errMsg = "could not open bitcode file for writing: "; errMsg += path; return false; @@ -189,6 +205,7 @@ bool LTOCodeGenerator::compile_to_file(const char** name, bool disableOpt, bool disableInline, bool disableGVNLoadPRE, + bool disableVectorization, std::string& errMsg) { // make unique temp .o file to put generated object file SmallString<128> Filename; @@ -203,8 +220,9 @@ bool LTOCodeGenerator::compile_to_file(const char** name, // generate object file tool_output_file objFile(Filename.c_str(), FD); - bool genResult = generateObjectFile(objFile.os(), disableOpt, disableInline, - disableGVNLoadPRE, errMsg); + bool genResult = + generateObjectFile(objFile.os(), disableOpt, disableInline, + disableGVNLoadPRE, disableVectorization, errMsg); objFile.os().close(); if (objFile.os().has_error()) { objFile.os().clear_error(); @@ -227,15 +245,13 @@ const void* LTOCodeGenerator::compile(size_t* length, bool disableOpt, bool disableInline, bool disableGVNLoadPRE, + bool disableVectorization, std::string& errMsg) { const char *name; if (!compile_to_file(&name, disableOpt, disableInline, disableGVNLoadPRE, - errMsg)) + disableVectorization, errMsg)) return nullptr; - // remove old buffer if compile() called twice - delete NativeObjectFile; - // read .o file into memory buffer ErrorOr> BufferOrErr = MemoryBuffer::getFile(name, -1, false); @@ -244,7 +260,7 @@ const void* LTOCodeGenerator::compile(size_t* length, sys::fs::remove(NativeObjectPath); return nullptr; } - NativeObjectFile = BufferOrErr.get().release(); + NativeObjectFile = std::move(*BufferOrErr); // remove temp files sys::fs::remove(NativeObjectPath); @@ -299,8 +315,7 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { MCpu = "core2"; else if (Triple.getArch() == llvm::Triple::x86) MCpu = "yonah"; - else if (Triple.getArch() == llvm::Triple::arm64 || - Triple.getArch() == llvm::Triple::aarch64) + else if (Triple.getArch() == llvm::Triple::aarch64) MCpu = "cyclone"; } @@ -312,9 +327,9 @@ bool LTOCodeGenerator::determineTarget(std::string &errMsg) { void LTOCodeGenerator:: applyRestriction(GlobalValue &GV, - const ArrayRef &Libcalls, + ArrayRef Libcalls, std::vector &MustPreserveList, - SmallPtrSet &AsmUsed, + SmallPtrSetImpl &AsmUsed, Mangler &Mangler) { // There are no restrictions to apply to declarations. if (GV.isDeclaration()) @@ -343,7 +358,7 @@ applyRestriction(GlobalValue &GV, } static void findUsedValues(GlobalVariable *LLVMUsed, - SmallPtrSet &UsedValues) { + SmallPtrSetImpl &UsedValues) { if (!LLVMUsed) return; ConstantArray *Inits = cast(LLVMUsed->getInitializer()); @@ -391,12 +406,13 @@ void LTOCodeGenerator::applyScopeRestrictions() { passes.add(createDebugInfoVerifierPass()); // mark which symbols can not be internalized - Mangler Mangler(TargetMach->getDataLayout()); + Mangler Mangler(TargetMach->getSubtargetImpl()->getDataLayout()); std::vector MustPreserveList; SmallPtrSet AsmUsed; std::vector Libcalls; TargetLibraryInfo TLI(Triple(TargetMach->getTargetTriple())); - accumulateAndSortLibcalls(Libcalls, TLI, TargetMach->getTargetLowering()); + accumulateAndSortLibcalls( + Libcalls, TLI, TargetMach->getSubtargetImpl()->getTargetLowering()); for (Module::iterator f = mergedModule->begin(), e = mergedModule->end(); f != e; ++f) @@ -445,6 +461,7 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, bool DisableOpt, bool DisableInline, bool DisableGVNLoadPRE, + bool DisableVectorization, std::string &errMsg) { if (!this->determineTarget(errMsg)) return false; @@ -457,35 +474,27 @@ bool LTOCodeGenerator::generateObjectFile(raw_ostream &out, // Instantiate the pass manager to organize the passes. PassManager passes; - // Start off with a verification pass. - passes.add(createVerifierPass()); - passes.add(createDebugInfoVerifierPass()); - // Add an appropriate DataLayout instance for this module... - mergedModule->setDataLayout(TargetMach->getDataLayout()); - passes.add(new DataLayoutPass(mergedModule)); - - // Add appropriate TargetLibraryInfo for this module. - passes.add(new TargetLibraryInfo(Triple(TargetMach->getTargetTriple()))); - - TargetMach->addAnalysisPasses(passes); - - // Enabling internalize here would use its AllButMain variant. It - // keeps only main if it exists and does nothing for libraries. Instead - // we create the pass ourselves with the symbol list provided by the linker. - if (!DisableOpt) - PassManagerBuilder().populateLTOPassManager(passes, - /*Internalize=*/false, - !DisableInline, - DisableGVNLoadPRE); - - // Make sure everything is still good. - passes.add(createVerifierPass()); - passes.add(createDebugInfoVerifierPass()); + mergedModule->setDataLayout(TargetMach->getSubtargetImpl()->getDataLayout()); + + Triple TargetTriple(TargetMach->getTargetTriple()); + PassManagerBuilder PMB; + PMB.DisableGVNLoadPRE = DisableGVNLoadPRE; + PMB.LoopVectorize = !DisableVectorization; + PMB.SLPVectorize = !DisableVectorization; + if (!DisableInline) + PMB.Inliner = createFunctionInliningPass(); + PMB.LibraryInfo = new TargetLibraryInfo(TargetTriple); + if (DisableOpt) + PMB.OptLevel = 0; + PMB.VerifyInput = true; + PMB.VerifyOutput = true; + + PMB.populateLTOPassManager(passes, TargetMach); PassManager codeGenPasses; - codeGenPasses.add(new DataLayoutPass(mergedModule)); + codeGenPasses.add(new DataLayoutPass()); formatted_raw_ostream Out(out); @@ -572,5 +581,6 @@ LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler, return Context.setDiagnosticHandler(nullptr, nullptr); // Register the LTOCodeGenerator stub in the LLVMContext to forward the // diagnostic to the external DiagHandler. - Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this); + Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this, + /* RespectFilters */ true); } diff --git a/lib/LTO/LTOModule.cpp b/lib/LTO/LTOModule.cpp index 844c0f2..8b4a2f4 100644 --- a/lib/LTO/LTOModule.cpp +++ b/lib/LTO/LTOModule.cpp @@ -15,7 +15,9 @@ #include "llvm/LTO/LTOModule.h" #include "llvm/ADT/Triple.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/CodeGen/Analysis.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -28,6 +30,8 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/SubtargetFeature.h" +#include "llvm/Object/IRObjectFile.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" @@ -39,32 +43,51 @@ #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/Utils/GlobalStatus.h" #include using namespace llvm; +using namespace llvm::object; LTOModule::LTOModule(std::unique_ptr Obj, llvm::TargetMachine *TM) : IRFile(std::move(Obj)), _target(TM) {} +LTOModule::LTOModule(std::unique_ptr Obj, + llvm::TargetMachine *TM, + std::unique_ptr Context) + : OwnedContext(std::move(Context)), IRFile(std::move(Obj)), _target(TM) {} + +LTOModule::~LTOModule() {} + /// isBitcodeFile - Returns 'true' if the file (or memory contents) is LLVM /// bitcode. -bool LTOModule::isBitcodeFile(const void *mem, size_t length) { - return sys::fs::identify_magic(StringRef((const char *)mem, length)) == - sys::fs::file_magic::bitcode; +bool LTOModule::isBitcodeFile(const void *Mem, size_t Length) { + ErrorOr BCData = IRObjectFile::findBitcodeInMemBuffer( + MemoryBufferRef(StringRef((const char *)Mem, Length), "")); + return bool(BCData); } -bool LTOModule::isBitcodeFile(const char *path) { - sys::fs::file_magic type; - if (sys::fs::identify_magic(path, type)) +bool LTOModule::isBitcodeFile(const char *Path) { + ErrorOr> BufferOrErr = + MemoryBuffer::getFile(Path); + if (!BufferOrErr) return false; - return type == sys::fs::file_magic::bitcode; + + ErrorOr BCData = IRObjectFile::findBitcodeInMemBuffer( + BufferOrErr.get()->getMemBufferRef()); + return bool(BCData); } -bool LTOModule::isBitcodeForTarget(MemoryBuffer *buffer, - StringRef triplePrefix) { - std::string Triple = getBitcodeTargetTriple(buffer, getGlobalContext()); - return StringRef(Triple).startswith(triplePrefix); +bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer, + StringRef TriplePrefix) { + ErrorOr BCOrErr = + IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef()); + if (!BCOrErr) + return false; + LLVMContext Context; + std::string Triple = getBitcodeTargetTriple(*BCOrErr, Context); + return StringRef(Triple).startswith(TriplePrefix); } LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options, @@ -75,7 +98,9 @@ LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options, errMsg = EC.message(); return nullptr; } - return makeLTOModule(std::move(BufferOrErr.get()), options, errMsg); + std::unique_ptr Buffer = std::move(BufferOrErr.get()); + return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg, + &getGlobalContext()); } LTOModule *LTOModule::createFromOpenFile(int fd, const char *path, size_t size, @@ -94,28 +119,88 @@ LTOModule *LTOModule::createFromOpenFileSlice(int fd, const char *path, errMsg = EC.message(); return nullptr; } - return makeLTOModule(std::move(BufferOrErr.get()), options, errMsg); + std::unique_ptr Buffer = std::move(BufferOrErr.get()); + return makeLTOModule(Buffer->getMemBufferRef(), options, errMsg, + &getGlobalContext()); } LTOModule *LTOModule::createFromBuffer(const void *mem, size_t length, TargetOptions options, std::string &errMsg, StringRef path) { - std::unique_ptr buffer(makeBuffer(mem, length, path)); - if (!buffer) - return nullptr; - return makeLTOModule(std::move(buffer), options, errMsg); + return createInContext(mem, length, options, errMsg, path, + &getGlobalContext()); } -LTOModule *LTOModule::makeLTOModule(std::unique_ptr Buffer, - TargetOptions options, - std::string &errMsg) { - ErrorOr MOrErr = - getLazyBitcodeModule(Buffer.get(), getGlobalContext()); - if (std::error_code EC = MOrErr.getError()) { - errMsg = EC.message(); +LTOModule *LTOModule::createInLocalContext(const void *mem, size_t length, + TargetOptions options, + std::string &errMsg, + StringRef path) { + return createInContext(mem, length, options, errMsg, path, nullptr); +} + +LTOModule *LTOModule::createInContext(const void *mem, size_t length, + TargetOptions options, + std::string &errMsg, StringRef path, + LLVMContext *Context) { + StringRef Data((const char *)mem, length); + MemoryBufferRef Buffer(Data, path); + return makeLTOModule(Buffer, options, errMsg, Context); +} + +static Module *parseBitcodeFileImpl(MemoryBufferRef Buffer, + LLVMContext &Context, bool ShouldBeLazy, + std::string &ErrMsg) { + + // Find the buffer. + ErrorOr MBOrErr = + IRObjectFile::findBitcodeInMemBuffer(Buffer); + if (std::error_code EC = MBOrErr.getError()) { + ErrMsg = EC.message(); + return nullptr; + } + + std::function DiagnosticHandler = + [&ErrMsg](const DiagnosticInfo &DI) { + raw_string_ostream Stream(ErrMsg); + DiagnosticPrinterRawOStream DP(Stream); + DI.print(DP); + }; + + if (!ShouldBeLazy) { + // Parse the full file. + ErrorOr M = + parseBitcodeFile(*MBOrErr, Context, DiagnosticHandler); + if (!M) + return nullptr; + return *M; + } + + // Parse lazily. + std::unique_ptr LightweightBuf = + MemoryBuffer::getMemBuffer(*MBOrErr, false); + ErrorOr M = getLazyBitcodeModule(std::move(LightweightBuf), Context, + DiagnosticHandler); + if (!M) return nullptr; + return *M; +} + +LTOModule *LTOModule::makeLTOModule(MemoryBufferRef Buffer, + TargetOptions options, std::string &errMsg, + LLVMContext *Context) { + std::unique_ptr OwnedContext; + if (!Context) { + OwnedContext = llvm::make_unique(); + Context = OwnedContext.get(); } - std::unique_ptr M(MOrErr.get()); + + // If we own a context, we know this is being used only for symbol + // extraction, not linking. Be lazy in that case. + std::unique_ptr M(parseBitcodeFileImpl( + Buffer, *Context, + /* ShouldBeLazy */ static_cast(OwnedContext), errMsg)); + if (!M) + return nullptr; std::string TripleStr = M->getTargetTriple(); if (TripleStr.empty()) @@ -138,20 +223,22 @@ LTOModule *LTOModule::makeLTOModule(std::unique_ptr Buffer, CPU = "core2"; else if (Triple.getArch() == llvm::Triple::x86) CPU = "yonah"; - else if (Triple.getArch() == llvm::Triple::arm64 || - Triple.getArch() == llvm::Triple::aarch64) + else if (Triple.getArch() == llvm::Triple::aarch64) CPU = "cyclone"; } TargetMachine *target = march->createTargetMachine(TripleStr, CPU, FeatureStr, options); - M->materializeAllPermanently(true); - M->setDataLayout(target->getDataLayout()); + M->setDataLayout(target->getSubtargetImpl()->getDataLayout()); std::unique_ptr IRObj( - new object::IRObjectFile(std::move(Buffer), std::move(M))); + new object::IRObjectFile(Buffer, std::move(M))); - LTOModule *Ret = new LTOModule(std::move(IRObj), target); + LTOModule *Ret; + if (OwnedContext) + Ret = new LTOModule(std::move(IRObj), target, std::move(OwnedContext)); + else + Ret = new LTOModule(std::move(IRObj), target); if (Ret->parseSymbols(errMsg)) { delete Ret; @@ -164,8 +251,8 @@ LTOModule *LTOModule::makeLTOModule(std::unique_ptr Buffer, } /// Create a MemoryBuffer from a memory range with an optional name. -MemoryBuffer *LTOModule::makeBuffer(const void *mem, size_t length, - StringRef name) { +std::unique_ptr +LTOModule::makeBuffer(const void *mem, size_t length, StringRef name) { const char *startPtr = (const char*)mem; return MemoryBuffer::getMemBuffer(StringRef(startPtr, length), name, false); } @@ -196,27 +283,24 @@ void LTOModule::addObjCClass(const GlobalVariable *clgv) { // second slot in __OBJC,__class is pointer to superclass name std::string superclassName; if (objcClassNameFromExpression(c->getOperand(1), superclassName)) { - NameAndAttributes info; - StringMap::value_type &entry = - _undefines.GetOrCreateValue(superclassName); - if (!entry.getValue().name) { - const char *symbolName = entry.getKey().data(); - info.name = symbolName; + auto IterBool = + _undefines.insert(std::make_pair(superclassName, NameAndAttributes())); + if (IterBool.second) { + NameAndAttributes &info = IterBool.first->second; + info.name = IterBool.first->first().data(); info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; info.isFunction = false; info.symbol = clgv; - entry.setValue(info); } } // third slot in __OBJC,__class is pointer to class name std::string className; if (objcClassNameFromExpression(c->getOperand(2), className)) { - StringSet::value_type &entry = _defines.GetOrCreateValue(className); - entry.setValue(1); + auto Iter = _defines.insert(className).first; NameAndAttributes info; - info.name = entry.getKey().data(); + info.name = Iter->first().data(); info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | LTO_SYMBOL_SCOPE_DEFAULT; info.isFunction = false; @@ -235,19 +319,17 @@ void LTOModule::addObjCCategory(const GlobalVariable *clgv) { if (!objcClassNameFromExpression(c->getOperand(1), targetclassName)) return; - NameAndAttributes info; - StringMap::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); + auto IterBool = + _undefines.insert(std::make_pair(targetclassName, NameAndAttributes())); - if (entry.getValue().name) + if (!IterBool.second) return; - const char *symbolName = entry.getKey().data(); - info.name = symbolName; + NameAndAttributes &info = IterBool.first->second; + info.name = IterBool.first->first().data(); info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; info.isFunction = false; info.symbol = clgv; - entry.setValue(info); } /// addObjCClassRef - Parse i386/ppc ObjC class list data structure. @@ -256,18 +338,17 @@ void LTOModule::addObjCClassRef(const GlobalVariable *clgv) { if (!objcClassNameFromExpression(clgv->getInitializer(), targetclassName)) return; - NameAndAttributes info; - StringMap::value_type &entry = - _undefines.GetOrCreateValue(targetclassName); - if (entry.getValue().name) + auto IterBool = + _undefines.insert(std::make_pair(targetclassName, NameAndAttributes())); + + if (!IterBool.second) return; - const char *symbolName = entry.getKey().data(); - info.name = symbolName; + NameAndAttributes &info = IterBool.first->second; + info.name = IterBool.first->first().data(); info.attributes = LTO_SYMBOL_DEFINITION_UNDEFINED; info.isFunction = false; info.symbol = clgv; - entry.setValue(info); } void LTOModule::addDefinedDataSymbol(const object::BasicSymbolRef &Sym) { @@ -348,30 +429,6 @@ void LTOModule::addDefinedFunctionSymbol(const char *Name, const Function *F) { addDefinedSymbol(Name, F, true); } -static bool canBeHidden(const GlobalValue *GV) { - // FIXME: this is duplicated with another static function in AsmPrinter.cpp - GlobalValue::LinkageTypes L = GV->getLinkage(); - - if (L != GlobalValue::LinkOnceODRLinkage) - return false; - - if (GV->hasUnnamedAddr()) - return true; - - // If it is a non constant variable, it needs to be uniqued across shared - // objects. - if (const GlobalVariable *Var = dyn_cast(GV)) { - if (!Var->isConstant()) - return false; - } - - GlobalStatus GS; - if (GlobalStatus::analyzeGlobal(GV, GS)) - return false; - - return !GS.IsCompared; -} - void LTOModule::addDefinedSymbol(const char *Name, const GlobalValue *def, bool isFunction) { // set alignment part log2() can have rounding errors @@ -405,17 +462,16 @@ void LTOModule::addDefinedSymbol(const char *Name, const GlobalValue *def, attr |= LTO_SYMBOL_SCOPE_HIDDEN; else if (def->hasProtectedVisibility()) attr |= LTO_SYMBOL_SCOPE_PROTECTED; - else if (canBeHidden(def)) + else if (canBeOmittedFromSymbolTable(def)) attr |= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN; else attr |= LTO_SYMBOL_SCOPE_DEFAULT; - StringSet::value_type &entry = _defines.GetOrCreateValue(Name); - entry.setValue(1); + auto Iter = _defines.insert(Name).first; // fill information structure NameAndAttributes info; - StringRef NameRef = entry.getKey(); + StringRef NameRef = Iter->first(); info.name = NameRef.data(); assert(info.name[NameRef.size()] == '\0'); info.attributes = attr; @@ -430,15 +486,13 @@ void LTOModule::addDefinedSymbol(const char *Name, const GlobalValue *def, /// defined list. void LTOModule::addAsmGlobalSymbol(const char *name, lto_symbol_attributes scope) { - StringSet::value_type &entry = _defines.GetOrCreateValue(name); + auto IterBool = _defines.insert(name); // only add new define if not already defined - if (entry.getValue()) + if (!IterBool.second) return; - entry.setValue(1); - - NameAndAttributes &info = _undefines[entry.getKey().data()]; + NameAndAttributes &info = _undefines[IterBool.first->first().data()]; if (info.symbol == nullptr) { // FIXME: This is trying to take care of module ASM like this: @@ -450,7 +504,7 @@ void LTOModule::addAsmGlobalSymbol(const char *name, // much. // fill information structure - info.name = entry.getKey().data(); + info.name = IterBool.first->first().data(); info.attributes = LTO_SYMBOL_PERMISSIONS_DATA | LTO_SYMBOL_DEFINITION_REGULAR | scope; info.isFunction = false; @@ -473,24 +527,21 @@ void LTOModule::addAsmGlobalSymbol(const char *name, /// addAsmGlobalSymbolUndef - Add a global symbol from module-level ASM to the /// undefined list. void LTOModule::addAsmGlobalSymbolUndef(const char *name) { - StringMap::value_type &entry = - _undefines.GetOrCreateValue(name); + auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes())); - _asm_undefines.push_back(entry.getKey().data()); + _asm_undefines.push_back(IterBool.first->first().data()); // we already have the symbol - if (entry.getValue().name) + if (!IterBool.second) return; uint32_t attr = LTO_SYMBOL_DEFINITION_UNDEFINED; attr |= LTO_SYMBOL_SCOPE_DEFAULT; - NameAndAttributes info; - info.name = entry.getKey().data(); + NameAndAttributes &info = IterBool.first->second; + info.name = IterBool.first->first().data(); info.attributes = attr; info.isFunction = false; info.symbol = nullptr; - - entry.setValue(info); } /// Add a symbol which isn't defined just yet to a list to be resolved later. @@ -502,16 +553,15 @@ void LTOModule::addPotentialUndefinedSymbol(const object::BasicSymbolRef &Sym, Sym.printName(OS); } - StringMap::value_type &entry = - _undefines.GetOrCreateValue(name); + auto IterBool = _undefines.insert(std::make_pair(name, NameAndAttributes())); // we already have the symbol - if (entry.getValue().name) + if (!IterBool.second) return; - NameAndAttributes info; + NameAndAttributes &info = IterBool.first->second; - info.name = entry.getKey().data(); + info.name = IterBool.first->first().data(); const GlobalValue *decl = IRFile->getSymbolGV(Sym.getRawDataRefImpl()); @@ -522,8 +572,6 @@ void LTOModule::addPotentialUndefinedSymbol(const object::BasicSymbolRef &Sym, info.isFunction = isFunc; info.symbol = decl; - - entry.setValue(info); } /// parseSymbols - Parse the symbols from the module and model-level ASM and add @@ -590,16 +638,21 @@ bool LTOModule::parseSymbols(std::string &errMsg) { /// parseMetadata - Parse metadata from the module void LTOModule::parseMetadata() { // Linker Options - if (Value *Val = getModule().getModuleFlag("Linker Options")) { + if (Metadata *Val = getModule().getModuleFlag("Linker Options")) { MDNode *LinkerOptions = cast(Val); for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) { MDNode *MDOptions = cast(LinkerOptions->getOperand(i)); for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { MDString *MDOption = cast(MDOptions->getOperand(ii)); - StringRef Op = _linkeropt_strings. - GetOrCreateValue(MDOption->getString()).getKey(); - StringRef DepLibName = _target->getTargetLowering()-> - getObjFileLowering().getDepLibFromLinkerOpt(Op); + // FIXME: Make StringSet::insert match Self-Associative Container + // requirements, returning rather than bool, and use that + // here. + StringRef Op = + _linkeropt_strings.insert(MDOption->getString()).first->first(); + StringRef DepLibName = _target->getSubtargetImpl() + ->getTargetLowering() + ->getObjFileLowering() + .getDepLibFromLinkerOpt(Op); if (!DepLibName.empty()) _deplibs.push_back(DepLibName.data()); else if (!Op.empty()) diff --git a/lib/Linker/LinkModules.cpp b/lib/Linker/LinkModules.cpp index 5bb2862..767d465 100644 --- a/lib/Linker/LinkModules.cpp +++ b/lib/Linker/LinkModules.cpp @@ -13,10 +13,16 @@ #include "llvm/Linker/Linker.h" #include "llvm-c/Linker.h" +#include "llvm/ADT/Hashing.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Statistic.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/TypeFinder.h" #include "llvm/Support/CommandLine.h" @@ -33,94 +39,99 @@ using namespace llvm; //===----------------------------------------------------------------------===// namespace { - typedef SmallPtrSet TypeSet; - class TypeMapTy : public ValueMapTypeRemapper { - /// MappedTypes - This is a mapping from a source type to a destination type - /// to use. + /// This is a mapping from a source type to a destination type to use. DenseMap MappedTypes; - /// SpeculativeTypes - When checking to see if two subgraphs are isomorphic, - /// we speculatively add types to MappedTypes, but keep track of them here in - /// case we need to roll back. + /// When checking to see if two subgraphs are isomorphic, we speculatively + /// add types to MappedTypes, but keep track of them here in case we need to + /// roll back. SmallVector SpeculativeTypes; - /// SrcDefinitionsToResolve - This is a list of non-opaque structs in the - /// source module that are mapped to an opaque struct in the destination - /// module. + SmallVector SpeculativeDstOpaqueTypes; + + /// This is a list of non-opaque structs in the source module that are mapped + /// to an opaque struct in the destination module. SmallVector SrcDefinitionsToResolve; - /// DstResolvedOpaqueTypes - This is the set of opaque types in the - /// destination modules who are getting a body from the source module. + /// This is the set of opaque types in the destination modules who are + /// getting a body from the source module. SmallPtrSet DstResolvedOpaqueTypes; public: - TypeMapTy(TypeSet &Set) : DstStructTypesSet(Set) {} + TypeMapTy(Linker::IdentifiedStructTypeSet &DstStructTypesSet) + : DstStructTypesSet(DstStructTypesSet) {} - TypeSet &DstStructTypesSet; - /// addTypeMapping - Indicate that the specified type in the destination - /// module is conceptually equivalent to the specified type in the source - /// module. + Linker::IdentifiedStructTypeSet &DstStructTypesSet; + /// Indicate that the specified type in the destination module is conceptually + /// equivalent to the specified type in the source module. void addTypeMapping(Type *DstTy, Type *SrcTy); - /// linkDefinedTypeBodies - Produce a body for an opaque type in the dest - /// module from a type definition in the source module. + /// Produce a body for an opaque type in the dest module from a type + /// definition in the source module. void linkDefinedTypeBodies(); - /// get - Return the mapped type to use for the specified input type from the + /// Return the mapped type to use for the specified input type from the /// source module. Type *get(Type *SrcTy); + Type *get(Type *SrcTy, SmallPtrSet &Visited); + + void finishType(StructType *DTy, StructType *STy, ArrayRef ETypes); - FunctionType *get(FunctionType *T) {return cast(get((Type*)T));} + FunctionType *get(FunctionType *T) { + return cast(get((Type *)T)); + } - /// dump - Dump out the type map for debugging purposes. + /// Dump out the type map for debugging purposes. void dump() const { - for (DenseMap::const_iterator - I = MappedTypes.begin(), E = MappedTypes.end(); I != E; ++I) { + for (auto &Pair : MappedTypes) { dbgs() << "TypeMap: "; - I->first->dump(); + Pair.first->print(dbgs()); dbgs() << " => "; - I->second->dump(); + Pair.second->print(dbgs()); dbgs() << '\n'; } } private: - Type *getImpl(Type *T); - /// remapType - Implement the ValueMapTypeRemapper interface. - Type *remapType(Type *SrcTy) override { - return get(SrcTy); - } + Type *remapType(Type *SrcTy) override { return get(SrcTy); } bool areTypesIsomorphic(Type *DstTy, Type *SrcTy); }; } void TypeMapTy::addTypeMapping(Type *DstTy, Type *SrcTy) { - Type *&Entry = MappedTypes[SrcTy]; - if (Entry) return; - - if (DstTy == SrcTy) { - Entry = DstTy; - return; - } + assert(SpeculativeTypes.empty()); + assert(SpeculativeDstOpaqueTypes.empty()); // Check to see if these types are recursively isomorphic and establish a // mapping between them if so. if (!areTypesIsomorphic(DstTy, SrcTy)) { // Oops, they aren't isomorphic. Just discard this request by rolling out // any speculative mappings we've established. - for (unsigned i = 0, e = SpeculativeTypes.size(); i != e; ++i) - MappedTypes.erase(SpeculativeTypes[i]); + for (Type *Ty : SpeculativeTypes) + MappedTypes.erase(Ty); + + SrcDefinitionsToResolve.resize(SrcDefinitionsToResolve.size() - + SpeculativeDstOpaqueTypes.size()); + for (StructType *Ty : SpeculativeDstOpaqueTypes) + DstResolvedOpaqueTypes.erase(Ty); + } else { + for (Type *Ty : SpeculativeTypes) + if (auto *STy = dyn_cast(Ty)) + if (STy->hasName()) + STy->setName(""); } SpeculativeTypes.clear(); + SpeculativeDstOpaqueTypes.clear(); } -/// areTypesIsomorphic - Recursively walk this pair of types, returning true -/// if they are isomorphic, false if they are not. +/// Recursively walk this pair of types, returning true if they are isomorphic, +/// false if they are not. bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) { // Two types with differing kinds are clearly not isomorphic. - if (DstTy->getTypeID() != SrcTy->getTypeID()) return false; + if (DstTy->getTypeID() != SrcTy->getTypeID()) + return false; // If we have an entry in the MappedTypes table, then we have our answer. Type *&Entry = MappedTypes[SrcTy]; @@ -147,14 +158,15 @@ bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) { // Mapping a non-opaque source type to an opaque dest. If this is the first // type that we're mapping onto this destination type then we succeed. Keep - // the dest, but fill it in later. This doesn't need to be speculative. If - // this is the second (different) type that we're trying to map onto the - // same opaque type then we fail. + // the dest, but fill it in later. If this is the second (different) type + // that we're trying to map onto the same opaque type then we fail. if (cast(DstTy)->isOpaque()) { // We can only map one source type onto the opaque destination type. - if (!DstResolvedOpaqueTypes.insert(cast(DstTy))) + if (!DstResolvedOpaqueTypes.insert(cast(DstTy)).second) return false; SrcDefinitionsToResolve.push_back(SSTy); + SpeculativeTypes.push_back(SrcTy); + SpeculativeDstOpaqueTypes.push_back(cast(DstTy)); Entry = DstTy; return true; } @@ -192,164 +204,153 @@ bool TypeMapTy::areTypesIsomorphic(Type *DstTy, Type *SrcTy) { Entry = DstTy; SpeculativeTypes.push_back(SrcTy); - for (unsigned i = 0, e = SrcTy->getNumContainedTypes(); i != e; ++i) - if (!areTypesIsomorphic(DstTy->getContainedType(i), - SrcTy->getContainedType(i))) + for (unsigned I = 0, E = SrcTy->getNumContainedTypes(); I != E; ++I) + if (!areTypesIsomorphic(DstTy->getContainedType(I), + SrcTy->getContainedType(I))) return false; // If everything seems to have lined up, then everything is great. return true; } -/// linkDefinedTypeBodies - Produce a body for an opaque type in the dest -/// module from a type definition in the source module. void TypeMapTy::linkDefinedTypeBodies() { SmallVector Elements; - SmallString<16> TmpName; - - // Note that processing entries in this loop (calling 'get') can add new - // entries to the SrcDefinitionsToResolve vector. - while (!SrcDefinitionsToResolve.empty()) { - StructType *SrcSTy = SrcDefinitionsToResolve.pop_back_val(); + for (StructType *SrcSTy : SrcDefinitionsToResolve) { StructType *DstSTy = cast(MappedTypes[SrcSTy]); - - // TypeMap is a many-to-one mapping, if there were multiple types that - // provide a body for DstSTy then previous iterations of this loop may have - // already handled it. Just ignore this case. - if (!DstSTy->isOpaque()) continue; - assert(!SrcSTy->isOpaque() && "Not resolving a definition?"); + assert(DstSTy->isOpaque()); // Map the body of the source type over to a new body for the dest type. Elements.resize(SrcSTy->getNumElements()); - for (unsigned i = 0, e = Elements.size(); i != e; ++i) - Elements[i] = getImpl(SrcSTy->getElementType(i)); + for (unsigned I = 0, E = Elements.size(); I != E; ++I) + Elements[I] = get(SrcSTy->getElementType(I)); DstSTy->setBody(Elements, SrcSTy->isPacked()); + } + SrcDefinitionsToResolve.clear(); + DstResolvedOpaqueTypes.clear(); +} - // If DstSTy has no name or has a longer name than STy, then viciously steal - // STy's name. - if (!SrcSTy->hasName()) continue; - StringRef SrcName = SrcSTy->getName(); +void TypeMapTy::finishType(StructType *DTy, StructType *STy, + ArrayRef ETypes) { + DTy->setBody(ETypes, STy->isPacked()); - if (!DstSTy->hasName() || DstSTy->getName().size() > SrcName.size()) { - TmpName.insert(TmpName.end(), SrcName.begin(), SrcName.end()); - SrcSTy->setName(""); - DstSTy->setName(TmpName.str()); - TmpName.clear(); - } + // Steal STy's name. + if (STy->hasName()) { + SmallString<16> TmpName = STy->getName(); + STy->setName(""); + DTy->setName(TmpName); } - DstResolvedOpaqueTypes.clear(); + DstStructTypesSet.addNonOpaque(DTy); } -/// get - Return the mapped type to use for the specified input type from the -/// source module. Type *TypeMapTy::get(Type *Ty) { - Type *Result = getImpl(Ty); - - // If this caused a reference to any struct type, resolve it before returning. - if (!SrcDefinitionsToResolve.empty()) - linkDefinedTypeBodies(); - return Result; + SmallPtrSet Visited; + return get(Ty, Visited); } -/// getImpl - This is the recursive version of get(). -Type *TypeMapTy::getImpl(Type *Ty) { +Type *TypeMapTy::get(Type *Ty, SmallPtrSet &Visited) { // If we already have an entry for this type, return it. Type **Entry = &MappedTypes[Ty]; - if (*Entry) return *Entry; + if (*Entry) + return *Entry; - // If this is not a named struct type, then just map all of the elements and - // then rebuild the type from inside out. - if (!isa(Ty) || cast(Ty)->isLiteral()) { - // If there are no element types to map, then the type is itself. This is - // true for the anonymous {} struct, things like 'float', integers, etc. - if (Ty->getNumContainedTypes() == 0) - return *Entry = Ty; + // These are types that LLVM itself will unique. + bool IsUniqued = !isa(Ty) || cast(Ty)->isLiteral(); - // Remap all of the elements, keeping track of whether any of them change. - bool AnyChange = false; - SmallVector ElementTypes; - ElementTypes.resize(Ty->getNumContainedTypes()); - for (unsigned i = 0, e = Ty->getNumContainedTypes(); i != e; ++i) { - ElementTypes[i] = getImpl(Ty->getContainedType(i)); - AnyChange |= ElementTypes[i] != Ty->getContainedType(i); +#ifndef NDEBUG + if (!IsUniqued) { + for (auto &Pair : MappedTypes) { + assert(!(Pair.first != Ty && Pair.second == Ty) && + "mapping to a source type"); } + } +#endif - // If we found our type while recursively processing stuff, just use it. - Entry = &MappedTypes[Ty]; - if (*Entry) return *Entry; + if (!IsUniqued && !Visited.insert(cast(Ty)).second) { + StructType *DTy = StructType::create(Ty->getContext()); + return *Entry = DTy; + } - // If all of the element types mapped directly over, then the type is usable - // as-is. - if (!AnyChange) - return *Entry = Ty; + // If this is not a recursive type, then just map all of the elements and + // then rebuild the type from inside out. + SmallVector ElementTypes; + + // If there are no element types to map, then the type is itself. This is + // true for the anonymous {} struct, things like 'float', integers, etc. + if (Ty->getNumContainedTypes() == 0 && IsUniqued) + return *Entry = Ty; + + // Remap all of the elements, keeping track of whether any of them change. + bool AnyChange = false; + ElementTypes.resize(Ty->getNumContainedTypes()); + for (unsigned I = 0, E = Ty->getNumContainedTypes(); I != E; ++I) { + ElementTypes[I] = get(Ty->getContainedType(I), Visited); + AnyChange |= ElementTypes[I] != Ty->getContainedType(I); + } - // Otherwise, rebuild a modified type. - switch (Ty->getTypeID()) { - default: llvm_unreachable("unknown derived type to remap"); - case Type::ArrayTyID: - return *Entry = ArrayType::get(ElementTypes[0], - cast(Ty)->getNumElements()); - case Type::VectorTyID: - return *Entry = VectorType::get(ElementTypes[0], - cast(Ty)->getNumElements()); - case Type::PointerTyID: - return *Entry = PointerType::get(ElementTypes[0], - cast(Ty)->getAddressSpace()); - case Type::FunctionTyID: - return *Entry = FunctionType::get(ElementTypes[0], - makeArrayRef(ElementTypes).slice(1), - cast(Ty)->isVarArg()); - case Type::StructTyID: - // Note that this is only reached for anonymous structs. - return *Entry = StructType::get(Ty->getContext(), ElementTypes, - cast(Ty)->isPacked()); + // If we found our type while recursively processing stuff, just use it. + Entry = &MappedTypes[Ty]; + if (*Entry) { + if (auto *DTy = dyn_cast(*Entry)) { + if (DTy->isOpaque()) { + auto *STy = cast(Ty); + finishType(DTy, STy, ElementTypes); + } } + return *Entry; } - // Otherwise, this is an unmapped named struct. If the struct can be directly - // mapped over, just use it as-is. This happens in a case when the linked-in - // module has something like: - // %T = type {%T*, i32} - // @GV = global %T* null - // where T does not exist at all in the destination module. - // - // The other case we watch for is when the type is not in the destination - // module, but that it has to be rebuilt because it refers to something that - // is already mapped. For example, if the destination module has: - // %A = type { i32 } - // and the source module has something like - // %A' = type { i32 } - // %B = type { %A'* } - // @GV = global %B* null - // then we want to create a new type: "%B = type { %A*}" and have it take the - // pristine "%B" name from the source module. - // - // To determine which case this is, we have to recursively walk the type graph - // speculating that we'll be able to reuse it unmodified. Only if this is - // safe would we map the entire thing over. Because this is an optimization, - // and is not required for the prettiness of the linked module, we just skip - // it and always rebuild a type here. - StructType *STy = cast(Ty); - - // If the type is opaque, we can just use it directly. - if (STy->isOpaque()) { - // A named structure type from src module is used. Add it to the Set of - // identified structs in the destination module. - DstStructTypesSet.insert(STy); - return *Entry = STy; - } + // If all of the element types mapped directly over and the type is not + // a nomed struct, then the type is usable as-is. + if (!AnyChange && IsUniqued) + return *Entry = Ty; + + // Otherwise, rebuild a modified type. + switch (Ty->getTypeID()) { + default: + llvm_unreachable("unknown derived type to remap"); + case Type::ArrayTyID: + return *Entry = ArrayType::get(ElementTypes[0], + cast(Ty)->getNumElements()); + case Type::VectorTyID: + return *Entry = VectorType::get(ElementTypes[0], + cast(Ty)->getNumElements()); + case Type::PointerTyID: + return *Entry = PointerType::get(ElementTypes[0], + cast(Ty)->getAddressSpace()); + case Type::FunctionTyID: + return *Entry = FunctionType::get(ElementTypes[0], + makeArrayRef(ElementTypes).slice(1), + cast(Ty)->isVarArg()); + case Type::StructTyID: { + auto *STy = cast(Ty); + bool IsPacked = STy->isPacked(); + if (IsUniqued) + return *Entry = StructType::get(Ty->getContext(), ElementTypes, IsPacked); + + // If the type is opaque, we can just use it directly. + if (STy->isOpaque()) { + DstStructTypesSet.addOpaque(STy); + return *Entry = Ty; + } + + if (StructType *OldT = + DstStructTypesSet.findNonOpaque(ElementTypes, IsPacked)) { + STy->setName(""); + return *Entry = OldT; + } + + if (!AnyChange) { + DstStructTypesSet.addNonOpaque(STy); + return *Entry = Ty; + } - // Otherwise we create a new type and resolve its body later. This will be - // resolved by the top level of get(). - SrcDefinitionsToResolve.push_back(STy); - StructType *DTy = StructType::create(STy->getContext()); - // A new identified structure type was created. Add it to the set of - // identified structs in the destination module. - DstStructTypesSet.insert(DTy); - DstResolvedOpaqueTypes.insert(DTy); - return *Entry = DTy; + StructType *DTy = StructType::create(Ty->getContext()); + finishType(DTy, STy, ElementTypes); + return *Entry = DTy; + } + } } //===----------------------------------------------------------------------===// @@ -357,135 +358,153 @@ Type *TypeMapTy::getImpl(Type *Ty) { //===----------------------------------------------------------------------===// namespace { - class ModuleLinker; - - /// ValueMaterializerTy - Creates prototypes for functions that are lazily - /// linked on the fly. This speeds up linking for modules with many - /// lazily linked functions of which few get used. - class ValueMaterializerTy : public ValueMaterializer { - TypeMapTy &TypeMap; - Module *DstM; - std::vector &LazilyLinkFunctions; - public: - ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM, - std::vector &LazilyLinkFunctions) : - ValueMaterializer(), TypeMap(TypeMap), DstM(DstM), - LazilyLinkFunctions(LazilyLinkFunctions) { - } +class ModuleLinker; - Value *materializeValueFor(Value *V) override; +/// Creates prototypes for functions that are lazily linked on the fly. This +/// speeds up linking for modules with many/ lazily linked functions of which +/// few get used. +class ValueMaterializerTy : public ValueMaterializer { + TypeMapTy &TypeMap; + Module *DstM; + std::vector &LazilyLinkGlobalValues; + +public: + ValueMaterializerTy(TypeMapTy &TypeMap, Module *DstM, + std::vector &LazilyLinkGlobalValues) + : ValueMaterializer(), TypeMap(TypeMap), DstM(DstM), + LazilyLinkGlobalValues(LazilyLinkGlobalValues) {} + + Value *materializeValueFor(Value *V) override; +}; + +class LinkDiagnosticInfo : public DiagnosticInfo { + const Twine &Msg; + +public: + LinkDiagnosticInfo(DiagnosticSeverity Severity, const Twine &Msg); + void print(DiagnosticPrinter &DP) const override; +}; +LinkDiagnosticInfo::LinkDiagnosticInfo(DiagnosticSeverity Severity, + const Twine &Msg) + : DiagnosticInfo(DK_Linker, Severity), Msg(Msg) {} +void LinkDiagnosticInfo::print(DiagnosticPrinter &DP) const { DP << Msg; } + +/// This is an implementation class for the LinkModules function, which is the +/// entrypoint for this file. +class ModuleLinker { + Module *DstM, *SrcM; + + TypeMapTy TypeMap; + ValueMaterializerTy ValMaterializer; + + /// Mapping of values from what they used to be in Src, to what they are now + /// in DstM. ValueToValueMapTy is a ValueMap, which involves some overhead + /// due to the use of Value handles which the Linker doesn't actually need, + /// but this allows us to reuse the ValueMapper code. + ValueToValueMapTy ValueMap; + + struct AppendingVarInfo { + GlobalVariable *NewGV; // New aggregate global in dest module. + const Constant *DstInit; // Old initializer from dest module. + const Constant *SrcInit; // Old initializer from src module. }; - /// ModuleLinker - This is an implementation class for the LinkModules - /// function, which is the entrypoint for this file. - class ModuleLinker { - Module *DstM, *SrcM; + std::vector AppendingVars; - TypeMapTy TypeMap; - ValueMaterializerTy ValMaterializer; + // Set of items not to link in from source. + SmallPtrSet DoNotLinkFromSource; - /// ValueMap - Mapping of values from what they used to be in Src, to what - /// they are now in DstM. ValueToValueMapTy is a ValueMap, which involves - /// some overhead due to the use of Value handles which the Linker doesn't - /// actually need, but this allows us to reuse the ValueMapper code. - ValueToValueMapTy ValueMap; + // Vector of GlobalValues to lazily link in. + std::vector LazilyLinkGlobalValues; - struct AppendingVarInfo { - GlobalVariable *NewGV; // New aggregate global in dest module. - Constant *DstInit; // Old initializer from dest module. - Constant *SrcInit; // Old initializer from src module. - }; + /// Functions that have replaced other functions. + SmallPtrSet OverridingFunctions; - std::vector AppendingVars; + DiagnosticHandlerFunction DiagnosticHandler; + +public: + ModuleLinker(Module *dstM, Linker::IdentifiedStructTypeSet &Set, Module *srcM, + DiagnosticHandlerFunction DiagnosticHandler) + : DstM(dstM), SrcM(srcM), TypeMap(Set), + ValMaterializer(TypeMap, DstM, LazilyLinkGlobalValues), + DiagnosticHandler(DiagnosticHandler) {} - unsigned Mode; // Mode to treat source module. + bool run(); - // Set of items not to link in from source. - SmallPtrSet DoNotLinkFromSource; +private: + bool shouldLinkFromSource(bool &LinkFromSrc, const GlobalValue &Dest, + const GlobalValue &Src); - // Vector of functions to lazily link in. - std::vector LazilyLinkFunctions; + /// Helper method for setting a message and returning an error code. + bool emitError(const Twine &Message) { + DiagnosticHandler(LinkDiagnosticInfo(DS_Error, Message)); + return true; + } - bool SuppressWarnings; + void emitWarning(const Twine &Message) { + DiagnosticHandler(LinkDiagnosticInfo(DS_Warning, Message)); + } - public: - std::string ErrorMsg; + bool getComdatLeader(Module *M, StringRef ComdatName, + const GlobalVariable *&GVar); + bool computeResultingSelectionKind(StringRef ComdatName, + Comdat::SelectionKind Src, + Comdat::SelectionKind Dst, + Comdat::SelectionKind &Result, + bool &LinkFromSrc); + std::map> + ComdatsChosen; + bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK, + bool &LinkFromSrc); + + /// Given a global in the source module, return the global in the + /// destination module that is being linked to, if any. + GlobalValue *getLinkedToGlobal(const GlobalValue *SrcGV) { + // If the source has no name it can't link. If it has local linkage, + // there is no name match-up going on. + if (!SrcGV->hasName() || SrcGV->hasLocalLinkage()) + return nullptr; + + // Otherwise see if we have a match in the destination module's symtab. + GlobalValue *DGV = DstM->getNamedValue(SrcGV->getName()); + if (!DGV) + return nullptr; + + // If we found a global with the same name in the dest module, but it has + // internal linkage, we are really not doing any linkage here. + if (DGV->hasLocalLinkage()) + return nullptr; + + // Otherwise, we do in fact link to the destination global. + return DGV; + } - ModuleLinker(Module *dstM, TypeSet &Set, Module *srcM, unsigned mode, - bool SuppressWarnings=false) - : DstM(dstM), SrcM(srcM), TypeMap(Set), - ValMaterializer(TypeMap, DstM, LazilyLinkFunctions), Mode(mode), - SuppressWarnings(SuppressWarnings) {} + void computeTypeMapping(); - bool run(); + void upgradeMismatchedGlobalArray(StringRef Name); + void upgradeMismatchedGlobals(); - private: - /// emitError - Helper method for setting a message and returning an error - /// code. - bool emitError(const Twine &Message) { - ErrorMsg = Message.str(); - return true; - } + bool linkAppendingVarProto(GlobalVariable *DstGV, + const GlobalVariable *SrcGV); - bool getComdatLeader(Module *M, StringRef ComdatName, - const GlobalVariable *&GVar); - bool computeResultingSelectionKind(StringRef ComdatName, - Comdat::SelectionKind Src, - Comdat::SelectionKind Dst, - Comdat::SelectionKind &Result, - bool &LinkFromSrc); - std::map> - ComdatsChosen; - bool getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &SK, - bool &LinkFromSrc); - - /// getLinkageResult - This analyzes the two global values and determines - /// what the result will look like in the destination module. - bool getLinkageResult(GlobalValue *Dest, const GlobalValue *Src, - GlobalValue::LinkageTypes <, - GlobalValue::VisibilityTypes &Vis, - bool &LinkFromSrc); - - /// getLinkedToGlobal - Given a global in the source module, return the - /// global in the destination module that is being linked to, if any. - GlobalValue *getLinkedToGlobal(GlobalValue *SrcGV) { - // If the source has no name it can't link. If it has local linkage, - // there is no name match-up going on. - if (!SrcGV->hasName() || SrcGV->hasLocalLinkage()) - return nullptr; - - // Otherwise see if we have a match in the destination module's symtab. - GlobalValue *DGV = DstM->getNamedValue(SrcGV->getName()); - if (!DGV) return nullptr; - - // If we found a global with the same name in the dest module, but it has - // internal linkage, we are really not doing any linkage here. - if (DGV->hasLocalLinkage()) - return nullptr; - - // Otherwise, we do in fact link to the destination global. - return DGV; - } + bool linkGlobalValueProto(GlobalValue *GV); + bool linkModuleFlagsMetadata(); - void computeTypeMapping(); + void linkAppendingVarInit(const AppendingVarInfo &AVI); - bool linkAppendingVarProto(GlobalVariable *DstGV, GlobalVariable *SrcGV); - bool linkGlobalProto(GlobalVariable *SrcGV); - bool linkFunctionProto(Function *SrcF); - bool linkAliasProto(GlobalAlias *SrcA); - bool linkModuleFlagsMetadata(); + void linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src); + bool linkFunctionBody(Function &Dst, Function &Src); + void linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src); + bool linkGlobalValueBody(GlobalValue &Src); - void linkAppendingVarInit(const AppendingVarInfo &AVI); - void linkGlobalInits(); - void linkFunctionBody(Function *Dst, Function *Src); - void linkAliasBodies(); - void linkNamedMDNodes(); - }; + void linkNamedMDNodes(); + void stripReplacedSubprograms(); +}; } -/// forceRenaming - The LLVM SymbolTable class autorenames globals that conflict -/// in the symbol table. This is good for all clients except for us. Go -/// through the trouble to force this back. +/// The LLVM SymbolTable class autorenames globals that conflict in the symbol +/// table. This is good for all clients except for us. Go through the trouble +/// to force this back. static void forceRenaming(GlobalValue *GV, StringRef Name) { // If the global doesn't force its name or if it already has the right name, // there is nothing for us to do. @@ -504,20 +523,10 @@ static void forceRenaming(GlobalValue *GV, StringRef Name) { } } -/// copyGVAttributes - copy additional attributes (those not needed to construct -/// a GlobalValue) from the SrcGV to the DestGV. +/// copy additional attributes (those not needed to construct a GlobalValue) +/// from the SrcGV to the DestGV. static void copyGVAttributes(GlobalValue *DestGV, const GlobalValue *SrcGV) { - // Use the maximum alignment, rather than just copying the alignment of SrcGV. - auto *DestGO = dyn_cast(DestGV); - unsigned Alignment; - if (DestGO) - Alignment = std::max(DestGO->getAlignment(), SrcGV->getAlignment()); - DestGV->copyAttributesFrom(SrcGV); - - if (DestGO) - DestGO->setAlignment(Alignment); - forceRenaming(DestGV, SrcGV->getName()); } @@ -534,17 +543,71 @@ static bool isLessConstraining(GlobalValue::VisibilityTypes a, return false; } +/// Loop through the global variables in the src module and merge them into the +/// dest module. +static GlobalVariable *copyGlobalVariableProto(TypeMapTy &TypeMap, Module &DstM, + const GlobalVariable *SGVar) { + // No linking to be performed or linking from the source: simply create an + // identical version of the symbol over in the dest module... the + // initializer will be filled in later by LinkGlobalInits. + GlobalVariable *NewDGV = new GlobalVariable( + DstM, TypeMap.get(SGVar->getType()->getElementType()), + SGVar->isConstant(), SGVar->getLinkage(), /*init*/ nullptr, + SGVar->getName(), /*insertbefore*/ nullptr, SGVar->getThreadLocalMode(), + SGVar->getType()->getAddressSpace()); + + return NewDGV; +} + +/// Link the function in the source module into the destination module if +/// needed, setting up mapping information. +static Function *copyFunctionProto(TypeMapTy &TypeMap, Module &DstM, + const Function *SF) { + // If there is no linkage to be performed or we are linking from the source, + // bring SF over. + return Function::Create(TypeMap.get(SF->getFunctionType()), SF->getLinkage(), + SF->getName(), &DstM); +} + +/// Set up prototypes for any aliases that come over from the source module. +static GlobalAlias *copyGlobalAliasProto(TypeMapTy &TypeMap, Module &DstM, + const GlobalAlias *SGA) { + // If there is no linkage to be performed or we're linking from the source, + // bring over SGA. + auto *PTy = cast(TypeMap.get(SGA->getType())); + return GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), + SGA->getLinkage(), SGA->getName(), &DstM); +} + +static GlobalValue *copyGlobalValueProto(TypeMapTy &TypeMap, Module &DstM, + const GlobalValue *SGV) { + GlobalValue *NewGV; + if (auto *SGVar = dyn_cast(SGV)) + NewGV = copyGlobalVariableProto(TypeMap, DstM, SGVar); + else if (auto *SF = dyn_cast(SGV)) + NewGV = copyFunctionProto(TypeMap, DstM, SF); + else + NewGV = copyGlobalAliasProto(TypeMap, DstM, cast(SGV)); + copyGVAttributes(NewGV, SGV); + return NewGV; +} + Value *ValueMaterializerTy::materializeValueFor(Value *V) { - Function *SF = dyn_cast(V); - if (!SF) + auto *SGV = dyn_cast(V); + if (!SGV) return nullptr; - Function *DF = Function::Create(TypeMap.get(SF->getFunctionType()), - SF->getLinkage(), SF->getName(), DstM); - copyGVAttributes(DF, SF); + GlobalValue *DGV = copyGlobalValueProto(TypeMap, *DstM, SGV); + + if (Comdat *SC = SGV->getComdat()) { + if (auto *DGO = dyn_cast(DGV)) { + Comdat *DC = DstM->getOrInsertComdat(SC->getName()); + DGO->setComdat(DC); + } + } - LazilyLinkFunctions.push_back(SF); - return DF; + LazilyLinkGlobalValues.push_back(SGV); + return DGV; } bool ModuleLinker::getComdatLeader(Module *M, StringRef ComdatName, @@ -644,177 +707,261 @@ bool ModuleLinker::computeResultingSelectionKind(StringRef ComdatName, bool ModuleLinker::getComdatResult(const Comdat *SrcC, Comdat::SelectionKind &Result, bool &LinkFromSrc) { + Comdat::SelectionKind SSK = SrcC->getSelectionKind(); StringRef ComdatName = SrcC->getName(); Module::ComdatSymTabType &ComdatSymTab = DstM->getComdatSymbolTable(); Module::ComdatSymTabType::iterator DstCI = ComdatSymTab.find(ComdatName); - if (DstCI != ComdatSymTab.end()) { - const Comdat *DstC = &DstCI->second; - Comdat::SelectionKind SSK = SrcC->getSelectionKind(); - Comdat::SelectionKind DSK = DstC->getSelectionKind(); - if (computeResultingSelectionKind(ComdatName, SSK, DSK, Result, LinkFromSrc)) - return true; + + if (DstCI == ComdatSymTab.end()) { + // Use the comdat if it is only available in one of the modules. + LinkFromSrc = true; + Result = SSK; + return false; } - return false; + + const Comdat *DstC = &DstCI->second; + Comdat::SelectionKind DSK = DstC->getSelectionKind(); + return computeResultingSelectionKind(ComdatName, SSK, DSK, Result, + LinkFromSrc); } -/// getLinkageResult - This analyzes the two global values and determines what -/// the result will look like in the destination module. In particular, it -/// computes the resultant linkage type and visibility, computes whether the -/// global in the source should be copied over to the destination (replacing -/// the existing one), and computes whether this linkage is an error or not. -bool ModuleLinker::getLinkageResult(GlobalValue *Dest, const GlobalValue *Src, - GlobalValue::LinkageTypes <, - GlobalValue::VisibilityTypes &Vis, - bool &LinkFromSrc) { - assert(Dest && "Must have two globals being queried"); - assert(!Src->hasLocalLinkage() && - "If Src has internal linkage, Dest shouldn't be set!"); - - bool SrcIsDeclaration = Src->isDeclaration() && !Src->isMaterializable(); - bool DestIsDeclaration = Dest->isDeclaration(); +bool ModuleLinker::shouldLinkFromSource(bool &LinkFromSrc, + const GlobalValue &Dest, + const GlobalValue &Src) { + // We always have to add Src if it has appending linkage. + if (Src.hasAppendingLinkage()) { + LinkFromSrc = true; + return false; + } + + bool SrcIsDeclaration = Src.isDeclarationForLinker(); + bool DestIsDeclaration = Dest.isDeclarationForLinker(); if (SrcIsDeclaration) { // If Src is external or if both Src & Dest are external.. Just link the // external globals, we aren't adding anything. - if (Src->hasDLLImportStorageClass()) { + if (Src.hasDLLImportStorageClass()) { // If one of GVs is marked as DLLImport, result should be dllimport'ed. - if (DestIsDeclaration) { - LinkFromSrc = true; - LT = Src->getLinkage(); - } - } else if (Dest->hasExternalWeakLinkage()) { - // If the Dest is weak, use the source linkage. - LinkFromSrc = true; - LT = Src->getLinkage(); - } else { - LinkFromSrc = false; - LT = Dest->getLinkage(); + LinkFromSrc = DestIsDeclaration; + return false; } - } else if (DestIsDeclaration && !Dest->hasDLLImportStorageClass()) { + // If the Dest is weak, use the source linkage. + LinkFromSrc = Dest.hasExternalWeakLinkage(); + return false; + } + + if (DestIsDeclaration) { // If Dest is external but Src is not: LinkFromSrc = true; - LT = Src->getLinkage(); - } else if (Src->isWeakForLinker()) { - // At this point we know that Dest has LinkOnce, External*, Weak, Common, - // or DLL* linkage. - if (Dest->hasExternalWeakLinkage() || - Dest->hasAvailableExternallyLinkage() || - (Dest->hasLinkOnceLinkage() && - (Src->hasWeakLinkage() || Src->hasCommonLinkage()))) { + return false; + } + + if (Src.hasCommonLinkage()) { + if (Dest.hasLinkOnceLinkage() || Dest.hasWeakLinkage()) { LinkFromSrc = true; - LT = Src->getLinkage(); - } else { - LinkFromSrc = false; - LT = Dest->getLinkage(); + return false; } - } else if (Dest->isWeakForLinker()) { - // At this point we know that Src has External* or DLL* linkage. - if (Src->hasExternalWeakLinkage()) { + + if (!Dest.hasCommonLinkage()) { LinkFromSrc = false; - LT = Dest->getLinkage(); - } else { + return false; + } + + // FIXME: Make datalayout mandatory and just use getDataLayout(). + DataLayout DL(Dest.getParent()); + + uint64_t DestSize = DL.getTypeAllocSize(Dest.getType()->getElementType()); + uint64_t SrcSize = DL.getTypeAllocSize(Src.getType()->getElementType()); + LinkFromSrc = SrcSize > DestSize; + return false; + } + + if (Src.isWeakForLinker()) { + assert(!Dest.hasExternalWeakLinkage()); + assert(!Dest.hasAvailableExternallyLinkage()); + + if (Dest.hasLinkOnceLinkage() && Src.hasWeakLinkage()) { LinkFromSrc = true; - LT = GlobalValue::ExternalLinkage; + return false; } - } else { - assert((Dest->hasExternalLinkage() || Dest->hasExternalWeakLinkage()) && - (Src->hasExternalLinkage() || Src->hasExternalWeakLinkage()) && - "Unexpected linkage type!"); - return emitError("Linking globals named '" + Src->getName() + - "': symbol multiply defined!"); + + LinkFromSrc = false; + return false; } - // Compute the visibility. We follow the rules in the System V Application - // Binary Interface. - assert(!GlobalValue::isLocalLinkage(LT) && - "Symbols with local linkage should not be merged"); - Vis = isLessConstraining(Src->getVisibility(), Dest->getVisibility()) ? - Dest->getVisibility() : Src->getVisibility(); - return false; + if (Dest.isWeakForLinker()) { + assert(Src.hasExternalLinkage()); + LinkFromSrc = true; + return false; + } + + assert(!Src.hasExternalWeakLinkage()); + assert(!Dest.hasExternalWeakLinkage()); + assert(Dest.hasExternalLinkage() && Src.hasExternalLinkage() && + "Unexpected linkage type!"); + return emitError("Linking globals named '" + Src.getName() + + "': symbol multiply defined!"); } -/// computeTypeMapping - Loop over all of the linked values to compute type -/// mappings. For example, if we link "extern Foo *x" and "Foo *x = NULL", then -/// we have two struct types 'Foo' but one got renamed when the module was -/// loaded into the same LLVMContext. +/// Loop over all of the linked values to compute type mappings. For example, +/// if we link "extern Foo *x" and "Foo *x = NULL", then we have two struct +/// types 'Foo' but one got renamed when the module was loaded into the same +/// LLVMContext. void ModuleLinker::computeTypeMapping() { - // Incorporate globals. - for (Module::global_iterator I = SrcM->global_begin(), - E = SrcM->global_end(); I != E; ++I) { - GlobalValue *DGV = getLinkedToGlobal(I); - if (!DGV) continue; + for (GlobalValue &SGV : SrcM->globals()) { + GlobalValue *DGV = getLinkedToGlobal(&SGV); + if (!DGV) + continue; - if (!DGV->hasAppendingLinkage() || !I->hasAppendingLinkage()) { - TypeMap.addTypeMapping(DGV->getType(), I->getType()); + if (!DGV->hasAppendingLinkage() || !SGV.hasAppendingLinkage()) { + TypeMap.addTypeMapping(DGV->getType(), SGV.getType()); continue; } // Unify the element type of appending arrays. ArrayType *DAT = cast(DGV->getType()->getElementType()); - ArrayType *SAT = cast(I->getType()->getElementType()); + ArrayType *SAT = cast(SGV.getType()->getElementType()); TypeMap.addTypeMapping(DAT->getElementType(), SAT->getElementType()); } - // Incorporate functions. - for (Module::iterator I = SrcM->begin(), E = SrcM->end(); I != E; ++I) { - if (GlobalValue *DGV = getLinkedToGlobal(I)) - TypeMap.addTypeMapping(DGV->getType(), I->getType()); + for (GlobalValue &SGV : *SrcM) { + if (GlobalValue *DGV = getLinkedToGlobal(&SGV)) + TypeMap.addTypeMapping(DGV->getType(), SGV.getType()); + } + + for (GlobalValue &SGV : SrcM->aliases()) { + if (GlobalValue *DGV = getLinkedToGlobal(&SGV)) + TypeMap.addTypeMapping(DGV->getType(), SGV.getType()); } // Incorporate types by name, scanning all the types in the source module. // At this point, the destination module may have a type "%foo = { i32 }" for // example. When the source module got loaded into the same LLVMContext, if // it had the same type, it would have been renamed to "%foo.42 = { i32 }". - TypeFinder SrcStructTypes; - SrcStructTypes.run(*SrcM, true); - SmallPtrSet SrcStructTypesSet(SrcStructTypes.begin(), - SrcStructTypes.end()); - - for (unsigned i = 0, e = SrcStructTypes.size(); i != e; ++i) { - StructType *ST = SrcStructTypes[i]; - if (!ST->hasName()) continue; + std::vector Types = SrcM->getIdentifiedStructTypes(); + for (StructType *ST : Types) { + if (!ST->hasName()) + continue; // Check to see if there is a dot in the name followed by a digit. size_t DotPos = ST->getName().rfind('.'); if (DotPos == 0 || DotPos == StringRef::npos || ST->getName().back() == '.' || - !isdigit(static_cast(ST->getName()[DotPos+1]))) + !isdigit(static_cast(ST->getName()[DotPos + 1]))) continue; // Check to see if the destination module has a struct with the prefix name. - if (StructType *DST = DstM->getTypeByName(ST->getName().substr(0, DotPos))) - // Don't use it if this actually came from the source module. They're in - // the same LLVMContext after all. Also don't use it unless the type is - // actually used in the destination module. This can happen in situations - // like this: - // - // Module A Module B - // -------- -------- - // %Z = type { %A } %B = type { %C.1 } - // %A = type { %B.1, [7 x i8] } %C.1 = type { i8* } - // %B.1 = type { %C } %A.2 = type { %B.3, [5 x i8] } - // %C = type { i8* } %B.3 = type { %C.1 } - // - // When we link Module B with Module A, the '%B' in Module B is - // used. However, that would then use '%C.1'. But when we process '%C.1', - // we prefer to take the '%C' version. So we are then left with both - // '%C.1' and '%C' being used for the same types. This leads to some - // variables using one type and some using the other. - if (!SrcStructTypesSet.count(DST) && TypeMap.DstStructTypesSet.count(DST)) - TypeMap.addTypeMapping(DST, ST); - } + StructType *DST = DstM->getTypeByName(ST->getName().substr(0, DotPos)); + if (!DST) + continue; - // Don't bother incorporating aliases, they aren't generally typed well. + // Don't use it if this actually came from the source module. They're in + // the same LLVMContext after all. Also don't use it unless the type is + // actually used in the destination module. This can happen in situations + // like this: + // + // Module A Module B + // -------- -------- + // %Z = type { %A } %B = type { %C.1 } + // %A = type { %B.1, [7 x i8] } %C.1 = type { i8* } + // %B.1 = type { %C } %A.2 = type { %B.3, [5 x i8] } + // %C = type { i8* } %B.3 = type { %C.1 } + // + // When we link Module B with Module A, the '%B' in Module B is + // used. However, that would then use '%C.1'. But when we process '%C.1', + // we prefer to take the '%C' version. So we are then left with both + // '%C.1' and '%C' being used for the same types. This leads to some + // variables using one type and some using the other. + if (TypeMap.DstStructTypesSet.hasType(DST)) + TypeMap.addTypeMapping(DST, ST); + } // Now that we have discovered all of the type equivalences, get a body for // any 'opaque' types in the dest module that are now resolved. TypeMap.linkDefinedTypeBodies(); } -/// linkAppendingVarProto - If there were any appending global variables, link -/// them together now. Return true on error. +static void upgradeGlobalArray(GlobalVariable *GV) { + ArrayType *ATy = cast(GV->getType()->getElementType()); + StructType *OldTy = cast(ATy->getElementType()); + assert(OldTy->getNumElements() == 2 && "Expected to upgrade from 2 elements"); + + // Get the upgraded 3 element type. + PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo(); + Type *Tys[3] = {OldTy->getElementType(0), OldTy->getElementType(1), + VoidPtrTy}; + StructType *NewTy = StructType::get(GV->getContext(), Tys, false); + + // Build new constants with a null third field filled in. + Constant *OldInitC = GV->getInitializer(); + ConstantArray *OldInit = dyn_cast(OldInitC); + if (!OldInit && !isa(OldInitC)) + // Invalid initializer; give up. + return; + std::vector Initializers; + if (OldInit && OldInit->getNumOperands()) { + Value *Null = Constant::getNullValue(VoidPtrTy); + for (Use &U : OldInit->operands()) { + ConstantStruct *Init = cast(U.get()); + Initializers.push_back(ConstantStruct::get( + NewTy, Init->getOperand(0), Init->getOperand(1), Null, nullptr)); + } + } + assert(Initializers.size() == ATy->getNumElements() && + "Failed to copy all array elements"); + + // Replace the old GV with a new one. + ATy = ArrayType::get(NewTy, Initializers.size()); + Constant *NewInit = ConstantArray::get(ATy, Initializers); + GlobalVariable *NewGV = new GlobalVariable( + *GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "", + GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(), + GV->isExternallyInitialized()); + NewGV->copyAttributesFrom(GV); + NewGV->takeName(GV); + assert(GV->use_empty() && "program cannot use initializer list"); + GV->eraseFromParent(); +} + +void ModuleLinker::upgradeMismatchedGlobalArray(StringRef Name) { + // Look for the global arrays. + auto *DstGV = dyn_cast_or_null(DstM->getNamedValue(Name)); + if (!DstGV) + return; + auto *SrcGV = dyn_cast_or_null(SrcM->getNamedValue(Name)); + if (!SrcGV) + return; + + // Check if the types already match. + auto *DstTy = cast(DstGV->getType()->getElementType()); + auto *SrcTy = + cast(TypeMap.get(SrcGV->getType()->getElementType())); + if (DstTy == SrcTy) + return; + + // Grab the element types. We can only upgrade an array of a two-field + // struct. Only bother if the other one has three-fields. + auto *DstEltTy = cast(DstTy->getElementType()); + auto *SrcEltTy = cast(SrcTy->getElementType()); + if (DstEltTy->getNumElements() == 2 && SrcEltTy->getNumElements() == 3) { + upgradeGlobalArray(DstGV); + return; + } + if (DstEltTy->getNumElements() == 3 && SrcEltTy->getNumElements() == 2) + upgradeGlobalArray(SrcGV); + + // We can't upgrade any other differences. +} + +void ModuleLinker::upgradeMismatchedGlobals() { + upgradeMismatchedGlobalArray("llvm.global_ctors"); + upgradeMismatchedGlobalArray("llvm.global_dtors"); +} + +/// If there were any appending global variables, link them together now. +/// Return true on error. bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, - GlobalVariable *SrcGV) { + const GlobalVariable *SrcGV) { if (!SrcGV->hasAppendingLinkage() || !DstGV->hasAppendingLinkage()) return emitError("Linking globals named '" + SrcGV->getName() + @@ -879,252 +1026,102 @@ bool ModuleLinker::linkAppendingVarProto(GlobalVariable *DstGV, return false; } -/// linkGlobalProto - Loop through the global variables in the src module and -/// merge them into the dest module. -bool ModuleLinker::linkGlobalProto(GlobalVariable *SGV) { +bool ModuleLinker::linkGlobalValueProto(GlobalValue *SGV) { GlobalValue *DGV = getLinkedToGlobal(SGV); - llvm::Optional NewVisibility; + + // Handle the ultra special appending linkage case first. + if (DGV && DGV->hasAppendingLinkage()) + return linkAppendingVarProto(cast(DGV), + cast(SGV)); + + bool LinkFromSrc = true; + Comdat *C = nullptr; + GlobalValue::VisibilityTypes Visibility = SGV->getVisibility(); bool HasUnnamedAddr = SGV->hasUnnamedAddr(); - bool LinkFromSrc = false; - Comdat *DC = nullptr; if (const Comdat *SC = SGV->getComdat()) { Comdat::SelectionKind SK; std::tie(SK, LinkFromSrc) = ComdatsChosen[SC]; - DC = DstM->getOrInsertComdat(SC->getName()); - DC->setSelectionKind(SK); + C = DstM->getOrInsertComdat(SC->getName()); + C->setSelectionKind(SK); + } else if (DGV) { + if (shouldLinkFromSource(LinkFromSrc, *DGV, *SGV)) + return true; } - if (DGV) { - if (!DC) { - // Concatenation of appending linkage variables is magic and handled later. - if (DGV->hasAppendingLinkage() || SGV->hasAppendingLinkage()) - return linkAppendingVarProto(cast(DGV), SGV); - - // Determine whether linkage of these two globals follows the source - // module's definition or the destination module's definition. - GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage; - GlobalValue::VisibilityTypes NV; - if (getLinkageResult(DGV, SGV, NewLinkage, NV, LinkFromSrc)) - return true; - NewVisibility = NV; - HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr(); - - // If we're not linking from the source, then keep the definition that we - // have. - if (!LinkFromSrc) { - // Special case for const propagation. - if (GlobalVariable *DGVar = dyn_cast(DGV)) - if (DGVar->isDeclaration() && SGV->isConstant() && - !DGVar->isConstant()) - DGVar->setConstant(true); - - // Set calculated linkage, visibility and unnamed_addr. - DGV->setLinkage(NewLinkage); - DGV->setVisibility(*NewVisibility); - DGV->setUnnamedAddr(HasUnnamedAddr); - } - } + if (!LinkFromSrc) { + // Track the source global so that we don't attempt to copy it over when + // processing global initializers. + DoNotLinkFromSource.insert(SGV); - if (!LinkFromSrc) { + if (DGV) // Make sure to remember this mapping. - ValueMap[SGV] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGV->getType())); - - // Track the source global so that we don't attempt to copy it over when - // processing global initializers. - DoNotLinkFromSource.insert(SGV); - - return false; - } + ValueMap[SGV] = + ConstantExpr::getBitCast(DGV, TypeMap.get(SGV->getType())); } - // If the Comdat this variable was inside of wasn't selected, skip it. - if (DC && !DGV && !LinkFromSrc) { - DoNotLinkFromSource.insert(SGV); - return false; - } - - // No linking to be performed or linking from the source: simply create an - // identical version of the symbol over in the dest module... the - // initializer will be filled in later by LinkGlobalInits. - GlobalVariable *NewDGV = - new GlobalVariable(*DstM, TypeMap.get(SGV->getType()->getElementType()), - SGV->isConstant(), SGV->getLinkage(), /*init*/nullptr, - SGV->getName(), /*insertbefore*/nullptr, - SGV->getThreadLocalMode(), - SGV->getType()->getAddressSpace()); - // Propagate alignment, visibility and section info. - copyGVAttributes(NewDGV, SGV); - if (NewVisibility) - NewDGV->setVisibility(*NewVisibility); - NewDGV->setUnnamedAddr(HasUnnamedAddr); - - if (DC) - NewDGV->setComdat(DC); - if (DGV) { - DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDGV, DGV->getType())); - DGV->eraseFromParent(); - } - - // Make sure to remember this mapping. - ValueMap[SGV] = NewDGV; - return false; -} - -/// linkFunctionProto - Link the function in the source module into the -/// destination module if needed, setting up mapping information. -bool ModuleLinker::linkFunctionProto(Function *SF) { - GlobalValue *DGV = getLinkedToGlobal(SF); - llvm::Optional NewVisibility; - bool HasUnnamedAddr = SF->hasUnnamedAddr(); - - bool LinkFromSrc = false; - Comdat *DC = nullptr; - if (const Comdat *SC = SF->getComdat()) { - Comdat::SelectionKind SK; - std::tie(SK, LinkFromSrc) = ComdatsChosen[SC]; - DC = DstM->getOrInsertComdat(SC->getName()); - DC->setSelectionKind(SK); + Visibility = isLessConstraining(Visibility, DGV->getVisibility()) + ? DGV->getVisibility() + : Visibility; + HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr(); } - if (DGV) { - if (!DC) { - GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage; - GlobalValue::VisibilityTypes NV; - if (getLinkageResult(DGV, SF, NewLinkage, NV, LinkFromSrc)) - return true; - NewVisibility = NV; - HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr(); - - if (!LinkFromSrc) { - // Set calculated linkage - DGV->setLinkage(NewLinkage); - DGV->setVisibility(*NewVisibility); - DGV->setUnnamedAddr(HasUnnamedAddr); - } - } - - if (!LinkFromSrc) { - // Make sure to remember this mapping. - ValueMap[SF] = ConstantExpr::getBitCast(DGV, TypeMap.get(SF->getType())); - - // Track the function from the source module so we don't attempt to remap - // it. - DoNotLinkFromSource.insert(SF); + if (!LinkFromSrc && !DGV) + return false; + GlobalValue *NewGV; + if (!LinkFromSrc) { + NewGV = DGV; + } else { + // If the GV is to be lazily linked, don't create it just yet. + // The ValueMaterializerTy will deal with creating it if it's used. + if (!DGV && (SGV->hasLocalLinkage() || SGV->hasLinkOnceLinkage() || + SGV->hasAvailableExternallyLinkage())) { + DoNotLinkFromSource.insert(SGV); return false; } - } - // If the function is to be lazily linked, don't create it just yet. - // The ValueMaterializerTy will deal with creating it if it's used. - if (!DGV && (SF->hasLocalLinkage() || SF->hasLinkOnceLinkage() || - SF->hasAvailableExternallyLinkage())) { - DoNotLinkFromSource.insert(SF); - return false; - } + NewGV = copyGlobalValueProto(TypeMap, *DstM, SGV); - // If the Comdat this function was inside of wasn't selected, skip it. - if (DC && !DGV && !LinkFromSrc) { - DoNotLinkFromSource.insert(SF); - return false; + if (DGV && isa(DGV)) + if (auto *NewF = dyn_cast(NewGV)) + OverridingFunctions.insert(NewF); } - // If there is no linkage to be performed or we are linking from the source, - // bring SF over. - Function *NewDF = Function::Create(TypeMap.get(SF->getFunctionType()), - SF->getLinkage(), SF->getName(), DstM); - copyGVAttributes(NewDF, SF); - if (NewVisibility) - NewDF->setVisibility(*NewVisibility); - NewDF->setUnnamedAddr(HasUnnamedAddr); + NewGV->setUnnamedAddr(HasUnnamedAddr); + NewGV->setVisibility(Visibility); - if (DC) - NewDF->setComdat(DC); + if (auto *NewGO = dyn_cast(NewGV)) { + if (C) + NewGO->setComdat(C); - if (DGV) { - // Any uses of DF need to change to NewDF, with cast. - DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDF, DGV->getType())); - DGV->eraseFromParent(); + if (DGV && DGV->hasCommonLinkage() && SGV->hasCommonLinkage()) + NewGO->setAlignment(std::max(DGV->getAlignment(), SGV->getAlignment())); } - ValueMap[SF] = NewDF; - return false; -} - -/// LinkAliasProto - Set up prototypes for any aliases that come over from the -/// source module. -bool ModuleLinker::linkAliasProto(GlobalAlias *SGA) { - GlobalValue *DGV = getLinkedToGlobal(SGA); - llvm::Optional NewVisibility; - bool HasUnnamedAddr = SGA->hasUnnamedAddr(); - - bool LinkFromSrc = false; - Comdat *DC = nullptr; - if (const Comdat *SC = SGA->getComdat()) { - Comdat::SelectionKind SK; - std::tie(SK, LinkFromSrc) = ComdatsChosen[SC]; - DC = DstM->getOrInsertComdat(SC->getName()); - DC->setSelectionKind(SK); + if (auto *NewGVar = dyn_cast(NewGV)) { + auto *DGVar = dyn_cast_or_null(DGV); + auto *SGVar = dyn_cast(SGV); + if (DGVar && SGVar && DGVar->isDeclaration() && SGVar->isDeclaration() && + (!DGVar->isConstant() || !SGVar->isConstant())) + NewGVar->setConstant(false); } - if (DGV) { - if (!DC) { - GlobalValue::LinkageTypes NewLinkage = GlobalValue::InternalLinkage; - GlobalValue::VisibilityTypes NV; - if (getLinkageResult(DGV, SGA, NewLinkage, NV, LinkFromSrc)) - return true; - NewVisibility = NV; - HasUnnamedAddr = HasUnnamedAddr && DGV->hasUnnamedAddr(); - - if (!LinkFromSrc) { - // Set calculated linkage. - DGV->setLinkage(NewLinkage); - DGV->setVisibility(*NewVisibility); - DGV->setUnnamedAddr(HasUnnamedAddr); - } - } - - if (!LinkFromSrc) { - // Make sure to remember this mapping. - ValueMap[SGA] = ConstantExpr::getBitCast(DGV,TypeMap.get(SGA->getType())); - - // Track the alias from the source module so we don't attempt to remap it. - DoNotLinkFromSource.insert(SGA); - - return false; + // Make sure to remember this mapping. + if (NewGV != DGV) { + if (DGV) { + DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewGV, DGV->getType())); + DGV->eraseFromParent(); } + ValueMap[SGV] = NewGV; } - // If the Comdat this alias was inside of wasn't selected, skip it. - if (DC && !DGV && !LinkFromSrc) { - DoNotLinkFromSource.insert(SGA); - return false; - } - - // If there is no linkage to be performed or we're linking from the source, - // bring over SGA. - auto *PTy = cast(TypeMap.get(SGA->getType())); - auto *NewDA = - GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), - SGA->getLinkage(), SGA->getName(), DstM); - copyGVAttributes(NewDA, SGA); - if (NewVisibility) - NewDA->setVisibility(*NewVisibility); - NewDA->setUnnamedAddr(HasUnnamedAddr); - - if (DGV) { - // Any uses of DGV need to change to NewDA, with cast. - DGV->replaceAllUsesWith(ConstantExpr::getBitCast(NewDA, DGV->getType())); - DGV->eraseFromParent(); - } - - ValueMap[SGA] = NewDA; return false; } -static void getArrayElements(Constant *C, SmallVectorImpl &Dest) { +static void getArrayElements(const Constant *C, + SmallVectorImpl &Dest) { unsigned NumElements = cast(C->getType())->getNumElements(); for (unsigned i = 0; i != NumElements; ++i) @@ -1133,94 +1130,115 @@ static void getArrayElements(Constant *C, SmallVectorImpl &Dest) { void ModuleLinker::linkAppendingVarInit(const AppendingVarInfo &AVI) { // Merge the initializer. - SmallVector Elements; - getArrayElements(AVI.DstInit, Elements); + SmallVector DstElements; + getArrayElements(AVI.DstInit, DstElements); - Constant *SrcInit = MapValue(AVI.SrcInit, ValueMap, RF_None, &TypeMap, &ValMaterializer); - getArrayElements(SrcInit, Elements); + SmallVector SrcElements; + getArrayElements(AVI.SrcInit, SrcElements); ArrayType *NewType = cast(AVI.NewGV->getType()->getElementType()); - AVI.NewGV->setInitializer(ConstantArray::get(NewType, Elements)); -} -/// linkGlobalInits - Update the initializers in the Dest module now that all -/// globals that may be referenced are in Dest. -void ModuleLinker::linkGlobalInits() { - // Loop over all of the globals in the src module, mapping them over as we go - for (Module::const_global_iterator I = SrcM->global_begin(), - E = SrcM->global_end(); I != E; ++I) { + StringRef Name = AVI.NewGV->getName(); + bool IsNewStructor = + (Name == "llvm.global_ctors" || Name == "llvm.global_dtors") && + cast(NewType->getElementType())->getNumElements() == 3; - // Only process initialized GV's or ones not already in dest. - if (!I->hasInitializer() || DoNotLinkFromSource.count(I)) continue; - - // Grab destination global variable. - GlobalVariable *DGV = cast(ValueMap[I]); - // Figure out what the initializer looks like in the dest module. - DGV->setInitializer(MapValue(I->getInitializer(), ValueMap, - RF_None, &TypeMap, &ValMaterializer)); + for (auto *V : SrcElements) { + if (IsNewStructor) { + Constant *Key = V->getAggregateElement(2); + if (DoNotLinkFromSource.count(Key)) + continue; + } + DstElements.push_back( + MapValue(V, ValueMap, RF_None, &TypeMap, &ValMaterializer)); } + if (IsNewStructor) { + NewType = ArrayType::get(NewType->getElementType(), DstElements.size()); + AVI.NewGV->mutateType(PointerType::get(NewType, 0)); + } + + AVI.NewGV->setInitializer(ConstantArray::get(NewType, DstElements)); } -/// linkFunctionBody - Copy the source function over into the dest function and -/// fix up references to values. At this point we know that Dest is an external -/// function, and that Src is not. -void ModuleLinker::linkFunctionBody(Function *Dst, Function *Src) { - assert(Src && Dst && Dst->isDeclaration() && !Src->isDeclaration()); +/// Update the initializers in the Dest module now that all globals that may be +/// referenced are in Dest. +void ModuleLinker::linkGlobalInit(GlobalVariable &Dst, GlobalVariable &Src) { + // Figure out what the initializer looks like in the dest module. + Dst.setInitializer(MapValue(Src.getInitializer(), ValueMap, RF_None, &TypeMap, + &ValMaterializer)); +} + +/// Copy the source function over into the dest function and fix up references +/// to values. At this point we know that Dest is an external function, and +/// that Src is not. +bool ModuleLinker::linkFunctionBody(Function &Dst, Function &Src) { + assert(Dst.isDeclaration() && !Src.isDeclaration()); + + // Materialize if needed. + if (std::error_code EC = Src.materialize()) + return emitError(EC.message()); + + // Link in the prefix data. + if (Src.hasPrefixData()) + Dst.setPrefixData(MapValue(Src.getPrefixData(), ValueMap, RF_None, &TypeMap, + &ValMaterializer)); + + // Link in the prologue data. + if (Src.hasPrologueData()) + Dst.setPrologueData(MapValue(Src.getPrologueData(), ValueMap, RF_None, + &TypeMap, &ValMaterializer)); // Go through and convert function arguments over, remembering the mapping. - Function::arg_iterator DI = Dst->arg_begin(); - for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); - I != E; ++I, ++DI) { - DI->setName(I->getName()); // Copy the name over. + Function::arg_iterator DI = Dst.arg_begin(); + for (Argument &Arg : Src.args()) { + DI->setName(Arg.getName()); // Copy the name over. // Add a mapping to our mapping. - ValueMap[I] = DI; + ValueMap[&Arg] = DI; + ++DI; } - if (Mode == Linker::DestroySource) { - // Splice the body of the source function into the dest function. - Dst->getBasicBlockList().splice(Dst->end(), Src->getBasicBlockList()); + // Splice the body of the source function into the dest function. + Dst.getBasicBlockList().splice(Dst.end(), Src.getBasicBlockList()); - // At this point, all of the instructions and values of the function are now - // copied over. The only problem is that they are still referencing values in - // the Source function as operands. Loop through all of the operands of the - // functions and patch them up to point to the local versions. - for (Function::iterator BB = Dst->begin(), BE = Dst->end(); BB != BE; ++BB) - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) - RemapInstruction(I, ValueMap, RF_IgnoreMissingEntries, - &TypeMap, &ValMaterializer); - - } else { - // Clone the body of the function into the dest function. - SmallVector Returns; // Ignore returns. - CloneFunctionInto(Dst, Src, ValueMap, false, Returns, "", nullptr, - &TypeMap, &ValMaterializer); - } + // At this point, all of the instructions and values of the function are now + // copied over. The only problem is that they are still referencing values in + // the Source function as operands. Loop through all of the operands of the + // functions and patch them up to point to the local versions. + for (BasicBlock &BB : Dst) + for (Instruction &I : BB) + RemapInstruction(&I, ValueMap, RF_IgnoreMissingEntries, &TypeMap, + &ValMaterializer); // There is no need to map the arguments anymore. - for (Function::arg_iterator I = Src->arg_begin(), E = Src->arg_end(); - I != E; ++I) - ValueMap.erase(I); + for (Argument &Arg : Src.args()) + ValueMap.erase(&Arg); + Src.Dematerialize(); + return false; } -/// linkAliasBodies - Insert all of the aliases in Src into the Dest module. -void ModuleLinker::linkAliasBodies() { - for (Module::alias_iterator I = SrcM->alias_begin(), E = SrcM->alias_end(); - I != E; ++I) { - if (DoNotLinkFromSource.count(I)) - continue; - if (Constant *Aliasee = I->getAliasee()) { - GlobalAlias *DA = cast(ValueMap[I]); - Constant *Val = - MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer); - DA->setAliasee(Val); - } +void ModuleLinker::linkAliasBody(GlobalAlias &Dst, GlobalAlias &Src) { + Constant *Aliasee = Src.getAliasee(); + Constant *Val = + MapValue(Aliasee, ValueMap, RF_None, &TypeMap, &ValMaterializer); + Dst.setAliasee(Val); +} + +bool ModuleLinker::linkGlobalValueBody(GlobalValue &Src) { + Value *Dst = ValueMap[&Src]; + assert(Dst); + if (auto *F = dyn_cast(&Src)) + return linkFunctionBody(cast(*Dst), *F); + if (auto *GVar = dyn_cast(&Src)) { + linkGlobalInit(cast(*Dst), *GVar); + return false; } + linkAliasBody(cast(*Dst), cast(Src)); + return false; } -/// linkNamedMDNodes - Insert all of the named MDNodes in Src into the Dest -/// module. +/// Insert all of the named MDNodes in Src into the Dest module. void ModuleLinker::linkNamedMDNodes() { const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata(); for (Module::const_named_metadata_iterator I = SrcM->named_metadata_begin(), @@ -1230,13 +1248,54 @@ void ModuleLinker::linkNamedMDNodes() { NamedMDNode *DestNMD = DstM->getOrInsertNamedMetadata(I->getName()); // Add Src elements into Dest node. for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) - DestNMD->addOperand(MapValue(I->getOperand(i), ValueMap, - RF_None, &TypeMap, &ValMaterializer)); + DestNMD->addOperand(MapMetadata(I->getOperand(i), ValueMap, RF_None, + &TypeMap, &ValMaterializer)); } } -/// linkModuleFlagsMetadata - Merge the linker flags in Src into the Dest -/// module. +/// Drop DISubprograms that have been superseded. +/// +/// FIXME: this creates an asymmetric result: we strip losing subprograms from +/// DstM, but leave losing subprograms in SrcM. Instead we should also strip +/// losers from SrcM, but this requires extra plumbing in MapMetadata. +void ModuleLinker::stripReplacedSubprograms() { + // Avoid quadratic runtime by returning early when there's nothing to do. + if (OverridingFunctions.empty()) + return; + + // Move the functions now, so the set gets cleared even on early returns. + auto Functions = std::move(OverridingFunctions); + OverridingFunctions.clear(); + + // Drop subprograms whose functions have been overridden by the new compile + // unit. + NamedMDNode *CompileUnits = DstM->getNamedMetadata("llvm.dbg.cu"); + if (!CompileUnits) + return; + for (unsigned I = 0, E = CompileUnits->getNumOperands(); I != E; ++I) { + DICompileUnit CU(CompileUnits->getOperand(I)); + assert(CU && "Expected valid compile unit"); + + DITypedArray SPs(CU.getSubprograms()); + assert(SPs && "Expected valid subprogram array"); + + SmallVector NewSPs; + NewSPs.reserve(SPs.getNumElements()); + for (unsigned S = 0, SE = SPs.getNumElements(); S != SE; ++S) { + DISubprogram SP = SPs.getElement(S); + if (SP && SP.getFunction() && Functions.count(SP.getFunction())) + continue; + + NewSPs.push_back(SP); + } + + // Redirect operand to the overriding subprogram. + if (NewSPs.size() != SPs.getNumElements()) + CU.replaceSubprograms(DIArray(MDNode::get(DstM->getContext(), NewSPs))); + } +} + +/// Merge the linker flags in Src into the Dest module. bool ModuleLinker::linkModuleFlagsMetadata() { // If the source module has no module flags, we are done. const NamedMDNode *SrcModFlags = SrcM->getModuleFlagsMetadata(); @@ -1253,17 +1312,17 @@ bool ModuleLinker::linkModuleFlagsMetadata() { } // First build a map of the existing module flags and requirements. - DenseMap Flags; + DenseMap> Flags; SmallSetVector Requirements; for (unsigned I = 0, E = DstModFlags->getNumOperands(); I != E; ++I) { MDNode *Op = DstModFlags->getOperand(I); - ConstantInt *Behavior = cast(Op->getOperand(0)); + ConstantInt *Behavior = mdconst::extract(Op->getOperand(0)); MDString *ID = cast(Op->getOperand(1)); if (Behavior->getZExtValue() == Module::Require) { Requirements.insert(cast(Op->getOperand(2))); } else { - Flags[ID] = Op; + Flags[ID] = std::make_pair(Op, I); } } @@ -1272,9 +1331,12 @@ bool ModuleLinker::linkModuleFlagsMetadata() { bool HasErr = false; for (unsigned I = 0, E = SrcModFlags->getNumOperands(); I != E; ++I) { MDNode *SrcOp = SrcModFlags->getOperand(I); - ConstantInt *SrcBehavior = cast(SrcOp->getOperand(0)); + ConstantInt *SrcBehavior = + mdconst::extract(SrcOp->getOperand(0)); MDString *ID = cast(SrcOp->getOperand(1)); - MDNode *DstOp = Flags.lookup(ID); + MDNode *DstOp; + unsigned DstIndex; + std::tie(DstOp, DstIndex) = Flags.lookup(ID); unsigned SrcBehaviorValue = SrcBehavior->getZExtValue(); // If this is a requirement, add it and continue. @@ -1289,13 +1351,14 @@ bool ModuleLinker::linkModuleFlagsMetadata() { // If there is no existing flag with this ID, just add it. if (!DstOp) { - Flags[ID] = SrcOp; + Flags[ID] = std::make_pair(SrcOp, DstModFlags->getNumOperands()); DstModFlags->addOperand(SrcOp); continue; } // Otherwise, perform a merge. - ConstantInt *DstBehavior = cast(DstOp->getOperand(0)); + ConstantInt *DstBehavior = + mdconst::extract(DstOp->getOperand(0)); unsigned DstBehaviorValue = DstBehavior->getZExtValue(); // If either flag has override behavior, handle it first. @@ -1309,8 +1372,8 @@ bool ModuleLinker::linkModuleFlagsMetadata() { continue; } else if (SrcBehaviorValue == Module::Override) { // Update the destination flag to that of the source. - DstOp->replaceOperandWith(0, SrcBehavior); - DstOp->replaceOperandWith(2, SrcOp->getOperand(2)); + DstModFlags->setOperand(DstIndex, SrcOp); + Flags[ID].first = SrcOp; continue; } @@ -1321,6 +1384,13 @@ bool ModuleLinker::linkModuleFlagsMetadata() { continue; } + auto replaceDstValue = [&](MDNode *New) { + Metadata *FlagOps[] = {DstOp->getOperand(0), ID, New}; + MDNode *Flag = MDNode::get(DstM->getContext(), FlagOps); + DstModFlags->setOperand(DstIndex, Flag); + Flags[ID].first = Flag; + }; + // Perform the merge for standard behavior types. switch (SrcBehaviorValue) { case Module::Require: @@ -1336,39 +1406,35 @@ bool ModuleLinker::linkModuleFlagsMetadata() { case Module::Warning: { // Emit a warning if the values differ. if (SrcOp->getOperand(2) != DstOp->getOperand(2)) { - if (!SuppressWarnings) { - errs() << "WARNING: linking module flags '" << ID->getString() - << "': IDs have conflicting values"; - } + emitWarning("linking module flags '" + ID->getString() + + "': IDs have conflicting values"); } continue; } case Module::Append: { MDNode *DstValue = cast(DstOp->getOperand(2)); MDNode *SrcValue = cast(SrcOp->getOperand(2)); - unsigned NumOps = DstValue->getNumOperands() + SrcValue->getNumOperands(); - Value **VP, **Values = VP = new Value*[NumOps]; - for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i, ++VP) - *VP = DstValue->getOperand(i); - for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i, ++VP) - *VP = SrcValue->getOperand(i); - DstOp->replaceOperandWith(2, MDNode::get(DstM->getContext(), - ArrayRef(Values, - NumOps))); - delete[] Values; + SmallVector MDs; + MDs.reserve(DstValue->getNumOperands() + SrcValue->getNumOperands()); + for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i) + MDs.push_back(DstValue->getOperand(i)); + for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i) + MDs.push_back(SrcValue->getOperand(i)); + + replaceDstValue(MDNode::get(DstM->getContext(), MDs)); break; } case Module::AppendUnique: { - SmallSetVector Elts; + SmallSetVector Elts; MDNode *DstValue = cast(DstOp->getOperand(2)); MDNode *SrcValue = cast(SrcOp->getOperand(2)); for (unsigned i = 0, e = DstValue->getNumOperands(); i != e; ++i) Elts.insert(DstValue->getOperand(i)); for (unsigned i = 0, e = SrcValue->getNumOperands(); i != e; ++i) Elts.insert(SrcValue->getOperand(i)); - DstOp->replaceOperandWith(2, MDNode::get(DstM->getContext(), - ArrayRef(Elts.begin(), - Elts.end()))); + + replaceDstValue(MDNode::get(DstM->getContext(), + makeArrayRef(Elts.begin(), Elts.end()))); break; } } @@ -1378,9 +1444,9 @@ bool ModuleLinker::linkModuleFlagsMetadata() { for (unsigned I = 0, E = Requirements.size(); I != E; ++I) { MDNode *Requirement = Requirements[I]; MDString *Flag = cast(Requirement->getOperand(0)); - Value *ReqValue = Requirement->getOperand(1); + Metadata *ReqValue = Requirement->getOperand(1); - MDNode *Op = Flags[Flag]; + MDNode *Op = Flags[Flag].first; if (!Op || Op->getOperand(2) != ReqValue) { HasErr |= emitError("linking module flags '" + Flag->getString() + "': does not have the required value"); @@ -1406,23 +1472,19 @@ bool ModuleLinker::run() { if (SrcM->getDataLayout() && DstM->getDataLayout() && *SrcM->getDataLayout() != *DstM->getDataLayout()) { - if (!SuppressWarnings) { - errs() << "WARNING: Linking two modules of different data layouts: '" - << SrcM->getModuleIdentifier() << "' is '" - << SrcM->getDataLayoutStr() << "' whereas '" - << DstM->getModuleIdentifier() << "' is '" - << DstM->getDataLayoutStr() << "'\n"; - } + emitWarning("Linking two modules of different data layouts: '" + + SrcM->getModuleIdentifier() + "' is '" + + SrcM->getDataLayoutStr() + "' whereas '" + + DstM->getModuleIdentifier() + "' is '" + + DstM->getDataLayoutStr() + "'\n"); } if (!SrcM->getTargetTriple().empty() && DstM->getTargetTriple() != SrcM->getTargetTriple()) { - if (!SuppressWarnings) { - errs() << "WARNING: Linking two modules of different target triples: " - << SrcM->getModuleIdentifier() << "' is '" - << SrcM->getTargetTriple() << "' whereas '" - << DstM->getModuleIdentifier() << "' is '" - << DstM->getTargetTriple() << "'\n"; - } + emitWarning("Linking two modules of different target triples: " + + SrcM->getModuleIdentifier() + "' is '" + + SrcM->getTargetTriple() + "' whereas '" + + DstM->getModuleIdentifier() + "' is '" + + DstM->getTargetTriple() + "'\n"); } // Append the module inline asm string. @@ -1438,7 +1500,7 @@ bool ModuleLinker::run() { computeTypeMapping(); ComdatsChosen.clear(); - for (const StringMapEntry &SMEC : SrcM->getComdatSymbolTable()) { + for (const auto &SMEC : SrcM->getComdatSymbolTable()) { const Comdat &C = SMEC.getValue(); if (ComdatsChosen.count(&C)) continue; @@ -1449,11 +1511,14 @@ bool ModuleLinker::run() { ComdatsChosen[&C] = std::make_pair(SK, LinkFromSrc); } + // Upgrade mismatched global arrays. + upgradeMismatchedGlobals(); + // Insert all of the globals in src into the DstM module... without linking // initializers (which could refer to functions not yet mapped over). for (Module::global_iterator I = SrcM->global_begin(), E = SrcM->global_end(); I != E; ++I) - if (linkGlobalProto(I)) + if (linkGlobalValueProto(I)) return true; // Link the functions together between the two modules, without doing function @@ -1462,45 +1527,51 @@ bool ModuleLinker::run() { // all of the global values that may be referenced are available in our // ValueMap. for (Module::iterator I = SrcM->begin(), E = SrcM->end(); I != E; ++I) - if (linkFunctionProto(I)) + if (linkGlobalValueProto(I)) return true; // If there were any aliases, link them now. for (Module::alias_iterator I = SrcM->alias_begin(), E = SrcM->alias_end(); I != E; ++I) - if (linkAliasProto(I)) + if (linkGlobalValueProto(I)) return true; for (unsigned i = 0, e = AppendingVars.size(); i != e; ++i) linkAppendingVarInit(AppendingVars[i]); + for (const auto &Entry : DstM->getComdatSymbolTable()) { + const Comdat &C = Entry.getValue(); + if (C.getSelectionKind() == Comdat::Any) + continue; + const GlobalValue *GV = SrcM->getNamedValue(C.getName()); + assert(GV); + MapValue(GV, ValueMap, RF_None, &TypeMap, &ValMaterializer); + } + // Link in the function bodies that are defined in the source module into // DstM. - for (Module::iterator SF = SrcM->begin(), E = SrcM->end(); SF != E; ++SF) { - // Skip if not linking from source. - if (DoNotLinkFromSource.count(SF)) continue; - - Function *DF = cast(ValueMap[SF]); - if (SF->hasPrefixData()) { - // Link in the prefix data. - DF->setPrefixData(MapValue( - SF->getPrefixData(), ValueMap, RF_None, &TypeMap, &ValMaterializer)); - } + for (Function &SF : *SrcM) { + // Skip if no body (function is external). + if (SF.isDeclaration()) + continue; - // Skip if no body (function is external) or materialize. - if (SF->isDeclaration()) { - if (!SF->isMaterializable()) - continue; - if (SF->Materialize(&ErrorMsg)) - return true; - } + // Skip if not linking from source. + if (DoNotLinkFromSource.count(&SF)) + continue; - linkFunctionBody(DF, SF); - SF->Dematerialize(); + if (linkGlobalValueBody(SF)) + return true; } // Resolve all uses of aliases with aliasees. - linkAliasBodies(); + for (GlobalAlias &Src : SrcM->aliases()) { + if (DoNotLinkFromSource.count(&Src)) + continue; + linkGlobalValueBody(Src); + } + + // Strip replaced subprograms before linking together compile units. + stripReplacedSubprograms(); // Remap all of the named MDNodes in Src into the DstM module. We do this // after linking GlobalValues so that MDNodes that reference GlobalValues @@ -1513,64 +1584,130 @@ bool ModuleLinker::run() { // Update the initializers in the DstM module now that all globals that may // be referenced are in DstM. - linkGlobalInits(); + for (GlobalVariable &Src : SrcM->globals()) { + // Only process initialized GV's or ones not already in dest. + if (!Src.hasInitializer() || DoNotLinkFromSource.count(&Src)) + continue; + linkGlobalValueBody(Src); + } // Process vector of lazily linked in functions. - bool LinkedInAnyFunctions; - do { - LinkedInAnyFunctions = false; - - for(std::vector::iterator I = LazilyLinkFunctions.begin(), - E = LazilyLinkFunctions.end(); I != E; ++I) { - Function *SF = *I; - if (!SF) - continue; + while (!LazilyLinkGlobalValues.empty()) { + GlobalValue *SGV = LazilyLinkGlobalValues.back(); + LazilyLinkGlobalValues.pop_back(); - Function *DF = cast(ValueMap[SF]); - if (SF->hasPrefixData()) { - // Link in the prefix data. - DF->setPrefixData(MapValue(SF->getPrefixData(), - ValueMap, - RF_None, - &TypeMap, - &ValMaterializer)); - } + assert(!SGV->isDeclaration() && "users should not pass down decls"); + if (linkGlobalValueBody(*SGV)) + return true; + } - // Materialize if necessary. - if (SF->isDeclaration()) { - if (!SF->isMaterializable()) - continue; - if (SF->Materialize(&ErrorMsg)) - return true; - } + return false; +} - // Erase from vector *before* the function body is linked - linkFunctionBody could - // invalidate I. - LazilyLinkFunctions.erase(I); +Linker::StructTypeKeyInfo::KeyTy::KeyTy(ArrayRef E, bool P) + : ETypes(E), IsPacked(P) {} - // Link in function body. - linkFunctionBody(DF, SF); - SF->Dematerialize(); +Linker::StructTypeKeyInfo::KeyTy::KeyTy(const StructType *ST) + : ETypes(ST->elements()), IsPacked(ST->isPacked()) {} - // Set flag to indicate we may have more functions to lazily link in - // since we linked in a function. - LinkedInAnyFunctions = true; - break; - } - } while (LinkedInAnyFunctions); +bool Linker::StructTypeKeyInfo::KeyTy::operator==(const KeyTy &That) const { + if (IsPacked != That.IsPacked) + return false; + if (ETypes != That.ETypes) + return false; + return true; +} - // Now that all of the types from the source are used, resolve any structs - // copied over to the dest that didn't exist there. - TypeMap.linkDefinedTypeBodies(); +bool Linker::StructTypeKeyInfo::KeyTy::operator!=(const KeyTy &That) const { + return !this->operator==(That); +} - return false; +StructType *Linker::StructTypeKeyInfo::getEmptyKey() { + return DenseMapInfo::getEmptyKey(); +} + +StructType *Linker::StructTypeKeyInfo::getTombstoneKey() { + return DenseMapInfo::getTombstoneKey(); +} + +unsigned Linker::StructTypeKeyInfo::getHashValue(const KeyTy &Key) { + return hash_combine(hash_combine_range(Key.ETypes.begin(), Key.ETypes.end()), + Key.IsPacked); +} + +unsigned Linker::StructTypeKeyInfo::getHashValue(const StructType *ST) { + return getHashValue(KeyTy(ST)); +} + +bool Linker::StructTypeKeyInfo::isEqual(const KeyTy &LHS, + const StructType *RHS) { + if (RHS == getEmptyKey() || RHS == getTombstoneKey()) + return false; + return LHS == KeyTy(RHS); +} + +bool Linker::StructTypeKeyInfo::isEqual(const StructType *LHS, + const StructType *RHS) { + if (RHS == getEmptyKey()) + return LHS == getEmptyKey(); + + if (RHS == getTombstoneKey()) + return LHS == getTombstoneKey(); + + return KeyTy(LHS) == KeyTy(RHS); +} + +void Linker::IdentifiedStructTypeSet::addNonOpaque(StructType *Ty) { + assert(!Ty->isOpaque()); + NonOpaqueStructTypes.insert(Ty); +} + +void Linker::IdentifiedStructTypeSet::addOpaque(StructType *Ty) { + assert(Ty->isOpaque()); + OpaqueStructTypes.insert(Ty); +} + +StructType * +Linker::IdentifiedStructTypeSet::findNonOpaque(ArrayRef ETypes, + bool IsPacked) { + Linker::StructTypeKeyInfo::KeyTy Key(ETypes, IsPacked); + auto I = NonOpaqueStructTypes.find_as(Key); + if (I == NonOpaqueStructTypes.end()) + return nullptr; + return *I; } -Linker::Linker(Module *M, bool SuppressWarnings) - : Composite(M), SuppressWarnings(SuppressWarnings) { +bool Linker::IdentifiedStructTypeSet::hasType(StructType *Ty) { + if (Ty->isOpaque()) + return OpaqueStructTypes.count(Ty); + auto I = NonOpaqueStructTypes.find(Ty); + if (I == NonOpaqueStructTypes.end()) + return false; + return *I == Ty; +} + +void Linker::init(Module *M, DiagnosticHandlerFunction DiagnosticHandler) { + this->Composite = M; + this->DiagnosticHandler = DiagnosticHandler; + TypeFinder StructTypes; StructTypes.run(*M, true); - IdentifiedStructTypes.insert(StructTypes.begin(), StructTypes.end()); + for (StructType *Ty : StructTypes) { + if (Ty->isOpaque()) + IdentifiedStructTypes.addOpaque(Ty); + else + IdentifiedStructTypes.addNonOpaque(Ty); + } +} + +Linker::Linker(Module *M, DiagnosticHandlerFunction DiagnosticHandler) { + init(M, DiagnosticHandler); +} + +Linker::Linker(Module *M) { + init(M, [this](const DiagnosticInfo &DI) { + Composite->getContext().diagnose(DI); + }); } Linker::~Linker() { @@ -1581,30 +1718,30 @@ void Linker::deleteModule() { Composite = nullptr; } -bool Linker::linkInModule(Module *Src, unsigned Mode, std::string *ErrorMsg) { - ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, Mode, - SuppressWarnings); - if (TheLinker.run()) { - if (ErrorMsg) - *ErrorMsg = TheLinker.ErrorMsg; - return true; - } - return false; +bool Linker::linkInModule(Module *Src) { + ModuleLinker TheLinker(Composite, IdentifiedStructTypes, Src, + DiagnosticHandler); + return TheLinker.run(); } //===----------------------------------------------------------------------===// // LinkModules entrypoint. //===----------------------------------------------------------------------===// -/// LinkModules - This function links two modules together, with the resulting -/// Dest module modified to be the composite of the two input modules. If an -/// error occurs, true is returned and ErrorMsg (if not null) is set to indicate -/// the problem. Upon failure, the Dest module could be in a modified state, -/// and shouldn't be relied on to be consistent. -bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode, - std::string *ErrorMsg) { +/// This function links two modules together, with the resulting Dest module +/// modified to be the composite of the two input modules. If an error occurs, +/// true is returned and ErrorMsg (if not null) is set to indicate the problem. +/// Upon failure, the Dest module could be in a modified state, and shouldn't be +/// relied on to be consistent. +bool Linker::LinkModules(Module *Dest, Module *Src, + DiagnosticHandlerFunction DiagnosticHandler) { + Linker L(Dest, DiagnosticHandler); + return L.linkInModule(Src); +} + +bool Linker::LinkModules(Module *Dest, Module *Src) { Linker L(Dest); - return L.linkInModule(Src, Mode, ErrorMsg); + return L.linkInModule(Src); } //===----------------------------------------------------------------------===// @@ -1612,11 +1749,16 @@ bool Linker::LinkModules(Module *Dest, Module *Src, unsigned Mode, //===----------------------------------------------------------------------===// LLVMBool LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, - LLVMLinkerMode Mode, char **OutMessages) { - std::string Messages; - LLVMBool Result = Linker::LinkModules(unwrap(Dest), unwrap(Src), - Mode, OutMessages? &Messages : nullptr); - if (OutMessages) - *OutMessages = strdup(Messages.c_str()); + unsigned Unused, char **OutMessages) { + Module *D = unwrap(Dest); + std::string Message; + raw_string_ostream Stream(Message); + DiagnosticPrinterRawOStream DP(Stream); + + LLVMBool Result = Linker::LinkModules( + D, unwrap(Src), [&](const DiagnosticInfo &DI) { DI.print(DP); }); + + if (OutMessages && Result) + *OutMessages = strdup(Message.c_str()); return Result; } diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt index 330519e..7181bdc 100644 --- a/lib/MC/CMakeLists.txt +++ b/lib/MC/CMakeLists.txt @@ -11,13 +11,11 @@ add_llvm_library(LLVMMC MCCodeEmitter.cpp MCCodeGenInfo.cpp MCContext.cpp - MCDisassembler.cpp MCDwarf.cpp MCELF.cpp MCELFObjectTargetWriter.cpp MCELFStreamer.cpp MCExpr.cpp - MCExternalSymbolizer.cpp MCInst.cpp MCInstPrinter.cpp MCInstrAnalysis.cpp @@ -30,7 +28,6 @@ add_llvm_library(LLVMMC MCObjectStreamer.cpp MCObjectWriter.cpp MCRegisterInfo.cpp - MCRelocationInfo.cpp MCSection.cpp MCSectionCOFF.cpp MCSectionELF.cpp @@ -42,6 +39,7 @@ add_llvm_library(LLVMMC MCTargetOptions.cpp MCValue.cpp MCWin64EH.cpp + MCWinEH.cpp MachObjectWriter.cpp StringTableBuilder.cpp SubtargetFeature.cpp @@ -50,6 +48,5 @@ add_llvm_library(LLVMMC YAML.cpp ) -add_subdirectory(MCAnalysis) add_subdirectory(MCParser) add_subdirectory(MCDisassembler) diff --git a/lib/MC/ConstantPools.cpp b/lib/MC/ConstantPools.cpp index c4cea60..a239a8f 100644 --- a/lib/MC/ConstantPools.cpp +++ b/lib/MC/ConstantPools.cpp @@ -11,10 +11,10 @@ // //===----------------------------------------------------------------------===// #include "llvm/ADT/MapVector.h" +#include "llvm/MC/ConstantPools.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/MC/ConstantPools.h" using namespace llvm; // diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index 5779b27..4dcf910 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -31,8 +31,8 @@ #include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/Compression.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Endian.h" #include "llvm/Support/ELF.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include using namespace llvm; @@ -81,23 +81,13 @@ public: struct ELFRelocationEntry { uint64_t Offset; // Where is the relocation. - bool UseSymbol; // Relocate with a symbol, not the section. - union { - const MCSymbol *Symbol; // The symbol to relocate with. - const MCSectionData *Section; // The section to relocate with. - }; + const MCSymbol *Symbol; // The symbol to relocate with. unsigned Type; // The type of the relocation. uint64_t Addend; // The addend to use. ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, uint64_t Addend) - : Offset(Offset), UseSymbol(true), Symbol(Symbol), Type(Type), - Addend(Addend) {} - - ELFRelocationEntry(uint64_t Offset, const MCSectionData *Section, - unsigned Type, uint64_t Addend) - : Offset(Offset), UseSymbol(false), Section(Section), Type(Type), - Addend(Addend) {} + : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {} }; class ELFObjectWriter : public MCObjectWriter { @@ -137,6 +127,14 @@ class ELFObjectWriter : public MCObjectWriter { // Support lexicographic sorting. bool operator<(const ELFSymbolData &RHS) const { + unsigned LHSType = MCELF::GetType(*SymbolData); + unsigned RHSType = MCELF::GetType(*RHS.SymbolData); + if (LHSType == ELF::STT_SECTION && RHSType != ELF::STT_SECTION) + return false; + if (LHSType != ELF::STT_SECTION && RHSType == ELF::STT_SECTION) + return true; + if (LHSType == ELF::STT_SECTION && RHSType == ELF::STT_SECTION) + return SectionIndex < RHS.SectionIndex; return Name < RHS.Name; } }; @@ -221,7 +219,7 @@ class ELFObjectWriter : public MCObjectWriter { const MCSymbolData *SD, uint64_t C, unsigned Type) const; - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; @@ -246,7 +244,7 @@ class ELFObjectWriter : public MCObjectWriter { /// \param NumRegularSections - Number of non-relocation sections. void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap, + const RevGroupMapTy &RevGroupMap, unsigned NumRegularSections); void ComputeIndexMap(MCAssembler &Asm, @@ -651,22 +649,6 @@ void ELFObjectWriter::WriteSymbolTable(MCDataFragment *SymtabF, WriteSymbol(Writer, MSD, Layout); } - // Write out a symbol table entry for each regular section. - for (MCAssembler::const_iterator i = Asm.begin(), e = Asm.end(); i != e; - ++i) { - const MCSectionELF &Section = - static_cast(i->getSection()); - if (Section.getType() == ELF::SHT_RELA || - Section.getType() == ELF::SHT_REL || - Section.getType() == ELF::SHT_STRTAB || - Section.getType() == ELF::SHT_SYMTAB || - Section.getType() == ELF::SHT_SYMTAB_SHNDX) - continue; - Writer.writeSymbol(0, ELF::STT_SECTION, 0, 0, ELF::STV_DEFAULT, - SectionIndexMap.lookup(&Section), false); - LastLocalSymbolIndex++; - } - for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) { ELFSymbolData &MSD = ExternalSymbolData[i]; MCSymbolData &Data = *MSD.SymbolData; @@ -770,8 +752,9 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, } // Most TLS relocations use a got, so they need the symbol. Even those that - // are just an offset (@tpoff), require a symbol in some linkers (gold, - // but not bfd ld). + // are just an offset (@tpoff), require a symbol in gold versions before + // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed + // http://sourceware.org/PR16773. if (Flags & ELF::SHF_TLS) return true; @@ -806,13 +789,11 @@ static const MCSymbol *getWeakRef(const MCSymbolRefExpr &Ref) { return nullptr; } -void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, +void ELFObjectWriter::RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) { + const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { const MCSectionData *FixupSection = Fragment->getParent(); uint64_t C = Target.getConstant(); uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); @@ -881,8 +862,11 @@ void ELFObjectWriter::RecordRelocation(const MCAssembler &Asm, if (!RelocateWithSymbol) { const MCSection *SecA = (SymA && !SymA->isUndefined()) ? &SymA->getSection() : nullptr; - const MCSectionData *SecAD = SecA ? &Asm.getSectionData(*SecA) : nullptr; - ELFRelocationEntry Rec(FixupOffset, SecAD, Type, Addend); + auto *ELFSec = cast_or_null(SecA); + MCSymbol *SectionSymbol = + ELFSec ? Asm.getContext().getOrCreateSectionSymbol(*ELFSec) + : nullptr; + ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend); Relocations[FixupSection].push_back(Rec); return; } @@ -991,7 +975,7 @@ void ELFObjectWriter::ComputeIndexMap(MCAssembler &Asm, void ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, - RevGroupMapTy RevGroupMap, + const RevGroupMapTy &RevGroupMap, unsigned NumRegularSections) { // FIXME: Is this the correct place to do this? // FIXME: Why is an undefined reference to _GLOBAL_OFFSET_TABLE_ needed? @@ -1037,7 +1021,7 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, MSD.SectionIndex = ELF::SHN_COMMON; } else if (BaseSymbol->isUndefined()) { if (isSignature && !Used) - MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap[&Symbol]); + MSD.SectionIndex = SectionIndexMap.lookup(RevGroupMap.lookup(&Symbol)); else MSD.SectionIndex = ELF::SHN_UNDEF; if (!Used && WeakrefUsed) @@ -1060,7 +1044,10 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, Buf += Name.substr(Pos + Skip); Name = Buf; } - MSD.Name = StrTabBuilder.add(Name); + + // Sections have their own string table + if (MCELF::GetType(SD) != ELF::STT_SECTION) + MSD.Name = StrTabBuilder.add(Name); if (MSD.SectionIndex == ELF::SHN_UNDEF) UndefinedSymbolData.push_back(MSD); @@ -1073,14 +1060,16 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i) StrTabBuilder.add(*i); - StrTabBuilder.finalize(); + StrTabBuilder.finalize(StringTableBuilder::ELF); for (auto i = Asm.file_names_begin(), e = Asm.file_names_end(); i != e; ++i) FileSymbolData.push_back(StrTabBuilder.getOffset(*i)); - for (ELFSymbolData& MSD : LocalSymbolData) - MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); - for (ELFSymbolData& MSD : ExternalSymbolData) + for (ELFSymbolData &MSD : LocalSymbolData) + MSD.StringIndex = MCELF::GetType(*MSD.SymbolData) == ELF::STT_SECTION + ? 0 + : StrTabBuilder.getOffset(MSD.Name); + for (ELFSymbolData &MSD : ExternalSymbolData) MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); for (ELFSymbolData& MSD : UndefinedSymbolData) MSD.StringIndex = StrTabBuilder.getOffset(MSD.Name); @@ -1096,8 +1085,6 @@ ELFObjectWriter::computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i) LocalSymbolData[i].SymbolData->setIndex(Index++); - Index += NumRegularSections; - for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i) ExternalSymbolData[i].SymbolData->setIndex(Index++); for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) @@ -1353,18 +1340,8 @@ void ELFObjectWriter::WriteRelocationsFragment(const MCAssembler &Asm, for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { const ELFRelocationEntry &Entry = Relocs[e - i - 1]; - - unsigned Index; - if (Entry.UseSymbol) { - Index = getSymbolIndexInSymbolTable(Asm, Entry.Symbol); - } else { - const MCSectionData *Sec = Entry.Section; - if (Sec) - Index = Sec->getOrdinal() + FileSymbolData.size() + - LocalSymbolData.size() + 1; - else - Index = 0; - } + unsigned Index = + Entry.Symbol ? getSymbolIndexInSymbolTable(Asm, Entry.Symbol) : 0; if (is64Bit()) { write(*F, Entry.Offset); @@ -1446,7 +1423,7 @@ void ELFObjectWriter::CreateMetadataSections(MCAssembler &Asm, static_cast(it->getSection()); ShStrTabBuilder.add(Section.getSectionName()); } - ShStrTabBuilder.finalize(); + ShStrTabBuilder.finalize(StringTableBuilder::ELF); F->getContents().append(ShStrTabBuilder.data().begin(), ShStrTabBuilder.data().end()); } @@ -1457,14 +1434,7 @@ void ELFObjectWriter::CreateIndexedSections(MCAssembler &Asm, RevGroupMapTy &RevGroupMap, SectionIndexMapTy &SectionIndexMap, const RelMapTy &RelMap) { - // Create the .note.GNU-stack section if needed. MCContext &Ctx = Asm.getContext(); - if (Asm.getNoExecStack()) { - const MCSectionELF *GnuStackSection = - Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, 0, - SectionKind::getReadOnly()); - Asm.getOrCreateSectionData(*GnuStackSection); - } // Build the groups for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); diff --git a/lib/MC/LLVMBuild.txt b/lib/MC/LLVMBuild.txt index 3fcb50b..f06be45 100644 --- a/lib/MC/LLVMBuild.txt +++ b/lib/MC/LLVMBuild.txt @@ -16,7 +16,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = MCAnalysis MCDisassembler MCParser +subdirectories = MCDisassembler MCParser [component_0] type = Library diff --git a/lib/MC/MCAnalysis/CMakeLists.txt b/lib/MC/MCAnalysis/CMakeLists.txt deleted file mode 100644 index 81eae2d..0000000 --- a/lib/MC/MCAnalysis/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -add_llvm_library(LLVMMCAnalysis - MCAtom.cpp - MCFunction.cpp - MCModule.cpp - MCModuleYAML.cpp - MCObjectDisassembler.cpp - MCObjectSymbolizer.cpp -) diff --git a/lib/MC/MCAnalysis/LLVMBuild.txt b/lib/MC/MCAnalysis/LLVMBuild.txt deleted file mode 100644 index 1b58fec..0000000 --- a/lib/MC/MCAnalysis/LLVMBuild.txt +++ /dev/null @@ -1,5 +0,0 @@ -[component_0] -type = Library -name = MCAnalysis -parent = Libraries -required_libraries = MC Object Support diff --git a/lib/MC/MCAnalysis/MCAtom.cpp b/lib/MC/MCAnalysis/MCAtom.cpp deleted file mode 100644 index 82056ee..0000000 --- a/lib/MC/MCAnalysis/MCAtom.cpp +++ /dev/null @@ -1,114 +0,0 @@ -//===- lib/MC/MCAtom.cpp - MCAtom implementation --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "llvm/Support/ErrorHandling.h" -#include - -using namespace llvm; - -// Pin the vtable to this file. -void MCAtom::anchor() {} - -void MCAtom::remap(uint64_t NewBegin, uint64_t NewEnd) { - Parent->remap(this, NewBegin, NewEnd); -} - -void MCAtom::remapForTruncate(uint64_t TruncPt) { - assert((TruncPt >= Begin && TruncPt < End) && - "Truncation point not contained in atom!"); - remap(Begin, TruncPt); -} - -void MCAtom::remapForSplit(uint64_t SplitPt, - uint64_t &LBegin, uint64_t &LEnd, - uint64_t &RBegin, uint64_t &REnd) { - assert((SplitPt > Begin && SplitPt <= End) && - "Splitting at point not contained in atom!"); - - // Compute the new begin/end points. - LBegin = Begin; - LEnd = SplitPt - 1; - RBegin = SplitPt; - REnd = End; - - // Remap this atom to become the lower of the two new ones. - remap(LBegin, LEnd); -} - -// MCDataAtom - -void MCDataAtom::addData(const MCData &D) { - Data.push_back(D); - if (Data.size() > End + 1 - Begin) - remap(Begin, End + 1); -} - -void MCDataAtom::truncate(uint64_t TruncPt) { - remapForTruncate(TruncPt); - - Data.resize(TruncPt - Begin + 1); -} - -MCDataAtom *MCDataAtom::split(uint64_t SplitPt) { - uint64_t LBegin, LEnd, RBegin, REnd; - remapForSplit(SplitPt, LBegin, LEnd, RBegin, REnd); - - MCDataAtom *RightAtom = Parent->createDataAtom(RBegin, REnd); - RightAtom->setName(getName()); - - std::vector::iterator I = Data.begin() + (RBegin - LBegin); - assert(I != Data.end() && "Split point not found in range!"); - - std::copy(I, Data.end(), std::back_inserter(RightAtom->Data)); - Data.erase(I, Data.end()); - return RightAtom; -} - -// MCTextAtom - -void MCTextAtom::addInst(const MCInst &I, uint64_t Size) { - if (NextInstAddress + Size - 1 > End) - remap(Begin, NextInstAddress + Size - 1); - Insts.push_back(MCDecodedInst(I, NextInstAddress, Size)); - NextInstAddress += Size; -} - -void MCTextAtom::truncate(uint64_t TruncPt) { - remapForTruncate(TruncPt); - - InstListTy::iterator I = Insts.begin(); - while (I != Insts.end() && I->Address <= TruncPt) ++I; - - assert(I != Insts.end() && "Truncation point not found in disassembly!"); - assert(I->Address == TruncPt + 1 && - "Truncation point does not fall on instruction boundary"); - - Insts.erase(I, Insts.end()); -} - -MCTextAtom *MCTextAtom::split(uint64_t SplitPt) { - uint64_t LBegin, LEnd, RBegin, REnd; - remapForSplit(SplitPt, LBegin, LEnd, RBegin, REnd); - - MCTextAtom *RightAtom = Parent->createTextAtom(RBegin, REnd); - RightAtom->setName(getName()); - - InstListTy::iterator I = Insts.begin(); - while (I != Insts.end() && I->Address < SplitPt) ++I; - assert(I != Insts.end() && "Split point not found in disassembly!"); - assert(I->Address == SplitPt && - "Split point does not fall on instruction boundary!"); - - std::copy(I, Insts.end(), std::back_inserter(RightAtom->Insts)); - Insts.erase(I, Insts.end()); - Parent->splitBasicBlocksForAtom(this, RightAtom); - return RightAtom; -} diff --git a/lib/MC/MCAnalysis/MCFunction.cpp b/lib/MC/MCAnalysis/MCFunction.cpp deleted file mode 100644 index 4e09d1a..0000000 --- a/lib/MC/MCAnalysis/MCFunction.cpp +++ /dev/null @@ -1,76 +0,0 @@ -//===-- lib/MC/MCFunction.cpp -----------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAnalysis/MCFunction.h" -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include - -using namespace llvm; - -// MCFunction - -MCFunction::MCFunction(StringRef Name, MCModule *Parent) - : Name(Name), ParentModule(Parent) -{} - -MCBasicBlock &MCFunction::createBlock(const MCTextAtom &TA) { - std::unique_ptr MCBB(new MCBasicBlock(TA, this)); - Blocks.push_back(std::move(MCBB)); - return *Blocks.back(); -} - -MCBasicBlock *MCFunction::find(uint64_t StartAddr) { - for (const_iterator I = begin(), E = end(); I != E; ++I) - if ((*I)->getInsts()->getBeginAddr() == StartAddr) - return I->get(); - return nullptr; -} - -const MCBasicBlock *MCFunction::find(uint64_t StartAddr) const { - return const_cast(this)->find(StartAddr); -} - -// MCBasicBlock - -MCBasicBlock::MCBasicBlock(const MCTextAtom &Insts, MCFunction *Parent) - : Insts(&Insts), Parent(Parent) { - getParent()->getParent()->trackBBForAtom(&Insts, this); -} - -void MCBasicBlock::addSuccessor(const MCBasicBlock *MCBB) { - if (!isSuccessor(MCBB)) - Successors.push_back(MCBB); -} - -bool MCBasicBlock::isSuccessor(const MCBasicBlock *MCBB) const { - return std::find(Successors.begin(), Successors.end(), - MCBB) != Successors.end(); -} - -void MCBasicBlock::addPredecessor(const MCBasicBlock *MCBB) { - if (!isPredecessor(MCBB)) - Predecessors.push_back(MCBB); -} - -bool MCBasicBlock::isPredecessor(const MCBasicBlock *MCBB) const { - return std::find(Predecessors.begin(), Predecessors.end(), - MCBB) != Predecessors.end(); -} - -void MCBasicBlock::splitBasicBlock(MCBasicBlock *SplitBB) { - assert(Insts->getEndAddr() + 1 == SplitBB->Insts->getBeginAddr() && - "Splitting unrelated basic blocks!"); - SplitBB->addPredecessor(this); - assert(SplitBB->Successors.empty() && - "Split basic block shouldn't already have successors!"); - SplitBB->Successors = Successors; - Successors.clear(); - addSuccessor(SplitBB); -} diff --git a/lib/MC/MCAnalysis/MCModule.cpp b/lib/MC/MCAnalysis/MCModule.cpp deleted file mode 100644 index 7512299..0000000 --- a/lib/MC/MCAnalysis/MCModule.cpp +++ /dev/null @@ -1,142 +0,0 @@ -//===- lib/MC/MCModule.cpp - MCModule implementation ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCFunction.h" -#include - -using namespace llvm; - -static bool AtomComp(const MCAtom *L, uint64_t Addr) { - return L->getEndAddr() < Addr; -} - -static bool AtomCompInv(uint64_t Addr, const MCAtom *R) { - return Addr < R->getEndAddr(); -} - -void MCModule::map(MCAtom *NewAtom) { - uint64_t Begin = NewAtom->Begin; - - assert(Begin <= NewAtom->End && "Creating MCAtom with endpoints reversed?"); - - // Check for atoms already covering this range. - AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(), - Begin, AtomComp); - assert((I == atom_end() || (*I)->getBeginAddr() > NewAtom->End) - && "Offset range already occupied!"); - - // Insert the new atom to the list. - Atoms.insert(I, NewAtom); -} - -MCTextAtom *MCModule::createTextAtom(uint64_t Begin, uint64_t End) { - MCTextAtom *NewAtom = new MCTextAtom(this, Begin, End); - map(NewAtom); - return NewAtom; -} - -MCDataAtom *MCModule::createDataAtom(uint64_t Begin, uint64_t End) { - MCDataAtom *NewAtom = new MCDataAtom(this, Begin, End); - map(NewAtom); - return NewAtom; -} - -// remap - Update the interval mapping for an atom. -void MCModule::remap(MCAtom *Atom, uint64_t NewBegin, uint64_t NewEnd) { - // Find and erase the old mapping. - AtomListTy::iterator I = std::lower_bound(atom_begin(), atom_end(), - Atom->Begin, AtomComp); - assert(I != atom_end() && "Atom offset not found in module!"); - assert(*I == Atom && "Previous atom mapping was invalid!"); - Atoms.erase(I); - - // FIXME: special case NewBegin == Atom->Begin - - // Insert the new mapping. - AtomListTy::iterator NewI = std::lower_bound(atom_begin(), atom_end(), - NewBegin, AtomComp); - assert((NewI == atom_end() || (*NewI)->getBeginAddr() > Atom->End) - && "Offset range already occupied!"); - Atoms.insert(NewI, Atom); - - // Update the atom internal bounds. - Atom->Begin = NewBegin; - Atom->End = NewEnd; -} - -const MCAtom *MCModule::findAtomContaining(uint64_t Addr) const { - AtomListTy::const_iterator I = std::lower_bound(atom_begin(), atom_end(), - Addr, AtomComp); - if (I != atom_end() && (*I)->getBeginAddr() <= Addr) - return *I; - return nullptr; -} - -MCAtom *MCModule::findAtomContaining(uint64_t Addr) { - return const_cast( - const_cast(this)->findAtomContaining(Addr)); -} - -const MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) const { - AtomListTy::const_iterator I = std::upper_bound(atom_begin(), atom_end(), - Addr, AtomCompInv); - if (I != atom_end()) - return *I; - return nullptr; -} - -MCAtom *MCModule::findFirstAtomAfter(uint64_t Addr) { - return const_cast( - const_cast(this)->findFirstAtomAfter(Addr)); -} - -MCFunction *MCModule::createFunction(StringRef Name) { - std::unique_ptr MCF(new MCFunction(Name, this)); - Functions.push_back(std::move(MCF)); - return Functions.back().get(); -} - -static bool CompBBToAtom(MCBasicBlock *BB, const MCTextAtom *Atom) { - return BB->getInsts() < Atom; -} - -void MCModule::splitBasicBlocksForAtom(const MCTextAtom *TA, - const MCTextAtom *NewTA) { - BBsByAtomTy::iterator - I = std::lower_bound(BBsByAtom.begin(), BBsByAtom.end(), - TA, CompBBToAtom); - for (; I != BBsByAtom.end() && (*I)->getInsts() == TA; ++I) { - MCBasicBlock *BB = *I; - MCBasicBlock *NewBB = &BB->getParent()->createBlock(*NewTA); - BB->splitBasicBlock(NewBB); - } -} - -void MCModule::trackBBForAtom(const MCTextAtom *Atom, MCBasicBlock *BB) { - assert(Atom == BB->getInsts() && "Text atom doesn't back the basic block!"); - BBsByAtomTy::iterator I = std::lower_bound(BBsByAtom.begin(), - BBsByAtom.end(), - Atom, CompBBToAtom); - for (; I != BBsByAtom.end() && (*I)->getInsts() == Atom; ++I) - if (*I == BB) - return; - BBsByAtom.insert(I, BB); -} - -MCModule::MCModule() : Entrypoint(0) { } - -MCModule::~MCModule() { - for (AtomListTy::iterator AI = atom_begin(), - AE = atom_end(); - AI != AE; ++AI) - delete *AI; -} diff --git a/lib/MC/MCAnalysis/MCModuleYAML.cpp b/lib/MC/MCAnalysis/MCModuleYAML.cpp deleted file mode 100644 index 876b06d..0000000 --- a/lib/MC/MCAnalysis/MCModuleYAML.cpp +++ /dev/null @@ -1,464 +0,0 @@ -//===- MCModuleYAML.cpp - MCModule YAMLIO implementation ------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines classes for handling the YAML representation of MCModule. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAnalysis/MCModuleYAML.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCFunction.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/YAML.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/YAMLTraits.h" -#include - -namespace llvm { - -namespace { - -// This class is used to map opcode and register names to enum values. -// -// There are at least 3 obvious ways to do this: -// 1- Generate an MII/MRI method using a tablegen StringMatcher -// 2- Write an MII/MRI method using std::lower_bound and the assumption that -// the enums are sorted (starting at a fixed value). -// 3- Do the matching manually as is done here. -// -// Why 3? -// 1- A StringMatcher function for thousands of entries would incur -// a non-negligible binary size overhead. -// 2- The lower_bound comparators would be somewhat involved and aren't -// obviously reusable (see LessRecordRegister in llvm/TableGen/Record.h) -// 3- This isn't actually something useful outside tests (but the same argument -// can be made against having {MII,MRI}::getName). -// -// If this becomes useful outside this specific situation, feel free to do -// the Right Thing (tm) and move the functionality to MII/MRI. -// -class InstrRegInfoHolder { - typedef StringMap EnumValByNameTy; - EnumValByNameTy InstEnumValueByName; - EnumValByNameTy RegEnumValueByName; - -public: - const MCInstrInfo &MII; - const MCRegisterInfo &MRI; - InstrRegInfoHolder(const MCInstrInfo &MII, const MCRegisterInfo &MRI) - : InstEnumValueByName(NextPowerOf2(MII.getNumOpcodes())), - RegEnumValueByName(NextPowerOf2(MRI.getNumRegs())), MII(MII), MRI(MRI) { - for (int i = 0, e = MII.getNumOpcodes(); i != e; ++i) - InstEnumValueByName[MII.getName(i)] = i; - for (int i = 0, e = MRI.getNumRegs(); i != e; ++i) - RegEnumValueByName[MRI.getName(i)] = i; - } - - bool matchRegister(StringRef Name, unsigned &Reg) { - EnumValByNameTy::const_iterator It = RegEnumValueByName.find(Name); - if (It == RegEnumValueByName.end()) - return false; - Reg = It->getValue(); - return true; - } - bool matchOpcode(StringRef Name, unsigned &Opc) { - EnumValByNameTy::const_iterator It = InstEnumValueByName.find(Name); - if (It == InstEnumValueByName.end()) - return false; - Opc = It->getValue(); - return true; - } -}; - -} // end unnamed namespace - -namespace MCModuleYAML { - -LLVM_YAML_STRONG_TYPEDEF(unsigned, OpcodeEnum) - -struct Operand { - MCOperand MCOp; -}; - -struct Inst { - OpcodeEnum Opcode; - std::vector Operands; - uint64_t Size; -}; - -struct Atom { - MCAtom::AtomKind Type; - yaml::Hex64 StartAddress; - uint64_t Size; - - std::vector Insts; - yaml::BinaryRef Data; -}; - -struct BasicBlock { - yaml::Hex64 Address; - std::vector Preds; - std::vector Succs; -}; - -struct Function { - StringRef Name; - std::vector BasicBlocks; -}; - -struct Module { - std::vector Atoms; - std::vector Functions; -}; - -} // end namespace MCModuleYAML -} // end namespace llvm - -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::Hex64) -LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::MCModuleYAML::Operand) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Inst) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Atom) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::BasicBlock) -LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::MCModuleYAML::Function) - -namespace llvm { - -namespace yaml { - -template <> struct ScalarEnumerationTraits { - static void enumeration(IO &IO, MCAtom::AtomKind &Kind); -}; - -template <> struct MappingTraits { - static void mapping(IO &IO, MCModuleYAML::Atom &A); -}; - -template <> struct MappingTraits { - static void mapping(IO &IO, MCModuleYAML::Inst &I); -}; - -template <> struct MappingTraits { - static void mapping(IO &IO, MCModuleYAML::BasicBlock &BB); -}; - -template <> struct MappingTraits { - static void mapping(IO &IO, MCModuleYAML::Function &Fn); -}; - -template <> struct MappingTraits { - static void mapping(IO &IO, MCModuleYAML::Module &M); -}; - -template <> struct ScalarTraits { - static void output(const MCModuleYAML::Operand &, void *, - llvm::raw_ostream &); - static StringRef input(StringRef, void *, MCModuleYAML::Operand &); - static bool mustQuote(StringRef) { return false; } -}; - -template <> struct ScalarTraits { - static void output(const MCModuleYAML::OpcodeEnum &, void *, - llvm::raw_ostream &); - static StringRef input(StringRef, void *, MCModuleYAML::OpcodeEnum &); - static bool mustQuote(StringRef) { return false; } -}; - -void ScalarEnumerationTraits::enumeration( - IO &IO, MCAtom::AtomKind &Value) { - IO.enumCase(Value, "Text", MCAtom::TextAtom); - IO.enumCase(Value, "Data", MCAtom::DataAtom); -} - -void MappingTraits::mapping(IO &IO, MCModuleYAML::Atom &A) { - IO.mapRequired("StartAddress", A.StartAddress); - IO.mapRequired("Size", A.Size); - IO.mapRequired("Type", A.Type); - if (A.Type == MCAtom::TextAtom) - IO.mapRequired("Content", A.Insts); - else if (A.Type == MCAtom::DataAtom) - IO.mapRequired("Content", A.Data); -} - -void MappingTraits::mapping(IO &IO, MCModuleYAML::Inst &I) { - IO.mapRequired("Inst", I.Opcode); - IO.mapRequired("Size", I.Size); - IO.mapRequired("Ops", I.Operands); -} - -void -MappingTraits::mapping(IO &IO, - MCModuleYAML::BasicBlock &BB) { - IO.mapRequired("Address", BB.Address); - IO.mapRequired("Preds", BB.Preds); - IO.mapRequired("Succs", BB.Succs); -} - -void MappingTraits::mapping(IO &IO, - MCModuleYAML::Function &F) { - IO.mapRequired("Name", F.Name); - IO.mapRequired("BasicBlocks", F.BasicBlocks); -} - -void MappingTraits::mapping(IO &IO, - MCModuleYAML::Module &M) { - IO.mapRequired("Atoms", M.Atoms); - IO.mapOptional("Functions", M.Functions); -} - -void -ScalarTraits::output(const MCModuleYAML::Operand &Val, - void *Ctx, raw_ostream &Out) { - InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; - - // FIXME: Doesn't support FPImm and expr/inst, but do these make sense? - if (Val.MCOp.isImm()) - Out << "I" << Val.MCOp.getImm(); - else if (Val.MCOp.isReg()) - Out << "R" << IRI->MRI.getName(Val.MCOp.getReg()); - else - llvm_unreachable("Trying to output invalid MCOperand!"); -} - -StringRef -ScalarTraits::input(StringRef Scalar, void *Ctx, - MCModuleYAML::Operand &Val) { - InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; - char Type = 0; - if (Scalar.size() >= 1) - Type = Scalar.front(); - if (Type != 'R' && Type != 'I') - return "Operand must start with 'R' (register) or 'I' (immediate)."; - if (Type == 'R') { - unsigned Reg; - if (!IRI->matchRegister(Scalar.substr(1), Reg)) - return "Invalid register name."; - Val.MCOp = MCOperand::CreateReg(Reg); - } else if (Type == 'I') { - int64_t RIVal; - if (Scalar.substr(1).getAsInteger(10, RIVal)) - return "Invalid immediate value."; - Val.MCOp = MCOperand::CreateImm(RIVal); - } else { - Val.MCOp = MCOperand(); - } - return StringRef(); -} - -void ScalarTraits::output( - const MCModuleYAML::OpcodeEnum &Val, void *Ctx, raw_ostream &Out) { - InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; - Out << IRI->MII.getName(Val); -} - -StringRef -ScalarTraits::input(StringRef Scalar, void *Ctx, - MCModuleYAML::OpcodeEnum &Val) { - InstrRegInfoHolder *IRI = (InstrRegInfoHolder *)Ctx; - unsigned Opc; - if (!IRI->matchOpcode(Scalar, Opc)) - return "Invalid instruction opcode."; - Val = Opc; - return ""; -} - -} // end namespace yaml - -namespace { - -class MCModule2YAML { - const MCModule &MCM; - MCModuleYAML::Module YAMLModule; - void dumpAtom(const MCAtom *MCA); - void dumpFunction(const MCFunction &MCF); - void dumpBasicBlock(const MCBasicBlock *MCBB); - -public: - MCModule2YAML(const MCModule &MCM); - MCModuleYAML::Module &getYAMLModule(); -}; - -class YAML2MCModule { - MCModule &MCM; - -public: - YAML2MCModule(MCModule &MCM); - StringRef parse(const MCModuleYAML::Module &YAMLModule); -}; - -} // end unnamed namespace - -MCModule2YAML::MCModule2YAML(const MCModule &MCM) : MCM(MCM), YAMLModule() { - for (MCModule::const_atom_iterator AI = MCM.atom_begin(), AE = MCM.atom_end(); - AI != AE; ++AI) - dumpAtom(*AI); - for (MCModule::const_func_iterator FI = MCM.func_begin(), FE = MCM.func_end(); - FI != FE; ++FI) - dumpFunction(**FI); -} - -void MCModule2YAML::dumpAtom(const MCAtom *MCA) { - YAMLModule.Atoms.resize(YAMLModule.Atoms.size() + 1); - MCModuleYAML::Atom &A = YAMLModule.Atoms.back(); - A.Type = MCA->getKind(); - A.StartAddress = MCA->getBeginAddr(); - A.Size = MCA->getEndAddr() - MCA->getBeginAddr() + 1; - if (const MCTextAtom *TA = dyn_cast(MCA)) { - const size_t InstCount = TA->size(); - A.Insts.resize(InstCount); - for (size_t i = 0; i != InstCount; ++i) { - const MCDecodedInst &MCDI = TA->at(i); - A.Insts[i].Opcode = MCDI.Inst.getOpcode(); - A.Insts[i].Size = MCDI.Size; - const unsigned OpCount = MCDI.Inst.getNumOperands(); - A.Insts[i].Operands.resize(OpCount); - for (unsigned oi = 0; oi != OpCount; ++oi) - A.Insts[i].Operands[oi].MCOp = MCDI.Inst.getOperand(oi); - } - } else if (const MCDataAtom *DA = dyn_cast(MCA)) { - A.Data = DA->getData(); - } else { - llvm_unreachable("Unknown atom type."); - } -} - -void MCModule2YAML::dumpFunction(const MCFunction &MCF) { - YAMLModule.Functions.resize(YAMLModule.Functions.size() + 1); - MCModuleYAML::Function &F = YAMLModule.Functions.back(); - F.Name = MCF.getName(); - for (MCFunction::const_iterator BBI = MCF.begin(), BBE = MCF.end(); - BBI != BBE; ++BBI) { - const MCBasicBlock &MCBB = **BBI; - F.BasicBlocks.resize(F.BasicBlocks.size() + 1); - MCModuleYAML::BasicBlock &BB = F.BasicBlocks.back(); - BB.Address = MCBB.getInsts()->getBeginAddr(); - for (MCBasicBlock::pred_const_iterator PI = MCBB.pred_begin(), - PE = MCBB.pred_end(); - PI != PE; ++PI) - BB.Preds.push_back((*PI)->getInsts()->getBeginAddr()); - for (MCBasicBlock::succ_const_iterator SI = MCBB.succ_begin(), - SE = MCBB.succ_end(); - SI != SE; ++SI) - BB.Succs.push_back((*SI)->getInsts()->getBeginAddr()); - } -} - -MCModuleYAML::Module &MCModule2YAML::getYAMLModule() { return YAMLModule; } - -YAML2MCModule::YAML2MCModule(MCModule &MCM) : MCM(MCM) {} - -StringRef YAML2MCModule::parse(const MCModuleYAML::Module &YAMLModule) { - typedef std::vector::const_iterator AtomIt; - typedef std::vector::const_iterator InstIt; - typedef std::vector::const_iterator OpIt; - - typedef DenseMap AddrToTextAtomTy; - AddrToTextAtomTy TAByAddr; - - for (AtomIt AI = YAMLModule.Atoms.begin(), AE = YAMLModule.Atoms.end(); - AI != AE; ++AI) { - uint64_t StartAddress = AI->StartAddress; - if (AI->Size == 0) - return "Atoms can't be empty!"; - uint64_t EndAddress = StartAddress + AI->Size - 1; - switch (AI->Type) { - case MCAtom::TextAtom: { - MCTextAtom *TA = MCM.createTextAtom(StartAddress, EndAddress); - TAByAddr[StartAddress] = TA; - for (InstIt II = AI->Insts.begin(), IE = AI->Insts.end(); II != IE; - ++II) { - MCInst MI; - MI.setOpcode(II->Opcode); - for (OpIt OI = II->Operands.begin(), OE = II->Operands.end(); OI != OE; - ++OI) - MI.addOperand(OI->MCOp); - TA->addInst(MI, II->Size); - } - break; - } - case MCAtom::DataAtom: { - MCDataAtom *DA = MCM.createDataAtom(StartAddress, EndAddress); - SmallVector Data; - raw_svector_ostream OS(Data); - AI->Data.writeAsBinary(OS); - OS.flush(); - for (size_t i = 0, e = Data.size(); i != e; ++i) - DA->addData((uint8_t)Data[i]); - break; - } - } - } - - typedef std::vector::const_iterator FuncIt; - typedef std::vector::const_iterator BBIt; - typedef std::vector::const_iterator AddrIt; - for (FuncIt FI = YAMLModule.Functions.begin(), - FE = YAMLModule.Functions.end(); - FI != FE; ++FI) { - MCFunction *MCFN = MCM.createFunction(FI->Name); - for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end(); - BBI != BBE; ++BBI) { - AddrToTextAtomTy::const_iterator It = TAByAddr.find(BBI->Address); - if (It == TAByAddr.end()) - return "Basic block start address doesn't match any text atom!"; - MCFN->createBlock(*It->second); - } - for (BBIt BBI = FI->BasicBlocks.begin(), BBE = FI->BasicBlocks.end(); - BBI != BBE; ++BBI) { - MCBasicBlock *MCBB = MCFN->find(BBI->Address); - if (!MCBB) - return "Couldn't find matching basic block in function."; - for (AddrIt PI = BBI->Preds.begin(), PE = BBI->Preds.end(); PI != PE; - ++PI) { - MCBasicBlock *Pred = MCFN->find(*PI); - if (!Pred) - return "Couldn't find predecessor basic block."; - MCBB->addPredecessor(Pred); - } - for (AddrIt SI = BBI->Succs.begin(), SE = BBI->Succs.end(); SI != SE; - ++SI) { - MCBasicBlock *Succ = MCFN->find(*SI); - if (!Succ) - return "Couldn't find predecessor basic block."; - MCBB->addSuccessor(Succ); - } - } - } - return ""; -} - -StringRef mcmodule2yaml(raw_ostream &OS, const MCModule &MCM, - const MCInstrInfo &MII, const MCRegisterInfo &MRI) { - MCModule2YAML Dumper(MCM); - InstrRegInfoHolder IRI(MII, MRI); - yaml::Output YOut(OS, (void *)&IRI); - YOut << Dumper.getYAMLModule(); - return ""; -} - -StringRef yaml2mcmodule(std::unique_ptr &MCM, StringRef YamlContent, - const MCInstrInfo &MII, const MCRegisterInfo &MRI) { - MCM.reset(new MCModule); - YAML2MCModule Parser(*MCM); - MCModuleYAML::Module YAMLModule; - InstrRegInfoHolder IRI(MII, MRI); - yaml::Input YIn(YamlContent, (void *)&IRI); - YIn >> YAMLModule; - if (std::error_code ec = YIn.error()) - return ec.message(); - StringRef err = Parser.parse(YAMLModule); - if (!err.empty()) - return err; - return ""; -} - -} // end namespace llvm diff --git a/lib/MC/MCAnalysis/MCObjectDisassembler.cpp b/lib/MC/MCAnalysis/MCObjectDisassembler.cpp deleted file mode 100644 index 0f789ff..0000000 --- a/lib/MC/MCAnalysis/MCObjectDisassembler.cpp +++ /dev/null @@ -1,574 +0,0 @@ -//===- lib/MC/MCObjectDisassembler.cpp ------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCObjectDisassembler.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCFunction.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCInstrAnalysis.h" -#include "llvm/MC/MCObjectSymbolizer.h" -#include "llvm/Object/MachO.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/MachO.h" -#include "llvm/Support/MemoryObject.h" -#include "llvm/Support/StringRefMemoryObject.h" -#include "llvm/Support/raw_ostream.h" -#include - -using namespace llvm; -using namespace object; - -#define DEBUG_TYPE "mc" - -MCObjectDisassembler::MCObjectDisassembler(const ObjectFile &Obj, - const MCDisassembler &Dis, - const MCInstrAnalysis &MIA) - : Obj(Obj), Dis(Dis), MIA(MIA), MOS(nullptr) {} - -uint64_t MCObjectDisassembler::getEntrypoint() { - for (const SymbolRef &Symbol : Obj.symbols()) { - StringRef Name; - Symbol.getName(Name); - if (Name == "main" || Name == "_main") { - uint64_t Entrypoint; - Symbol.getAddress(Entrypoint); - return getEffectiveLoadAddr(Entrypoint); - } - } - return 0; -} - -ArrayRef MCObjectDisassembler::getStaticInitFunctions() { - return ArrayRef(); -} - -ArrayRef MCObjectDisassembler::getStaticExitFunctions() { - return ArrayRef(); -} - -MemoryObject *MCObjectDisassembler::getRegionFor(uint64_t Addr) { - // FIXME: Keep track of object sections. - return FallbackRegion.get(); -} - -uint64_t MCObjectDisassembler::getEffectiveLoadAddr(uint64_t Addr) { - return Addr; -} - -uint64_t MCObjectDisassembler::getOriginalLoadAddr(uint64_t Addr) { - return Addr; -} - -MCModule *MCObjectDisassembler::buildEmptyModule() { - MCModule *Module = new MCModule; - Module->Entrypoint = getEntrypoint(); - return Module; -} - -MCModule *MCObjectDisassembler::buildModule(bool withCFG) { - MCModule *Module = buildEmptyModule(); - - buildSectionAtoms(Module); - if (withCFG) - buildCFG(Module); - return Module; -} - -void MCObjectDisassembler::buildSectionAtoms(MCModule *Module) { - for (const SectionRef &Section : Obj.sections()) { - bool isText; - Section.isText(isText); - bool isData; - Section.isData(isData); - if (!isData && !isText) - continue; - - uint64_t StartAddr; - Section.getAddress(StartAddr); - uint64_t SecSize; - Section.getSize(SecSize); - if (StartAddr == UnknownAddressOrSize || SecSize == UnknownAddressOrSize) - continue; - StartAddr = getEffectiveLoadAddr(StartAddr); - - StringRef Contents; - Section.getContents(Contents); - StringRefMemoryObject memoryObject(Contents, StartAddr); - - // We don't care about things like non-file-backed sections yet. - if (Contents.size() != SecSize || !SecSize) - continue; - uint64_t EndAddr = StartAddr + SecSize - 1; - - StringRef SecName; - Section.getName(SecName); - - if (isText) { - MCTextAtom *Text = nullptr; - MCDataAtom *InvalidData = nullptr; - - uint64_t InstSize; - for (uint64_t Index = 0; Index < SecSize; Index += InstSize) { - const uint64_t CurAddr = StartAddr + Index; - MCInst Inst; - if (Dis.getInstruction(Inst, InstSize, memoryObject, CurAddr, nulls(), - nulls())) { - if (!Text) { - Text = Module->createTextAtom(CurAddr, CurAddr); - Text->setName(SecName); - } - Text->addInst(Inst, InstSize); - InvalidData = nullptr; - } else { - assert(InstSize && "getInstruction() consumed no bytes"); - if (!InvalidData) { - Text = nullptr; - InvalidData = Module->createDataAtom(CurAddr, CurAddr+InstSize - 1); - } - for (uint64_t I = 0; I < InstSize; ++I) - InvalidData->addData(Contents[Index+I]); - } - } - } else { - MCDataAtom *Data = Module->createDataAtom(StartAddr, EndAddr); - Data->setName(SecName); - for (uint64_t Index = 0; Index < SecSize; ++Index) - Data->addData(Contents[Index]); - } - } -} - -namespace { - struct BBInfo; - typedef SmallPtrSet BBInfoSetTy; - - struct BBInfo { - MCTextAtom *Atom; - MCBasicBlock *BB; - BBInfoSetTy Succs; - BBInfoSetTy Preds; - MCObjectDisassembler::AddressSetTy SuccAddrs; - - BBInfo() : Atom(nullptr), BB(nullptr) {} - - void addSucc(BBInfo &Succ) { - Succs.insert(&Succ); - Succ.Preds.insert(this); - } - }; -} - -static void RemoveDupsFromAddressVector(MCObjectDisassembler::AddressSetTy &V) { - std::sort(V.begin(), V.end()); - V.erase(std::unique(V.begin(), V.end()), V.end()); -} - -void MCObjectDisassembler::buildCFG(MCModule *Module) { - typedef std::map BBInfoByAddrTy; - BBInfoByAddrTy BBInfos; - AddressSetTy Splits; - AddressSetTy Calls; - - for (const SymbolRef &Symbol : Obj.symbols()) { - SymbolRef::Type SymType; - Symbol.getType(SymType); - if (SymType == SymbolRef::ST_Function) { - uint64_t SymAddr; - Symbol.getAddress(SymAddr); - SymAddr = getEffectiveLoadAddr(SymAddr); - Calls.push_back(SymAddr); - Splits.push_back(SymAddr); - } - } - - assert(Module->func_begin() == Module->func_end() - && "Module already has a CFG!"); - - // First, determine the basic block boundaries and call targets. - for (MCModule::atom_iterator AI = Module->atom_begin(), - AE = Module->atom_end(); - AI != AE; ++AI) { - MCTextAtom *TA = dyn_cast(*AI); - if (!TA) continue; - Calls.push_back(TA->getBeginAddr()); - BBInfos[TA->getBeginAddr()].Atom = TA; - for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end(); - II != IE; ++II) { - if (MIA.isTerminator(II->Inst)) - Splits.push_back(II->Address + II->Size); - uint64_t Target; - if (MIA.evaluateBranch(II->Inst, II->Address, II->Size, Target)) { - if (MIA.isCall(II->Inst)) - Calls.push_back(Target); - Splits.push_back(Target); - } - } - } - - RemoveDupsFromAddressVector(Splits); - RemoveDupsFromAddressVector(Calls); - - // Split text atoms into basic block atoms. - for (AddressSetTy::const_iterator SI = Splits.begin(), SE = Splits.end(); - SI != SE; ++SI) { - MCAtom *A = Module->findAtomContaining(*SI); - if (!A) continue; - MCTextAtom *TA = cast(A); - if (TA->getBeginAddr() == *SI) - continue; - MCTextAtom *NewAtom = TA->split(*SI); - BBInfos[NewAtom->getBeginAddr()].Atom = NewAtom; - StringRef BBName = TA->getName(); - BBName = BBName.substr(0, BBName.find_last_of(':')); - NewAtom->setName((BBName + ":" + utohexstr(*SI)).str()); - } - - // Compute succs/preds. - for (MCModule::atom_iterator AI = Module->atom_begin(), - AE = Module->atom_end(); - AI != AE; ++AI) { - MCTextAtom *TA = dyn_cast(*AI); - if (!TA) continue; - BBInfo &CurBB = BBInfos[TA->getBeginAddr()]; - const MCDecodedInst &LI = TA->back(); - if (MIA.isBranch(LI.Inst)) { - uint64_t Target; - if (MIA.evaluateBranch(LI.Inst, LI.Address, LI.Size, Target)) - CurBB.addSucc(BBInfos[Target]); - if (MIA.isConditionalBranch(LI.Inst)) - CurBB.addSucc(BBInfos[LI.Address + LI.Size]); - } else if (!MIA.isTerminator(LI.Inst)) - CurBB.addSucc(BBInfos[LI.Address + LI.Size]); - } - - - // Create functions and basic blocks. - for (AddressSetTy::const_iterator CI = Calls.begin(), CE = Calls.end(); - CI != CE; ++CI) { - BBInfo &BBI = BBInfos[*CI]; - if (!BBI.Atom) continue; - - MCFunction &MCFN = *Module->createFunction(BBI.Atom->getName()); - - // Create MCBBs. - SmallSetVector Worklist; - Worklist.insert(&BBI); - for (size_t wi = 0; wi < Worklist.size(); ++wi) { - BBInfo *BBI = Worklist[wi]; - if (!BBI->Atom) - continue; - BBI->BB = &MCFN.createBlock(*BBI->Atom); - // Add all predecessors and successors to the worklist. - for (BBInfoSetTy::iterator SI = BBI->Succs.begin(), SE = BBI->Succs.end(); - SI != SE; ++SI) - Worklist.insert(*SI); - for (BBInfoSetTy::iterator PI = BBI->Preds.begin(), PE = BBI->Preds.end(); - PI != PE; ++PI) - Worklist.insert(*PI); - } - - // Set preds/succs. - for (size_t wi = 0; wi < Worklist.size(); ++wi) { - BBInfo *BBI = Worklist[wi]; - MCBasicBlock *MCBB = BBI->BB; - if (!MCBB) - continue; - for (BBInfoSetTy::iterator SI = BBI->Succs.begin(), SE = BBI->Succs.end(); - SI != SE; ++SI) - if ((*SI)->BB) - MCBB->addSuccessor((*SI)->BB); - for (BBInfoSetTy::iterator PI = BBI->Preds.begin(), PE = BBI->Preds.end(); - PI != PE; ++PI) - if ((*PI)->BB) - MCBB->addPredecessor((*PI)->BB); - } - } -} - -// Basic idea of the disassembly + discovery: -// -// start with the wanted address, insert it in the worklist -// while worklist not empty, take next address in the worklist: -// - check if atom exists there -// - if middle of atom: -// - split basic blocks referencing the atom -// - look for an already encountered BBInfo (using a map) -// - if there is, split it (new one, fallthrough, move succs, etc..) -// - if start of atom: nothing else to do -// - if no atom: create new atom and new bbinfo -// - look at the last instruction in the atom, add succs to worklist -// for all elements in the worklist: -// - create basic block, update preds/succs, etc.. -// -MCBasicBlock *MCObjectDisassembler::getBBAt(MCModule *Module, MCFunction *MCFN, - uint64_t BBBeginAddr, - AddressSetTy &CallTargets, - AddressSetTy &TailCallTargets) { - typedef std::map BBInfoByAddrTy; - typedef SmallSetVector AddrWorklistTy; - BBInfoByAddrTy BBInfos; - AddrWorklistTy Worklist; - - Worklist.insert(BBBeginAddr); - for (size_t wi = 0; wi < Worklist.size(); ++wi) { - const uint64_t BeginAddr = Worklist[wi]; - BBInfo *BBI = &BBInfos[BeginAddr]; - - MCTextAtom *&TA = BBI->Atom; - assert(!TA && "Discovered basic block already has an associated atom!"); - - // Look for an atom at BeginAddr. - if (MCAtom *A = Module->findAtomContaining(BeginAddr)) { - // FIXME: We don't care about mixed atoms, see above. - TA = cast(A); - - // The found atom doesn't begin at BeginAddr, we have to split it. - if (TA->getBeginAddr() != BeginAddr) { - // FIXME: Handle overlapping atoms: middle-starting instructions, etc.. - MCTextAtom *NewTA = TA->split(BeginAddr); - - // Look for an already encountered basic block that needs splitting - BBInfoByAddrTy::iterator It = BBInfos.find(TA->getBeginAddr()); - if (It != BBInfos.end() && It->second.Atom) { - BBI->SuccAddrs = It->second.SuccAddrs; - It->second.SuccAddrs.clear(); - It->second.SuccAddrs.push_back(BeginAddr); - } - TA = NewTA; - } - BBI->Atom = TA; - } else { - // If we didn't find an atom, then we have to disassemble to create one! - - MemoryObject *Region = getRegionFor(BeginAddr); - if (!Region) - llvm_unreachable(("Couldn't find suitable region for disassembly at " + - utostr(BeginAddr)).c_str()); - - uint64_t InstSize; - uint64_t EndAddr = Region->getBase() + Region->getExtent(); - - // We want to stop before the next atom and have a fallthrough to it. - if (MCTextAtom *NextAtom = - cast_or_null(Module->findFirstAtomAfter(BeginAddr))) - EndAddr = std::min(EndAddr, NextAtom->getBeginAddr()); - - for (uint64_t Addr = BeginAddr; Addr < EndAddr; Addr += InstSize) { - MCInst Inst; - if (Dis.getInstruction(Inst, InstSize, *Region, Addr, nulls(), - nulls())) { - if (!TA) - TA = Module->createTextAtom(Addr, Addr); - TA->addInst(Inst, InstSize); - } else { - // We don't care about splitting mixed atoms either. - llvm_unreachable("Couldn't disassemble instruction in atom."); - } - - uint64_t BranchTarget; - if (MIA.evaluateBranch(Inst, Addr, InstSize, BranchTarget)) { - if (MIA.isCall(Inst)) - CallTargets.push_back(BranchTarget); - } - - if (MIA.isTerminator(Inst)) - break; - } - BBI->Atom = TA; - } - - assert(TA && "Couldn't disassemble atom, none was created!"); - assert(TA->begin() != TA->end() && "Empty atom!"); - - MemoryObject *Region = getRegionFor(TA->getBeginAddr()); - assert(Region && "Couldn't find region for already disassembled code!"); - uint64_t EndRegion = Region->getBase() + Region->getExtent(); - - // Now we have a basic block atom, add successors. - // Add the fallthrough block. - if ((MIA.isConditionalBranch(TA->back().Inst) || - !MIA.isTerminator(TA->back().Inst)) && - (TA->getEndAddr() + 1 < EndRegion)) { - BBI->SuccAddrs.push_back(TA->getEndAddr() + 1); - Worklist.insert(TA->getEndAddr() + 1); - } - - // If the terminator is a branch, add the target block. - if (MIA.isBranch(TA->back().Inst)) { - uint64_t BranchTarget; - if (MIA.evaluateBranch(TA->back().Inst, TA->back().Address, - TA->back().Size, BranchTarget)) { - StringRef ExtFnName; - if (MOS) - ExtFnName = - MOS->findExternalFunctionAt(getOriginalLoadAddr(BranchTarget)); - if (!ExtFnName.empty()) { - TailCallTargets.push_back(BranchTarget); - CallTargets.push_back(BranchTarget); - } else { - BBI->SuccAddrs.push_back(BranchTarget); - Worklist.insert(BranchTarget); - } - } - } - } - - for (size_t wi = 0, we = Worklist.size(); wi != we; ++wi) { - const uint64_t BeginAddr = Worklist[wi]; - BBInfo *BBI = &BBInfos[BeginAddr]; - - assert(BBI->Atom && "Found a basic block without an associated atom!"); - - // Look for a basic block at BeginAddr. - BBI->BB = MCFN->find(BeginAddr); - if (BBI->BB) { - // FIXME: check that the succs/preds are the same - continue; - } - // If there was none, we have to create one from the atom. - BBI->BB = &MCFN->createBlock(*BBI->Atom); - } - - for (size_t wi = 0, we = Worklist.size(); wi != we; ++wi) { - const uint64_t BeginAddr = Worklist[wi]; - BBInfo *BBI = &BBInfos[BeginAddr]; - MCBasicBlock *BB = BBI->BB; - - RemoveDupsFromAddressVector(BBI->SuccAddrs); - for (AddressSetTy::const_iterator SI = BBI->SuccAddrs.begin(), - SE = BBI->SuccAddrs.end(); - SE != SE; ++SI) { - MCBasicBlock *Succ = BBInfos[*SI].BB; - BB->addSuccessor(Succ); - Succ->addPredecessor(BB); - } - } - - assert(BBInfos[Worklist[0]].BB && - "No basic block created at requested address?"); - - return BBInfos[Worklist[0]].BB; -} - -MCFunction * -MCObjectDisassembler::createFunction(MCModule *Module, uint64_t BeginAddr, - AddressSetTy &CallTargets, - AddressSetTy &TailCallTargets) { - // First, check if this is an external function. - StringRef ExtFnName; - if (MOS) - ExtFnName = MOS->findExternalFunctionAt(getOriginalLoadAddr(BeginAddr)); - if (!ExtFnName.empty()) - return Module->createFunction(ExtFnName); - - // If it's not, look for an existing function. - for (MCModule::func_iterator FI = Module->func_begin(), - FE = Module->func_end(); - FI != FE; ++FI) { - if ((*FI)->empty()) - continue; - // FIXME: MCModule should provide a findFunctionByAddr() - if ((*FI)->getEntryBlock()->getInsts()->getBeginAddr() == BeginAddr) - return FI->get(); - } - - // Finally, just create a new one. - MCFunction *MCFN = Module->createFunction(""); - getBBAt(Module, MCFN, BeginAddr, CallTargets, TailCallTargets); - return MCFN; -} - -// MachO MCObjectDisassembler implementation. - -MCMachOObjectDisassembler::MCMachOObjectDisassembler( - const MachOObjectFile &MOOF, const MCDisassembler &Dis, - const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, - uint64_t HeaderLoadAddress) - : MCObjectDisassembler(MOOF, Dis, MIA), MOOF(MOOF), - VMAddrSlide(VMAddrSlide), HeaderLoadAddress(HeaderLoadAddress) { - - for (const SectionRef &Section : MOOF.sections()) { - StringRef Name; - Section.getName(Name); - // FIXME: We should use the S_ section type instead of the name. - if (Name == "__mod_init_func") { - DEBUG(dbgs() << "Found __mod_init_func section!\n"); - Section.getContents(ModInitContents); - } else if (Name == "__mod_exit_func") { - DEBUG(dbgs() << "Found __mod_exit_func section!\n"); - Section.getContents(ModExitContents); - } - } -} - -// FIXME: Only do the translations for addresses actually inside the object. -uint64_t MCMachOObjectDisassembler::getEffectiveLoadAddr(uint64_t Addr) { - return Addr + VMAddrSlide; -} - -uint64_t -MCMachOObjectDisassembler::getOriginalLoadAddr(uint64_t EffectiveAddr) { - return EffectiveAddr - VMAddrSlide; -} - -uint64_t MCMachOObjectDisassembler::getEntrypoint() { - uint64_t EntryFileOffset = 0; - - // Look for LC_MAIN. - { - uint32_t LoadCommandCount = MOOF.getHeader().ncmds; - MachOObjectFile::LoadCommandInfo Load = MOOF.getFirstLoadCommandInfo(); - for (unsigned I = 0;; ++I) { - if (Load.C.cmd == MachO::LC_MAIN) { - EntryFileOffset = - ((const MachO::entry_point_command *)Load.Ptr)->entryoff; - break; - } - - if (I == LoadCommandCount - 1) - break; - else - Load = MOOF.getNextLoadCommandInfo(Load); - } - } - - // If we didn't find anything, default to the common implementation. - // FIXME: Maybe we could also look at LC_UNIXTHREAD and friends? - if (EntryFileOffset) - return MCObjectDisassembler::getEntrypoint(); - - return EntryFileOffset + HeaderLoadAddress; -} - -ArrayRef MCMachOObjectDisassembler::getStaticInitFunctions() { - // FIXME: We only handle 64bit mach-o - assert(MOOF.is64Bit()); - - size_t EntrySize = 8; - size_t EntryCount = ModInitContents.size() / EntrySize; - return ArrayRef( - reinterpret_cast(ModInitContents.data()), EntryCount); -} - -ArrayRef MCMachOObjectDisassembler::getStaticExitFunctions() { - // FIXME: We only handle 64bit mach-o - assert(MOOF.is64Bit()); - - size_t EntrySize = 8; - size_t EntryCount = ModExitContents.size() / EntrySize; - return ArrayRef( - reinterpret_cast(ModExitContents.data()), EntryCount); -} diff --git a/lib/MC/MCAnalysis/MCObjectSymbolizer.cpp b/lib/MC/MCAnalysis/MCObjectSymbolizer.cpp deleted file mode 100644 index b149596..0000000 --- a/lib/MC/MCAnalysis/MCObjectSymbolizer.cpp +++ /dev/null @@ -1,268 +0,0 @@ -//===-- lib/MC/MCObjectSymbolizer.cpp -------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCObjectSymbolizer.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/MC/MCRelocationInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Object/ELFObjectFile.h" -#include "llvm/Object/MachO.h" -#include "llvm/Support/raw_ostream.h" -#include - -using namespace llvm; -using namespace object; - -//===- MCMachObjectSymbolizer ---------------------------------------------===// - -namespace { -class MCMachObjectSymbolizer : public MCObjectSymbolizer { - const MachOObjectFile *MOOF; - // __TEXT;__stubs support. - uint64_t StubsStart; - uint64_t StubsCount; - uint64_t StubSize; - uint64_t StubsIndSymIndex; - -public: - MCMachObjectSymbolizer(MCContext &Ctx, - std::unique_ptr RelInfo, - const MachOObjectFile *MOOF); - - StringRef findExternalFunctionAt(uint64_t Addr) override; - - void tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, - uint64_t Address) override; -}; -} // End unnamed namespace - -MCMachObjectSymbolizer::MCMachObjectSymbolizer( - MCContext &Ctx, std::unique_ptr RelInfo, - const MachOObjectFile *MOOF) - : MCObjectSymbolizer(Ctx, std::move(RelInfo), MOOF), MOOF(MOOF), - StubsStart(0), StubsCount(0), StubSize(0), StubsIndSymIndex(0) { - - for (const SectionRef &Section : MOOF->sections()) { - StringRef Name; - Section.getName(Name); - if (Name == "__stubs") { - SectionRef StubsSec = Section; - if (MOOF->is64Bit()) { - MachO::section_64 S = MOOF->getSection64(StubsSec.getRawDataRefImpl()); - StubsIndSymIndex = S.reserved1; - StubSize = S.reserved2; - } else { - MachO::section S = MOOF->getSection(StubsSec.getRawDataRefImpl()); - StubsIndSymIndex = S.reserved1; - StubSize = S.reserved2; - } - assert(StubSize && "Mach-O stub entry size can't be zero!"); - StubsSec.getAddress(StubsStart); - StubsSec.getSize(StubsCount); - StubsCount /= StubSize; - } - } -} - -StringRef MCMachObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) { - // FIXME: also, this can all be done at the very beginning, by iterating over - // all stubs and creating the calls to outside functions. Is it worth it - // though? - if (!StubSize) - return StringRef(); - uint64_t StubIdx = (Addr - StubsStart) / StubSize; - if (StubIdx >= StubsCount) - return StringRef(); - - uint32_t SymtabIdx = - MOOF->getIndirectSymbolTableEntry(MOOF->getDysymtabLoadCommand(), StubIdx); - - StringRef SymName; - symbol_iterator SI = MOOF->symbol_begin(); - for (uint32_t i = 0; i != SymtabIdx; ++i) - ++SI; - SI->getName(SymName); - assert(SI != MOOF->symbol_end() && "Stub wasn't found in the symbol table!"); - assert(SymName.front() == '_' && "Mach-O symbol doesn't start with '_'!"); - return SymName.substr(1); -} - -void MCMachObjectSymbolizer:: -tryAddingPcLoadReferenceComment(raw_ostream &cStream, int64_t Value, - uint64_t Address) { - if (const RelocationRef *R = findRelocationAt(Address)) { - const MCExpr *RelExpr = RelInfo->createExprForRelocation(*R); - if (!RelExpr || RelExpr->EvaluateAsAbsolute(Value) == false) - return; - } - uint64_t Addr = Value; - if (const SectionRef *S = findSectionContaining(Addr)) { - StringRef Name; S->getName(Name); - uint64_t SAddr; S->getAddress(SAddr); - if (Name == "__cstring") { - StringRef Contents; - S->getContents(Contents); - Contents = Contents.substr(Addr - SAddr); - cStream << " ## literal pool for: " - << Contents.substr(0, Contents.find_first_of(0)); - } - } -} - -//===- MCObjectSymbolizer -------------------------------------------------===// - -MCObjectSymbolizer::MCObjectSymbolizer( - MCContext &Ctx, std::unique_ptr RelInfo, - const ObjectFile *Obj) - : MCSymbolizer(Ctx, std::move(RelInfo)), Obj(Obj), SortedSections(), - AddrToReloc() {} - -bool MCObjectSymbolizer:: -tryAddingSymbolicOperand(MCInst &MI, raw_ostream &cStream, - int64_t Value, uint64_t Address, bool IsBranch, - uint64_t Offset, uint64_t InstSize) { - if (IsBranch) { - StringRef ExtFnName = findExternalFunctionAt((uint64_t)Value); - if (!ExtFnName.empty()) { - MCSymbol *Sym = Ctx.GetOrCreateSymbol(ExtFnName); - const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); - MI.addOperand(MCOperand::CreateExpr(Expr)); - return true; - } - } - - if (const RelocationRef *R = findRelocationAt(Address + Offset)) { - if (const MCExpr *RelExpr = RelInfo->createExprForRelocation(*R)) { - MI.addOperand(MCOperand::CreateExpr(RelExpr)); - return true; - } - // Only try to create a symbol+offset expression if there is no relocation. - return false; - } - - // Interpret Value as a branch target. - if (IsBranch == false) - return false; - uint64_t UValue = Value; - // FIXME: map instead of looping each time? - for (const SymbolRef &Symbol : Obj->symbols()) { - uint64_t SymAddr; - Symbol.getAddress(SymAddr); - uint64_t SymSize; - Symbol.getSize(SymSize); - StringRef SymName; - Symbol.getName(SymName); - SymbolRef::Type SymType; - Symbol.getType(SymType); - if (SymAddr == UnknownAddressOrSize || SymSize == UnknownAddressOrSize || - SymName.empty() || SymType != SymbolRef::ST_Function) - continue; - - if ( SymAddr == UValue || - (SymAddr <= UValue && SymAddr + SymSize > UValue)) { - MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName); - const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); - if (SymAddr != UValue) { - const MCExpr *Off = MCConstantExpr::Create(UValue - SymAddr, Ctx); - Expr = MCBinaryExpr::CreateAdd(Expr, Off, Ctx); - } - MI.addOperand(MCOperand::CreateExpr(Expr)); - return true; - } - } - return false; -} - -void MCObjectSymbolizer:: -tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, uint64_t Address) { -} - -StringRef MCObjectSymbolizer::findExternalFunctionAt(uint64_t Addr) { - return StringRef(); -} - -MCObjectSymbolizer *MCObjectSymbolizer::createObjectSymbolizer( - MCContext &Ctx, std::unique_ptr RelInfo, - const ObjectFile *Obj) { - if (const MachOObjectFile *MOOF = dyn_cast(Obj)) - return new MCMachObjectSymbolizer(Ctx, std::move(RelInfo), MOOF); - return new MCObjectSymbolizer(Ctx, std::move(RelInfo), Obj); -} - -// SortedSections implementation. - -static bool SectionStartsBefore(const SectionRef &S, uint64_t Addr) { - uint64_t SAddr; S.getAddress(SAddr); - return SAddr < Addr; -} - -const SectionRef *MCObjectSymbolizer::findSectionContaining(uint64_t Addr) { - if (SortedSections.empty()) - buildSectionList(); - - SortedSectionList::iterator - EndIt = SortedSections.end(), - It = std::lower_bound(SortedSections.begin(), EndIt, - Addr, SectionStartsBefore); - if (It == EndIt) - return nullptr; - uint64_t SAddr; It->getAddress(SAddr); - uint64_t SSize; It->getSize(SSize); - if (Addr >= SAddr + SSize) - return nullptr; - return &*It; -} - -const RelocationRef *MCObjectSymbolizer::findRelocationAt(uint64_t Addr) { - if (AddrToReloc.empty()) - buildRelocationByAddrMap(); - - AddrToRelocMap::const_iterator RI = AddrToReloc.find(Addr); - if (RI == AddrToReloc.end()) - return nullptr; - return &RI->second; -} - -void MCObjectSymbolizer::buildSectionList() { - for (const SectionRef &Section : Obj->sections()) { - bool RequiredForExec; - Section.isRequiredForExecution(RequiredForExec); - if (RequiredForExec == false) - continue; - uint64_t SAddr; - Section.getAddress(SAddr); - uint64_t SSize; - Section.getSize(SSize); - SortedSectionList::iterator It = - std::lower_bound(SortedSections.begin(), SortedSections.end(), SAddr, - SectionStartsBefore); - if (It != SortedSections.end()) { - uint64_t FoundSAddr; It->getAddress(FoundSAddr); - if (FoundSAddr < SAddr + SSize) - llvm_unreachable("Inserting overlapping sections"); - } - SortedSections.insert(It, Section); - } -} - -void MCObjectSymbolizer::buildRelocationByAddrMap() { - for (const SectionRef &Section : Obj->sections()) { - for (const RelocationRef &Reloc : Section.relocations()) { - uint64_t Address; - Reloc.getAddress(Address); - // At a specific address, only keep the first relocation. - if (AddrToReloc.find(Address) == AddrToReloc.end()) - AddrToReloc[Address] = Reloc; - } - } -} diff --git a/lib/MC/MCAnalysis/Makefile b/lib/MC/MCAnalysis/Makefile deleted file mode 100644 index add2dbd..0000000 --- a/lib/MC/MCAnalysis/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- lib/MC/MCAnalysys/Makefile --------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMCAnalysis -BUILD_ARCHIVE := 1 - -include $(LEVEL)/Makefile.common diff --git a/lib/MC/MCAsmInfo.cpp b/lib/MC/MCAsmInfo.cpp index f8081ef..04b8042 100644 --- a/lib/MC/MCAsmInfo.cpp +++ b/lib/MC/MCAsmInfo.cpp @@ -32,7 +32,6 @@ MCAsmInfo::MCAsmInfo() { HasMachoZeroFillDirective = false; HasMachoTBSSDirective = false; HasStaticCtorDtorReferenceInStaticMode = false; - LinkerRequiresNonEmptyDwarfLines = false; MaxInstLength = 4; MinInstAlignment = 1; DollarIsPC = false; @@ -41,6 +40,7 @@ MCAsmInfo::MCAsmInfo() { LabelSuffix = ":"; UseAssignmentForEHBegin = false; PrivateGlobalPrefix = "L"; + PrivateLabelPrefix = PrivateGlobalPrefix; LinkerPrivateGlobalPrefix = ""; InlineAsmStart = "APP"; InlineAsmEnd = "NO_APP"; @@ -64,7 +64,7 @@ MCAsmInfo::MCAsmInfo() { GPRel64Directive = nullptr; GPRel32Directive = nullptr; GlobalDirective = "\t.globl\t"; - HasSetDirective = true; + SetDirectiveSuppressesReloc = false; HasAggressiveSymbolFolding = true; COMMDirectiveAlignmentIsInBytes = true; LCOMMDirectiveAlignmentType = LCOMM::NoAlignment; @@ -72,6 +72,7 @@ MCAsmInfo::MCAsmInfo() { HasSingleParameterDotFile = true; HasIdentDirective = false; HasNoDeadStrip = false; + WeakDirective = "\t.weak\t"; WeakRefDirective = nullptr; HasWeakDefDirective = false; HasWeakDefCanBeHiddenDirective = false; @@ -79,10 +80,9 @@ MCAsmInfo::MCAsmInfo() { HiddenVisibilityAttr = MCSA_Hidden; HiddenDeclarationVisibilityAttr = MCSA_Hidden; ProtectedVisibilityAttr = MCSA_Protected; - HasLEB128 = false; SupportsDebugInformation = false; ExceptionsType = ExceptionHandling::None; - WinEHEncodingType = WinEH::EncodingType::ET_Invalid; + WinEHEncodingType = WinEH::EncodingType::Invalid; DwarfUsesRelocationsAcrossSections = true; DwarfFDESymbolsUseAbsDiff = false; DwarfRegNumForCFI = false; @@ -109,6 +109,10 @@ MCAsmInfo::MCAsmInfo() { MCAsmInfo::~MCAsmInfo() { } +bool MCAsmInfo::isSectionAtomizableBySymbols(const MCSection &Section) const { + return false; +} + const MCExpr * MCAsmInfo::getExprForPersonalitySymbol(const MCSymbol *Sym, unsigned Encoding, diff --git a/lib/MC/MCAsmInfoCOFF.cpp b/lib/MC/MCAsmInfoCOFF.cpp index 9945637..bb3f0d3 100644 --- a/lib/MC/MCAsmInfoCOFF.cpp +++ b/lib/MC/MCAsmInfoCOFF.cpp @@ -32,7 +32,6 @@ MCAsmInfoCOFF::MCAsmInfoCOFF() { ProtectedVisibilityAttr = MCSA_Invalid; // Set up DWARF directives - HasLEB128 = true; // Target asm supports leb128 directives (little-endian) SupportsDebugInformation = true; NeedsDwarfSectionOffsetDirective = true; diff --git a/lib/MC/MCAsmInfoDarwin.cpp b/lib/MC/MCAsmInfoDarwin.cpp index eaf28dd..f705490 100644 --- a/lib/MC/MCAsmInfoDarwin.cpp +++ b/lib/MC/MCAsmInfoDarwin.cpp @@ -15,10 +15,42 @@ #include "llvm/MC/MCAsmInfoDarwin.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MCStreamer.h" using namespace llvm; -void MCAsmInfoDarwin::anchor() { } +bool MCAsmInfoDarwin::isSectionAtomizableBySymbols( + const MCSection &Section) const { + const MCSectionMachO &SMO = static_cast(Section); + + // Sections holding 1 byte strings are atomized based on the data they + // contain. + // Sections holding 2 byte strings require symbols in order to be atomized. + // There is no dedicated section for 4 byte strings. + if (SMO.getType() == MachO::S_CSTRING_LITERALS) + return false; + + if (SMO.getSegmentName() == "__DATA" && SMO.getSectionName() == "__cfstring") + return false; + + switch (SMO.getType()) { + default: + return true; + + // These sections are atomized at the element boundaries without using + // symbols. + case MachO::S_4BYTE_LITERALS: + case MachO::S_8BYTE_LITERALS: + case MachO::S_16BYTE_LITERALS: + case MachO::S_LITERAL_POINTERS: + case MachO::S_NON_LAZY_SYMBOL_POINTERS: + case MachO::S_LAZY_SYMBOL_POINTERS: + case MachO::S_MOD_INIT_FUNC_POINTERS: + case MachO::S_MOD_TERM_FUNC_POINTERS: + case MachO::S_INTERPOSING: + return false; + } +} MCAsmInfoDarwin::MCAsmInfoDarwin() { // Common settings for all Darwin targets. @@ -42,9 +74,6 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { HasMachoTBSSDirective = true; // Uses .tbss HasStaticCtorDtorReferenceInStaticMode = true; - // FIXME: Darwin 10 and newer don't need this. - LinkerRequiresNonEmptyDwarfLines = true; - // FIXME: Change this once MC is the system assembler. HasAggressiveSymbolFolding = false; @@ -60,4 +89,5 @@ MCAsmInfoDarwin::MCAsmInfoDarwin() { DwarfUsesRelocationsAcrossSections = false; UseIntegratedAssembler = true; + SetDirectiveSuppressesReloc = true; } diff --git a/lib/MC/MCAsmInfoELF.cpp b/lib/MC/MCAsmInfoELF.cpp index ccb3dc3..2fe626e 100644 --- a/lib/MC/MCAsmInfoELF.cpp +++ b/lib/MC/MCAsmInfoELF.cpp @@ -13,12 +13,22 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCAsmInfoELF.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCSectionELF.h" +#include "llvm/Support/ELF.h" using namespace llvm; void MCAsmInfoELF::anchor() { } +const MCSection * +MCAsmInfoELF::getNonexecutableStackSection(MCContext &Ctx) const { + return Ctx.getELFSection(".note.GNU-stack", ELF::SHT_PROGBITS, + 0, SectionKind::getMetadata()); +} + MCAsmInfoELF::MCAsmInfoELF() { HasIdentDirective = true; WeakRefDirective = "\t.weak\t"; PrivateGlobalPrefix = ".L"; + PrivateLabelPrefix = ".L"; } diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index 14f0f05..1fe0f63 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/MCStreamer.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmBackend.h" @@ -32,7 +32,6 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include -#include using namespace llvm; namespace { @@ -436,14 +435,18 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol, case MCSA_Internal: OS << "\t.internal\t"; break; case MCSA_LazyReference: OS << "\t.lazy_reference\t"; break; case MCSA_Local: OS << "\t.local\t"; break; - case MCSA_NoDeadStrip: OS << "\t.no_dead_strip\t"; break; + case MCSA_NoDeadStrip: + if (!MAI->hasNoDeadStrip()) + return false; + OS << "\t.no_dead_strip\t"; + break; case MCSA_SymbolResolver: OS << "\t.symbol_resolver\t"; break; case MCSA_PrivateExtern: OS << "\t.private_extern\t"; break; case MCSA_Protected: OS << "\t.protected\t"; break; case MCSA_Reference: OS << "\t.reference\t"; break; - case MCSA_Weak: OS << "\t.weak\t"; break; + case MCSA_Weak: OS << MAI->getWeakDirective(); break; case MCSA_WeakDefinition: OS << "\t.weak_definition\t"; break; @@ -682,7 +685,11 @@ void MCAsmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, // We truncate our partial emission to fit within the bounds of the // emission domain. This produces nicer output and silences potential // truncation warnings when round tripping through another assembler. - ValueToEmit &= ~0ULL >> (64 - EmissionSize * 8); + uint64_t Shift = 64 - EmissionSize * 8; + assert(Shift < static_cast( + std::numeric_limits::digits) && + "undefined behavior"); + ValueToEmit &= ~0ULL >> Shift; EmitIntValue(ValueToEmit, EmissionSize); Emitted += EmissionSize; } @@ -700,7 +707,6 @@ void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value) { EmitULEB128IntValue(IntValue); return; } - assert(MAI->hasLEB128() && "Cannot print a .uleb"); OS << ".uleb128 " << *Value; EmitEOL(); } @@ -711,7 +717,6 @@ void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value) { EmitSLEB128IntValue(IntValue); return; } - assert(MAI->hasLEB128() && "Cannot print a .sleb"); OS << ".sleb128 " << *Value; EmitEOL(); } @@ -867,8 +872,6 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Isa, unsigned Discriminator, StringRef FileName) { - this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, - Isa, Discriminator, FileName); OS << "\t.loc\t" << FileNo << " " << Line << " " << Column; if (Flags & DWARF2_FLAG_BASIC_BLOCK) OS << " basic_block"; @@ -898,6 +901,8 @@ void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, << Line << ':' << Column; } EmitEOL(); + this->MCStreamer::EmitDwarfLocDirective(FileNo, Line, Column, Flags, + Isa, Discriminator, FileName); } MCSymbol *MCAsmStreamer::getDwarfLineTableSymbol(unsigned CUID) { @@ -1089,19 +1094,6 @@ void MCAsmStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, EmitEOL(); } -static const MCSection *getWin64EHTableSection(StringRef suffix, - MCContext &context) { - // FIXME: This doesn't belong in MCObjectFileInfo. However, - /// this duplicate code in MCWin64EH.cpp. - if (suffix == "") - return context.getObjectFileInfo()->getXDataSection(); - return context.getCOFFSection((".xdata"+suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ | - COFF::IMAGE_SCN_MEM_WRITE, - SectionKind::getDataRel()); -} - void MCAsmStreamer::EmitWinEHHandlerData() { MCStreamer::EmitWinEHHandlerData(); @@ -1109,11 +1101,10 @@ void MCAsmStreamer::EmitWinEHHandlerData() { // cause the section switch to be visible in the emitted assembly. // We only do this so the section switch that terminates the handler // data block is visible. - MCWinFrameInfo *CurFrame = getCurrentWinFrameInfo(); - StringRef suffix=MCWin64EHUnwindEmitter::GetSectionSuffix(CurFrame->Function); - const MCSection *xdataSect = getWin64EHTableSection(suffix, getContext()); - if (xdataSect) - SwitchSectionNoChange(xdataSect); + WinEH::FrameInfo *CurFrame = getCurrentWinFrameInfo(); + if (const MCSection *XData = WinEH::UnwindEmitter::getXDataSection( + CurFrame->Function, getContext())) + SwitchSectionNoChange(XData); OS << "\t.seh_handlerdata"; EmitEOL(); diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index a8aad71..45d49fa 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -12,6 +12,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" @@ -20,6 +21,7 @@ #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/Debug.h" @@ -27,7 +29,6 @@ #include "llvm/Support/LEB128.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/MC/MCSectionELF.h" #include using namespace llvm; @@ -141,7 +142,7 @@ static bool getSymbolOffsetImpl(const MCAsmLayout &Layout, // If SD is a variable, evaluate it. MCValue Target; - if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout)) + if (!S.getVariableValue()->EvaluateAsValue(Target, &Layout, nullptr)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); @@ -187,7 +188,7 @@ const MCSymbol *MCAsmLayout::getBaseSymbol(const MCSymbol &Symbol) const { const MCExpr *Expr = Symbol.getVariableValue(); MCValue Value; - if (!Expr->EvaluateAsValue(Value, this)) + if (!Expr->EvaluateAsValue(Value, this, nullptr)) llvm_unreachable("Invalid Expression"); const MCSymbolRefExpr *RefB = Value.getSymB(); @@ -291,7 +292,9 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A) : Section(&_Section), Ordinal(~UINT32_C(0)), Alignment(1), - BundleLockState(NotBundleLocked), BundleGroupBeforeFirstInst(false), + BundleLockState(NotBundleLocked), + BundleLockNestingDepth(0), + BundleGroupBeforeFirstInst(false), HasInstructions(false) { if (A) @@ -328,17 +331,33 @@ MCSectionData::getSubsectionInsertionPoint(unsigned Subsection) { return IP; } +void MCSectionData::setBundleLockState(BundleLockStateType NewState) { + if (NewState == NotBundleLocked) { + if (BundleLockNestingDepth == 0) { + report_fatal_error("Mismatched bundle_lock/unlock directives"); + } + if (--BundleLockNestingDepth == 0) { + BundleLockState = NotBundleLocked; + } + return; + } + + // If any of the directives is an align_to_end directive, the whole nested + // group is align_to_end. So don't downgrade from align_to_end to just locked. + if (BundleLockState != BundleLockedAlignToEnd) { + BundleLockState = NewState; + } + ++BundleLockNestingDepth; +} + /* *** */ MCSymbolData::MCSymbolData() : Symbol(nullptr) {} MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, uint64_t _Offset, MCAssembler *A) - : Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset), - IsExternal(false), IsPrivateExtern(false), - CommonSize(0), SymbolSize(nullptr), CommonAlign(0), - Flags(0), Index(0) -{ + : Symbol(&_Symbol), Fragment(_Fragment), Offset(_Offset), + SymbolSize(nullptr), CommonAlign(-1U), Flags(0), Index(0) { if (A) A->getSymbolList().push_back(this); } @@ -348,9 +367,9 @@ MCSymbolData::MCSymbolData(const MCSymbol &_Symbol, MCFragment *_Fragment, MCAssembler::MCAssembler(MCContext &Context_, MCAsmBackend &Backend_, MCCodeEmitter &Emitter_, MCObjectWriter &Writer_, raw_ostream &OS_) - : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), - OS(OS_), BundleAlignSize(0), RelaxAll(false), NoExecStack(false), - SubsectionsViaSymbols(false), ELFHeaderEFlags(0) { + : Context(Context_), Backend(Backend_), Emitter(Emitter_), Writer(Writer_), + OS(OS_), BundleAlignSize(0), RelaxAll(false), + SubsectionsViaSymbols(false), ELFHeaderEFlags(0) { VersionMinInfo.Major = 0; // Major version == 0 for "none specified" } @@ -364,11 +383,15 @@ void MCAssembler::reset() { SymbolMap.clear(); IndirectSymbols.clear(); DataRegions.clear(); + LinkerOptions.clear(); + FileNames.clear(); ThumbFuncs.clear(); + BundleAlignSize = 0; RelaxAll = false; - NoExecStack = false; SubsectionsViaSymbols = false; ELFHeaderEFlags = 0; + LOHContainer.reset(); + VersionMinInfo.Major = 0; // reset objects owned by us getBackend().reset(); @@ -402,6 +425,16 @@ bool MCAssembler::isThumbFunc(const MCSymbol *Symbol) const { return true; } +void MCAssembler::addLocalUsedInReloc(const MCSymbol &Sym) { + assert(Sym.isTemporary()); + LocalsUsedInReloc.insert(&Sym); +} + +bool MCAssembler::isLocalUsedInReloc(const MCSymbol &Sym) const { + assert(Sym.isTemporary()); + return LocalsUsedInReloc.count(&Sym); +} + bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { // Non-temporary labels should always be visible to the linker. if (!Symbol.isTemporary()) @@ -411,8 +444,10 @@ bool MCAssembler::isSymbolLinkerVisible(const MCSymbol &Symbol) const { if (!Symbol.isInSection()) return false; - // Otherwise, check if the section requires symbols even for temporary labels. - return getBackend().doesSectionRequireSymbols(Symbol.getSection()); + if (isLocalUsedInReloc(Symbol)) + return true; + + return false; } const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { @@ -426,8 +461,8 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { // Non-linker visible symbols in sections which can't be atomized have no // defining atom. - if (!getBackend().isSectionAtomizable( - SD->getFragment()->getParent()->getSection())) + if (!getContext().getAsmInfo()->isSectionAtomizableBySymbols( + SD->getFragment()->getParent()->getSection())) return nullptr; // Otherwise, return the atom for the containing fragment. @@ -438,11 +473,12 @@ const MCSymbolData *MCAssembler::getAtom(const MCSymbolData *SD) const { // a relocatable expr. // FIXME: Should this be the behavior of EvaluateAsRelocatable itself? static bool evaluate(const MCExpr &Expr, const MCAsmLayout &Layout, - MCValue &Target) { - if (Expr.EvaluateAsValue(Target, &Layout)) + const MCFixup &Fixup, MCValue &Target) { + if (Expr.EvaluateAsValue(Target, &Layout, &Fixup)) { if (Target.isAbsolute()) return true; - return Expr.EvaluateAsRelocatable(Target, &Layout); + } + return Expr.EvaluateAsRelocatable(Target, &Layout, &Fixup); } bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, @@ -454,7 +490,7 @@ bool MCAssembler::evaluateFixup(const MCAsmLayout &Layout, // probably merge the two into a single callback that tries to evaluate a // fixup and records a relocation if one is needed. const MCExpr *Expr = Fixup.getValue(); - if (!evaluate(*Expr, Layout, Target)) + if (!evaluate(*Expr, Layout, Fixup, Target)) getContext().FatalError(Fixup.getLoc(), "expected relocatable expression"); bool IsPCRel = Backend.getFixupKindInfo( @@ -993,11 +1029,8 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout, } bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { - int64_t Value = 0; uint64_t OldSize = LF.getContents().size(); - bool IsAbs = LF.getValue().EvaluateAsAbsolute(Value, Layout); - (void)IsAbs; - assert(IsAbs); + int64_t Value = LF.getValue().evaluateKnownAbsolute(Layout); SmallString<8> &Data = LF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); @@ -1012,11 +1045,8 @@ bool MCAssembler::relaxLEB(MCAsmLayout &Layout, MCLEBFragment &LF) { bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, MCDwarfLineAddrFragment &DF) { MCContext &Context = Layout.getAssembler().getContext(); - int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); - bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); - (void)IsAbs; - assert(IsAbs); + int64_t AddrDelta = DF.getAddrDelta().evaluateKnownAbsolute(Layout); int64_t LineDelta; LineDelta = DF.getLineDelta(); SmallString<8> &Data = DF.getContents(); @@ -1030,11 +1060,8 @@ bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, bool MCAssembler::relaxDwarfCallFrameFragment(MCAsmLayout &Layout, MCDwarfCallFrameFragment &DF) { MCContext &Context = Layout.getAssembler().getContext(); - int64_t AddrDelta = 0; uint64_t OldSize = DF.getContents().size(); - bool IsAbs = DF.getAddrDelta().EvaluateAsAbsolute(AddrDelta, Layout); - (void)IsAbs; - assert(IsAbs); + int64_t AddrDelta = DF.getAddrDelta().evaluateKnownAbsolute(Layout); SmallString<8> &Data = DF.getContents(); Data.clear(); raw_svector_ostream OSE(Data); @@ -1247,8 +1274,10 @@ void MCSymbolData::dump() const { raw_ostream &OS = llvm::errs(); OS << " &Entry = Symbols.GetOrCreateValue(Name); - MCSymbol *Sym = Entry.getValue(); + MCSymbol *&Sym = Symbols[Name]; + if (!Sym) + Sym = CreateSymbol(Name); + + return Sym; +} + +MCSymbol *MCContext::getOrCreateSectionSymbol(const MCSectionELF &Section) { + MCSymbol *&Sym = SectionSymbols[&Section]; if (Sym) return Sym; - Sym = CreateSymbol(Name); - Entry.setValue(Sym); + StringRef Name = Section.getSectionName(); + + MCSymbol *&OldSym = Symbols[Name]; + if (OldSym && OldSym->isUndefined()) { + Sym = OldSym; + return OldSym; + } + + auto NameIter = UsedNames.insert(std::make_pair(Name, true)).first; + Sym = new (*this) MCSymbol(NameIter->getKey(), /*isTemporary*/ false); + + if (!OldSym) + OldSym = Sym; + return Sym; } +MCSymbol *MCContext::getOrCreateFrameAllocSymbol(StringRef FuncName) { + return GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + + "frameallocation_" + FuncName); +} + MCSymbol *MCContext::CreateSymbol(StringRef Name) { // Determine whether this is an assembler temporary or normal label, if used. bool isTemporary = false; if (AllowTemporaryLabels) isTemporary = Name.startswith(MAI->getPrivateGlobalPrefix()); - StringMapEntry *NameEntry = &UsedNames.GetOrCreateValue(Name); - if (NameEntry->getValue()) { + auto NameEntry = UsedNames.insert(std::make_pair(Name, true)); + if (!NameEntry.second) { assert(isTemporary && "Cannot rename non-temporary symbols"); SmallString<128> NewName = Name; do { NewName.resize(Name.size()); raw_svector_ostream(NewName) << NextUniqueID++; - NameEntry = &UsedNames.GetOrCreateValue(NewName); - } while (NameEntry->getValue()); + NameEntry = UsedNames.insert(std::make_pair(NewName, true)); + } while (!NameEntry.second); } - NameEntry->setValue(true); // Ok, the entry doesn't already exist. Have the MCSymbol object itself refer // to the copy of the string that is embedded in the UsedNames entry. - MCSymbol *Result = new (*this) MCSymbol(NameEntry->getKey(), isTemporary); + MCSymbol *Result = + new (*this) MCSymbol(NameEntry.first->getKey(), isTemporary); return Result; } @@ -317,6 +342,22 @@ const MCSectionCOFF *MCContext::getCOFFSection(StringRef Section) { return Iter->second; } +const MCSectionCOFF * +MCContext::getAssociativeCOFFSection(const MCSectionCOFF *Sec, + const MCSymbol *KeySym) { + // Return the normal section if we don't have to be associative. + if (!KeySym) + return Sec; + + // Make an associative section with the same name and kind as the normal + // section. + unsigned Characteristics = + Sec->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT; + return getCOFFSection(Sec->getSectionName(), Characteristics, Sec->getKind(), + KeySym->getName(), + COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE); +} + //===----------------------------------------------------------------------===// // Dwarf Management //===----------------------------------------------------------------------===// diff --git a/lib/MC/MCDisassembler.cpp b/lib/MC/MCDisassembler.cpp deleted file mode 100644 index 77d9ce1..0000000 --- a/lib/MC/MCDisassembler.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===-- lib/MC/MCDisassembler.cpp - Disassembler interface ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCExternalSymbolizer.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -MCDisassembler::~MCDisassembler() { -} - -bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, - uint64_t Address, bool IsBranch, - uint64_t Offset, - uint64_t InstSize) const { - raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); - if (Symbolizer) - return Symbolizer->tryAddingSymbolicOperand(Inst, cStream, Value, Address, - IsBranch, Offset, InstSize); - return false; -} - -void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value, - uint64_t Address) const { - raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); - if (Symbolizer) - Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address); -} - -void MCDisassembler::setSymbolizer(std::unique_ptr Symzer) { - Symbolizer = std::move(Symzer); -} diff --git a/lib/MC/MCDisassembler/CMakeLists.txt b/lib/MC/MCDisassembler/CMakeLists.txt index 5195b9e..f266f8f 100644 --- a/lib/MC/MCDisassembler/CMakeLists.txt +++ b/lib/MC/MCDisassembler/CMakeLists.txt @@ -1,3 +1,6 @@ add_llvm_library(LLVMMCDisassembler Disassembler.cpp + MCRelocationInfo.cpp + MCExternalSymbolizer.cpp + MCDisassembler.cpp ) diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp index 0530c26..d27d83b 100644 --- a/lib/MC/MCDisassembler/Disassembler.cpp +++ b/lib/MC/MCDisassembler/Disassembler.cpp @@ -21,7 +21,6 @@ #include "llvm/MC/MCSymbolizer.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Support/MemoryObject.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -33,10 +32,11 @@ using namespace llvm; // functions can all be passed as NULL. If successful, this returns a // disassembler context. If not, it returns NULL. // -LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, - void *DisInfo, int TagType, - LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp){ +LLVMDisasmContextRef +LLVMCreateDisasmCPUFeatures(const char *Triple, const char *CPU, + const char *Features, void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp) { // Get the target. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(Triple, Error); @@ -56,11 +56,8 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, if (!MII) return nullptr; - // Package up features to be passed to target/subtarget - std::string FeaturesStr; - const MCSubtargetInfo *STI = TheTarget->createMCSubtargetInfo(Triple, CPU, - FeaturesStr); + Features); if (!STI) return nullptr; @@ -101,11 +98,19 @@ LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, return DC; } +LLVMDisasmContextRef LLVMCreateDisasmCPU(const char *Triple, const char *CPU, + void *DisInfo, int TagType, + LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp){ + return LLVMCreateDisasmCPUFeatures(Triple, CPU, "", DisInfo, TagType, + GetOpInfo, SymbolLookUp); +} + LLVMDisasmContextRef LLVMCreateDisasm(const char *Triple, void *DisInfo, int TagType, LLVMOpInfoCallback GetOpInfo, LLVMSymbolLookupCallback SymbolLookUp) { - return LLVMCreateDisasmCPU(Triple, "", DisInfo, TagType, GetOpInfo, - SymbolLookUp); + return LLVMCreateDisasmCPUFeatures(Triple, "", "", DisInfo, TagType, + GetOpInfo, SymbolLookUp); } // @@ -116,30 +121,6 @@ void LLVMDisasmDispose(LLVMDisasmContextRef DCR){ delete DC; } -namespace { -// -// The memory object created by LLVMDisasmInstruction(). -// -class DisasmMemoryObject : public MemoryObject { - uint8_t *Bytes; - uint64_t Size; - uint64_t BasePC; -public: - DisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) : - Bytes(bytes), Size(size), BasePC(basePC) {} - - uint64_t getBase() const override { return BasePC; } - uint64_t getExtent() const override { return Size; } - - int readByte(uint64_t Addr, uint8_t *Byte) const override { - if (Addr - BasePC >= Size) - return -1; - *Byte = Bytes[Addr - BasePC]; - return 0; - } -}; -} // end anonymous namespace - /// \brief Emits the comments that are stored in \p DC comment stream. /// Each comment in the comment stream must end with a newline. static void emitComments(LLVMDisasmContext *DC, @@ -170,10 +151,10 @@ static void emitComments(LLVMDisasmContext *DC, DC->CommentStream.resync(); } -/// \brief Gets latency information for \p Inst form the itinerary +/// \brief Gets latency information for \p Inst from the itinerary /// scheduling model, based on \p DC information. /// \return The maximum expected latency over all the operands or -1 -/// if no information are available. +/// if no information is available. static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) { const int NoInformationAvailable = -1; @@ -198,23 +179,23 @@ static int getItineraryLatency(LLVMDisasmContext *DC, const MCInst &Inst) { /// \brief Gets latency information for \p Inst, based on \p DC information. /// \return The maximum expected latency over all the definitions or -1 -/// if no information are available. +/// if no information is available. static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) { // Try to compute scheduling information. const MCSubtargetInfo *STI = DC->getSubtargetInfo(); - const MCSchedModel *SCModel = STI->getSchedModel(); + const MCSchedModel SCModel = STI->getSchedModel(); const int NoInformationAvailable = -1; // Check if we have a scheduling model for instructions. - if (!SCModel || !SCModel->hasInstrSchedModel()) - // Try to fall back to the itinerary model if we do not have a - // scheduling model. + if (!SCModel.hasInstrSchedModel()) + // Try to fall back to the itinerary model if the scheduling model doesn't + // have a scheduling table. Note the default does not have a table. return getItineraryLatency(DC, Inst); // Get the scheduling class of the requested instruction. const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); unsigned SCClass = Desc.getSchedClass(); - const MCSchedClassDesc *SCDesc = SCModel->getSchedClassDesc(SCClass); + const MCSchedClassDesc *SCDesc = SCModel.getSchedClassDesc(SCClass); // Resolving the variant SchedClass requires an MI to pass to // SubTargetInfo::resolveSchedClass. if (!SCDesc || !SCDesc->isValid() || SCDesc->isVariant()) @@ -239,7 +220,7 @@ static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) { static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) { int Latency = getLatency(DC, Inst); - // Report only interesting latency. + // Report only interesting latencies. if (Latency < 2) return; @@ -263,7 +244,7 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, size_t OutStringSize){ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; // Wrap the pointer to the Bytes, BytesSize and PC in a MemoryObject. - DisasmMemoryObject MemoryObject(Bytes, BytesSize, PC); + ArrayRef Data(Bytes, BytesSize); uint64_t Size; MCInst Inst; @@ -272,7 +253,7 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, MCDisassembler::DecodeStatus S; SmallVector InsnStr; raw_svector_ostream Annotations(InsnStr); - S = DisAsm->getInstruction(Inst, Size, MemoryObject, PC, + S = DisAsm->getInstruction(Inst, Size, Data, PC, /*REMOVE*/ nulls(), Annotations); switch (S) { case MCDisassembler::Fail: diff --git a/lib/MC/MCDisassembler/Disassembler.h b/lib/MC/MCDisassembler/Disassembler.h index d1d40cd..46d0c4c 100644 --- a/lib/MC/MCDisassembler/Disassembler.h +++ b/lib/MC/MCDisassembler/Disassembler.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_MC_DISASSEMBLER_H -#define LLVM_MC_DISASSEMBLER_H +#ifndef LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H +#define LLVM_LIB_MC_MCDISASSEMBLER_DISASSEMBLER_H #include "llvm-c/Disassembler.h" #include "llvm/ADT/SmallString.h" diff --git a/lib/MC/MCDisassembler/MCDisassembler.cpp b/lib/MC/MCDisassembler/MCDisassembler.cpp new file mode 100644 index 0000000..1084e5e --- /dev/null +++ b/lib/MC/MCDisassembler/MCDisassembler.cpp @@ -0,0 +1,39 @@ +//===-- MCDisassembler.cpp - Disassembler interface -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +MCDisassembler::~MCDisassembler() { +} + +bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value, + uint64_t Address, bool IsBranch, + uint64_t Offset, + uint64_t InstSize) const { + raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); + if (Symbolizer) + return Symbolizer->tryAddingSymbolicOperand(Inst, cStream, Value, Address, + IsBranch, Offset, InstSize); + return false; +} + +void MCDisassembler::tryAddingPcLoadReferenceComment(int64_t Value, + uint64_t Address) const { + raw_ostream &cStream = CommentStream ? *CommentStream : nulls(); + if (Symbolizer) + Symbolizer->tryAddingPcLoadReferenceComment(cStream, Value, Address); +} + +void MCDisassembler::setSymbolizer(std::unique_ptr Symzer) { + Symbolizer = std::move(Symzer); +} diff --git a/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp b/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp new file mode 100644 index 0000000..0145623 --- /dev/null +++ b/lib/MC/MCDisassembler/MCExternalSymbolizer.cpp @@ -0,0 +1,198 @@ +//===-- MCExternalSymbolizer.cpp - External symbolizer --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCExternalSymbolizer.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/raw_ostream.h" +#include + +using namespace llvm; + +// This function tries to add a symbolic operand in place of the immediate +// Value in the MCInst. The immediate Value has had any PC adjustment made by +// the caller. If the instruction is a branch instruction then IsBranch is true, +// else false. If the getOpInfo() function was set as part of the +// setupForSymbolicDisassembly() call then that function is called to get any +// symbolic information at the Address for this instruction. If that returns +// non-zero then the symbolic information it returns is used to create an MCExpr +// and that is added as an operand to the MCInst. If getOpInfo() returns zero +// and IsBranch is true then a symbol look up for Value is done and if a symbol +// is found an MCExpr is created with that, else an MCExpr with Value is +// created. This function returns true if it adds an operand to the MCInst and +// false otherwise. +bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, + raw_ostream &cStream, + int64_t Value, + uint64_t Address, + bool IsBranch, + uint64_t Offset, + uint64_t InstSize) { + struct LLVMOpInfo1 SymbolicOp; + std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); + SymbolicOp.Value = Value; + + if (!GetOpInfo || + !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) { + // Clear SymbolicOp.Value from above and also all other fields. + std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); + + // At this point, GetOpInfo() did not find any relocation information about + // this operand and we are left to use the SymbolLookUp() call back to guess + // if the Value is the address of a symbol. In the case this is a branch + // that always makes sense to guess. But in the case of an immediate it is + // a bit more questionable if it is an address of a symbol or some other + // reference. So if the immediate Value comes from a width of 1 byte, + // InstSize, we will not guess it is an address of a symbol. Because in + // object files assembled starting at address 0 this usually leads to + // incorrect symbolication. + if (!SymbolLookUp || (InstSize == 1 && !IsBranch)) + return false; + + uint64_t ReferenceType; + if (IsBranch) + ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; + else + ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; + const char *ReferenceName; + const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address, + &ReferenceName); + if (Name) { + SymbolicOp.AddSymbol.Name = Name; + SymbolicOp.AddSymbol.Present = true; + // If Name is a C++ symbol name put the human readable name in a comment. + if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name) + cStream << ReferenceName; + } + // For branches always create an MCExpr so it gets printed as hex address. + else if (IsBranch) { + SymbolicOp.Value = Value; + } + if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) + cStream << "symbol stub for: " << ReferenceName; + else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message) + cStream << "Objc message: " << ReferenceName; + if (!Name && !IsBranch) + return false; + } + + const MCExpr *Add = nullptr; + if (SymbolicOp.AddSymbol.Present) { + if (SymbolicOp.AddSymbol.Name) { + StringRef Name(SymbolicOp.AddSymbol.Name); + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); + Add = MCSymbolRefExpr::Create(Sym, Ctx); + } else { + Add = MCConstantExpr::Create((int)SymbolicOp.AddSymbol.Value, Ctx); + } + } + + const MCExpr *Sub = nullptr; + if (SymbolicOp.SubtractSymbol.Present) { + if (SymbolicOp.SubtractSymbol.Name) { + StringRef Name(SymbolicOp.SubtractSymbol.Name); + MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); + Sub = MCSymbolRefExpr::Create(Sym, Ctx); + } else { + Sub = MCConstantExpr::Create((int)SymbolicOp.SubtractSymbol.Value, Ctx); + } + } + + const MCExpr *Off = nullptr; + if (SymbolicOp.Value != 0) + Off = MCConstantExpr::Create(SymbolicOp.Value, Ctx); + + const MCExpr *Expr; + if (Sub) { + const MCExpr *LHS; + if (Add) + LHS = MCBinaryExpr::CreateSub(Add, Sub, Ctx); + else + LHS = MCUnaryExpr::CreateMinus(Sub, Ctx); + if (Off) + Expr = MCBinaryExpr::CreateAdd(LHS, Off, Ctx); + else + Expr = LHS; + } else if (Add) { + if (Off) + Expr = MCBinaryExpr::CreateAdd(Add, Off, Ctx); + else + Expr = Add; + } else { + if (Off) + Expr = Off; + else + Expr = MCConstantExpr::Create(0, Ctx); + } + + Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind); + if (!Expr) + return false; + + MI.addOperand(MCOperand::CreateExpr(Expr)); + return true; +} + +// This function tries to add a comment as to what is being referenced by a load +// instruction with the base register that is the Pc. These can often be values +// in a literal pool near the Address of the instruction. The Address of the +// instruction and its immediate Value are used as a possible literal pool entry. +// The SymbolLookUp call back will return the name of a symbol referenced by the +// literal pool's entry if the referenced address is that of a symbol. Or it +// will return a pointer to a literal 'C' string if the referenced address of +// the literal pool's entry is an address into a section with C string literals. +// Or if the reference is to an Objective-C data structure it will return a +// specific reference type for it and a string. +void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, + int64_t Value, + uint64_t Address) { + if (SymbolLookUp) { + uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load; + const char *ReferenceName; + (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName); + if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr) + cStream << "literal pool symbol address: " << ReferenceName; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) { + cStream << "literal pool for: \""; + cStream.write_escaped(ReferenceName); + cStream << "\""; + } + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref) + cStream << "Objc cfstring ref: @\"" << ReferenceName << "\""; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Message) + cStream << "Objc message: " << ReferenceName; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref) + cStream << "Objc message ref: " << ReferenceName; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref) + cStream << "Objc selector ref: " << ReferenceName; + else if(ReferenceType == + LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref) + cStream << "Objc class ref: " << ReferenceName; + } +} + +namespace llvm { +MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, + MCContext *Ctx, + MCRelocationInfo *RelInfo) { + assert(Ctx && "No MCContext given for symbolic disassembly"); + + return new MCExternalSymbolizer(*Ctx, + std::unique_ptr(RelInfo), + GetOpInfo, SymbolLookUp, DisInfo); +} +} diff --git a/lib/MC/MCDisassembler/MCRelocationInfo.cpp b/lib/MC/MCDisassembler/MCRelocationInfo.cpp new file mode 100644 index 0000000..ff0c27f --- /dev/null +++ b/lib/MC/MCDisassembler/MCRelocationInfo.cpp @@ -0,0 +1,39 @@ +//==-- MCRelocationInfo.cpp ------------------------------------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/MC/MCRelocationInfo.h" +#include "llvm-c/Disassembler.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +MCRelocationInfo::MCRelocationInfo(MCContext &Ctx) + : Ctx(Ctx) { +} + +MCRelocationInfo::~MCRelocationInfo() { +} + +const MCExpr * +MCRelocationInfo::createExprForRelocation(object::RelocationRef Rel) { + return nullptr; +} + +const MCExpr * +MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr, + unsigned VariantKind) { + if (VariantKind != LLVMDisassembler_VariantKind_None) + return nullptr; + return SubExpr; +} + +MCRelocationInfo *llvm::createMCRelocationInfo(StringRef TT, MCContext &Ctx) { + return new MCRelocationInfo(Ctx); +} diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 968cbc9..5effb01 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -247,6 +247,22 @@ std::pair MCDwarfLineTableHeader::Emit(MCStreamer *MCOS) return Emit(MCOS, StandardOpcodeLengths); } +static const MCExpr *forceExpAbs(MCStreamer &OS, const MCExpr* Expr) { + MCContext &Context = OS.getContext(); + assert(!isa(Expr)); + if (Context.getAsmInfo()->hasAggressiveSymbolFolding()) + return Expr; + + MCSymbol *ABS = Context.CreateTempSymbol(); + OS.EmitAssignment(ABS, Expr); + return MCSymbolRefExpr::Create(ABS, Context); +} + +static void emitAbsValue(MCStreamer &OS, const MCExpr *Value, unsigned Size) { + const MCExpr *ABS = forceExpAbs(OS, Value); + OS.EmitValue(ABS, Size); +} + std::pair MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, ArrayRef StandardOpcodeLengths) const { @@ -265,8 +281,8 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, // The first 4 bytes is the total length of the information for this // compilation unit (not including these 4 bytes for the length). - MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym,4), - 4); + emitAbsValue(*MCOS, + MakeStartMinusEndExpr(*MCOS, *LineStartSym, *LineEndSym, 4), 4); // Next 2 bytes is the Version, which is Dwarf 2. MCOS->EmitIntValue(2, 2); @@ -278,8 +294,9 @@ MCDwarfLineTableHeader::Emit(MCStreamer *MCOS, // section to the end of the prologue. Not including the 4 bytes for the // total length, the 2 bytes for the version, and these 4 bytes for the // length of the prologue. - MCOS->EmitAbsValue(MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, - (4 + 2 + 4)), 4); + emitAbsValue( + *MCOS, + MakeStartMinusEndExpr(*MCOS, *LineStartSym, *ProEndSym, (4 + 2 + 4)), 4); // Parameters of the state machine, are next. MCOS->EmitIntValue(context.getAsmInfo()->getMinInstAlignment(), 1); @@ -327,18 +344,6 @@ void MCDwarfLineTable::EmitCU(MCObjectStreamer *MCOS) const { for (const auto &LineSec : MCLineSections.getMCLineEntries()) EmitDwarfLineTable(MCOS, LineSec.first, LineSec.second); - if (MCOS->getContext().getAsmInfo()->getLinkerRequiresNonEmptyDwarfLines() && - MCLineSections.getMCLineEntries().empty()) { - // The darwin9 linker has a bug (see PR8715). For for 32-bit architectures - // it requires: - // total_length >= prologue_length + 10 - // We are 4 bytes short, since we have total_length = 51 and - // prologue_length = 45 - - // The regular end_sequence should be sufficient. - MCDwarfLineAddr::Emit(MCOS, INT64_MAX, 0); - } - // This is the end of the section, so set the value of the symbol at the end // of this section (that was used in a previous expression). MCOS->EmitLabel(LineEndSym); @@ -363,10 +368,10 @@ unsigned MCDwarfLineTableHeader::getFile(StringRef &Directory, FileNumber = SourceIdMap.size() + 1; assert((MCDwarfFiles.empty() || FileNumber == MCDwarfFiles.size()) && "Don't mix autonumbered and explicit numbered line table usage"); - StringMapEntry &Ent = SourceIdMap.GetOrCreateValue( - (Directory + Twine('\0') + FileName).str(), FileNumber); - if (Ent.getValue() != FileNumber) - return Ent.getValue(); + auto IterBool = SourceIdMap.insert( + std::make_pair((Directory + Twine('\0') + FileName).str(), FileNumber)); + if (!IterBool.second) + return IterBool.first->second; } // Make space for this FileNumber in the MCDwarfFiles vector if needed. MCDwarfFiles.resize(FileNumber + 1); @@ -519,7 +524,8 @@ static void EmitGenDwarfAbbrev(MCStreamer *MCOS) { MCOS->EmitULEB128IntValue(dwarf::DW_TAG_compile_unit); MCOS->EmitIntValue(dwarf::DW_CHILDREN_yes, 1); EmitAbbrev(MCOS, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4); - if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1) { + if (MCOS->getContext().getGenDwarfSectionSyms().size() > 1 && + MCOS->getContext().getDwarfVersion() >= 3) { EmitAbbrev(MCOS, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4); } else { EmitAbbrev(MCOS, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr); @@ -596,7 +602,8 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, // The 4 byte offset to the compile unit in the .debug_info from the start // of the .debug_info. if (InfoSectionSymbol) - MCOS->EmitSymbolValue(InfoSectionSymbol, 4); + MCOS->EmitSymbolValue(InfoSectionSymbol, 4, + asmInfo->needsDwarfSectionOffsetDirective()); else MCOS->EmitIntValue(0, 4); // The 1 byte size of an address. @@ -620,7 +627,7 @@ static void EmitGenDwarfAranges(MCStreamer *MCOS, const MCExpr *Size = MakeStartMinusEndExpr(*MCOS, *StartSymbol, *EndSymbol, 0); MCOS->EmitValue(Addr, AddrSize); - MCOS->EmitAbsValue(Size, AddrSize); + emitAbsValue(*MCOS, Size, AddrSize); } // And finally the pair of terminating zeros. @@ -650,7 +657,7 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, // The 4 byte total length of the information for this compilation unit, not // including these 4 bytes. const MCExpr *Length = MakeStartMinusEndExpr(*MCOS, *InfoStart, *InfoEnd, 4); - MCOS->EmitAbsValue(Length, 4); + emitAbsValue(*MCOS, Length, 4); // The 2 byte DWARF version. MCOS->EmitIntValue(context.getDwarfVersion(), 2); @@ -676,11 +683,11 @@ static void EmitGenDwarfInfo(MCStreamer *MCOS, // DW_AT_stmt_list, a 4 byte offset from the start of the .debug_line section, // which is at the start of that section so this is zero. - if (LineSectionSymbol) { - MCOS->EmitSymbolValue(LineSectionSymbol, 4); - } else { + if (LineSectionSymbol) + MCOS->EmitSymbolValue(LineSectionSymbol, 4, + AsmInfo.needsDwarfSectionOffsetDirective()); + else MCOS->EmitIntValue(0, 4); - } if (RangesSectionSymbol) { // There are multiple sections containing code, so we must use the @@ -821,7 +828,7 @@ static void EmitGenDwarfRanges(MCStreamer *MCOS) { const MCExpr *SectionSize = MakeStartMinusEndExpr(*MCOS, *StartSymbol, *EndSymbol, 0); MCOS->EmitIntValue(0, AddrSize); - MCOS->EmitAbsValue(SectionSize, AddrSize); + emitAbsValue(*MCOS, SectionSize, AddrSize); } // Emit end of list entry @@ -855,10 +862,11 @@ void MCGenDwarfInfo::Emit(MCStreamer *MCOS) { if (MCOS->getContext().getGenDwarfSectionSyms().empty()) return; - // We only need to use the .debug_ranges section if we have multiple - // code sections. + // We only use the .debug_ranges section if we have multiple code sections, + // and we are emitting a DWARF version which supports it. const bool UseRangesSection = - MCOS->getContext().getGenDwarfSectionSyms().size() > 1; + MCOS->getContext().getGenDwarfSectionSyms().size() > 1 && + MCOS->getContext().getDwarfVersion() >= 3; CreateDwarfSectionSymbols |= UseRangesSection; MCOS->SwitchSection(context.getObjectFileInfo()->getDwarfInfoSection()); @@ -971,18 +979,16 @@ static unsigned getSizeForEncoding(MCStreamer &streamer, } } -static void EmitFDESymbol(MCStreamer &streamer, const MCSymbol &symbol, - unsigned symbolEncoding, bool isEH, - const char *comment = nullptr) { +static void emitFDESymbol(MCObjectStreamer &streamer, const MCSymbol &symbol, + unsigned symbolEncoding, bool isEH) { MCContext &context = streamer.getContext(); const MCAsmInfo *asmInfo = context.getAsmInfo(); const MCExpr *v = asmInfo->getExprForFDESymbol(&symbol, symbolEncoding, streamer); unsigned size = getSizeForEncoding(streamer, symbolEncoding); - if (streamer.isVerboseAsm() && comment) streamer.AddComment(comment); if (asmInfo->doDwarfFDESymbolsUseAbsDiff() && isEH) - streamer.EmitAbsValue(v, size); + emitAbsValue(streamer, v, size); else streamer.EmitValue(v, size); } @@ -1001,17 +1007,16 @@ static void EmitPersonality(MCStreamer &streamer, const MCSymbol &symbol, namespace { class FrameEmitterImpl { int CFAOffset; - int CIENum; bool IsEH; const MCSymbol *SectionStart; public: FrameEmitterImpl(bool isEH) - : CFAOffset(0), CIENum(0), IsEH(isEH), SectionStart(nullptr) {} + : CFAOffset(0), IsEH(isEH), SectionStart(nullptr) {} void setSectionStart(const MCSymbol *Label) { SectionStart = Label; } - /// EmitCompactUnwind - Emit the unwind information in a compact way. - void EmitCompactUnwind(MCStreamer &streamer, + /// Emit the unwind information in a compact way. + void EmitCompactUnwind(MCObjectStreamer &streamer, const MCDwarfFrameInfo &frame); const MCSymbol &EmitCIE(MCObjectStreamer &streamer, @@ -1033,65 +1038,18 @@ namespace { } // end anonymous namespace -static void EmitEncodingByte(MCStreamer &Streamer, unsigned Encoding, - StringRef Prefix) { - if (Streamer.isVerboseAsm()) { - const char *EncStr; - switch (Encoding) { - default: EncStr = ""; break; - case dwarf::DW_EH_PE_absptr: EncStr = "absptr"; break; - case dwarf::DW_EH_PE_omit: EncStr = "omit"; break; - case dwarf::DW_EH_PE_pcrel: EncStr = "pcrel"; break; - case dwarf::DW_EH_PE_udata4: EncStr = "udata4"; break; - case dwarf::DW_EH_PE_udata8: EncStr = "udata8"; break; - case dwarf::DW_EH_PE_sdata4: EncStr = "sdata4"; break; - case dwarf::DW_EH_PE_sdata8: EncStr = "sdata8"; break; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: - EncStr = "pcrel udata4"; - break; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: - EncStr = "pcrel sdata4"; - break; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: - EncStr = "pcrel udata8"; - break; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: - EncStr = "screl sdata8"; - break; - case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata4: - EncStr = "indirect pcrel udata4"; - break; - case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata4: - EncStr = "indirect pcrel sdata4"; - break; - case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_udata8: - EncStr = "indirect pcrel udata8"; - break; - case dwarf::DW_EH_PE_indirect |dwarf::DW_EH_PE_pcrel|dwarf::DW_EH_PE_sdata8: - EncStr = "indirect pcrel sdata8"; - break; - } - - Streamer.AddComment(Twine(Prefix) + " = " + EncStr); - } - +static void emitEncodingByte(MCObjectStreamer &Streamer, unsigned Encoding) { Streamer.EmitIntValue(Encoding, 1); } void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, const MCCFIInstruction &Instr) { int dataAlignmentFactor = getDataAlignmentFactor(Streamer); - bool VerboseAsm = Streamer.isVerboseAsm(); switch (Instr.getOperation()) { case MCCFIInstruction::OpRegister: { unsigned Reg1 = Instr.getRegister(); unsigned Reg2 = Instr.getRegister2(); - if (VerboseAsm) { - Streamer.AddComment("DW_CFA_register"); - Streamer.AddComment(Twine("Reg1 ") + Twine(Reg1)); - Streamer.AddComment(Twine("Reg2 ") + Twine(Reg2)); - } Streamer.EmitIntValue(dwarf::DW_CFA_register, 1); Streamer.EmitULEB128IntValue(Reg1); Streamer.EmitULEB128IntValue(Reg2); @@ -1103,10 +1061,6 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, } case MCCFIInstruction::OpUndefined: { unsigned Reg = Instr.getRegister(); - if (VerboseAsm) { - Streamer.AddComment("DW_CFA_undefined"); - Streamer.AddComment(Twine("Reg ") + Twine(Reg)); - } Streamer.EmitIntValue(dwarf::DW_CFA_undefined, 1); Streamer.EmitULEB128IntValue(Reg); return; @@ -1116,8 +1070,6 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, const bool IsRelative = Instr.getOperation() == MCCFIInstruction::OpAdjustCfaOffset; - if (VerboseAsm) - Streamer.AddComment("DW_CFA_def_cfa_offset"); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_offset, 1); if (IsRelative) @@ -1125,37 +1077,21 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, else CFAOffset = -Instr.getOffset(); - if (VerboseAsm) - Streamer.AddComment(Twine("Offset " + Twine(CFAOffset))); Streamer.EmitULEB128IntValue(CFAOffset); return; } case MCCFIInstruction::OpDefCfa: { - if (VerboseAsm) - Streamer.AddComment("DW_CFA_def_cfa"); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa, 1); - - if (VerboseAsm) - Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister())); Streamer.EmitULEB128IntValue(Instr.getRegister()); - CFAOffset = -Instr.getOffset(); - - if (VerboseAsm) - Streamer.AddComment(Twine("Offset " + Twine(CFAOffset))); Streamer.EmitULEB128IntValue(CFAOffset); return; } case MCCFIInstruction::OpDefCfaRegister: { - if (VerboseAsm) - Streamer.AddComment("DW_CFA_def_cfa_register"); Streamer.EmitIntValue(dwarf::DW_CFA_def_cfa_register, 1); - - if (VerboseAsm) - Streamer.AddComment(Twine("Reg ") + Twine(Instr.getRegister())); Streamer.EmitULEB128IntValue(Instr.getRegister()); return; @@ -1173,63 +1109,44 @@ void FrameEmitterImpl::EmitCFIInstruction(MCObjectStreamer &Streamer, Offset = Offset / dataAlignmentFactor; if (Offset < 0) { - if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended_sf"); Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended_sf, 1); - if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); Streamer.EmitULEB128IntValue(Reg); - if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitSLEB128IntValue(Offset); } else if (Reg < 64) { - if (VerboseAsm) Streamer.AddComment(Twine("DW_CFA_offset + Reg(") + - Twine(Reg) + ")"); Streamer.EmitIntValue(dwarf::DW_CFA_offset + Reg, 1); - if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitULEB128IntValue(Offset); } else { - if (VerboseAsm) Streamer.AddComment("DW_CFA_offset_extended"); Streamer.EmitIntValue(dwarf::DW_CFA_offset_extended, 1); - if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); Streamer.EmitULEB128IntValue(Reg); - if (VerboseAsm) Streamer.AddComment(Twine("Offset ") + Twine(Offset)); Streamer.EmitULEB128IntValue(Offset); } return; } case MCCFIInstruction::OpRememberState: - if (VerboseAsm) Streamer.AddComment("DW_CFA_remember_state"); Streamer.EmitIntValue(dwarf::DW_CFA_remember_state, 1); return; case MCCFIInstruction::OpRestoreState: - if (VerboseAsm) Streamer.AddComment("DW_CFA_restore_state"); Streamer.EmitIntValue(dwarf::DW_CFA_restore_state, 1); return; case MCCFIInstruction::OpSameValue: { unsigned Reg = Instr.getRegister(); - if (VerboseAsm) Streamer.AddComment("DW_CFA_same_value"); Streamer.EmitIntValue(dwarf::DW_CFA_same_value, 1); - if (VerboseAsm) Streamer.AddComment(Twine("Reg ") + Twine(Reg)); Streamer.EmitULEB128IntValue(Reg); return; } case MCCFIInstruction::OpRestore: { unsigned Reg = Instr.getRegister(); - if (VerboseAsm) { - Streamer.AddComment("DW_CFA_restore"); - Streamer.AddComment(Twine("Reg ") + Twine(Reg)); - } Streamer.EmitIntValue(dwarf::DW_CFA_restore | Reg, 1); return; } case MCCFIInstruction::OpEscape: - if (VerboseAsm) Streamer.AddComment("Escape bytes"); Streamer.EmitBytes(Instr.getValues()); return; } llvm_unreachable("Unhandled case in switch"); } -/// EmitFrameMoves - Emit frame instructions to describe the layout of the -/// frame. +/// Emit frame instructions to describe the layout of the frame. void FrameEmitterImpl::EmitCFIInstructions(MCObjectStreamer &streamer, ArrayRef Instrs, MCSymbol *BaseLabel) { @@ -1243,7 +1160,6 @@ void FrameEmitterImpl::EmitCFIInstructions(MCObjectStreamer &streamer, if (BaseLabel && Label) { MCSymbol *ThisSym = Label; if (ThisSym != BaseLabel) { - if (streamer.isVerboseAsm()) streamer.AddComment("DW_CFA_advance_loc4"); streamer.EmitDwarfAdvanceFrameAddr(BaseLabel, ThisSym); BaseLabel = ThisSym; } @@ -1253,12 +1169,11 @@ void FrameEmitterImpl::EmitCFIInstructions(MCObjectStreamer &streamer, } } -/// EmitCompactUnwind - Emit the unwind information in a compact way. -void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, +/// Emit the unwind information in a compact way. +void FrameEmitterImpl::EmitCompactUnwind(MCObjectStreamer &Streamer, const MCDwarfFrameInfo &Frame) { MCContext &Context = Streamer.getContext(); const MCObjectFileInfo *MOFI = Context.getObjectFileInfo(); - bool VerboseAsm = Streamer.isVerboseAsm(); // range-start range-length compact-unwind-enc personality-func lsda // _foo LfooEnd-_foo 0x00000023 0 0 @@ -1293,24 +1208,19 @@ void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // Range Start unsigned FDEEncoding = MOFI->getFDEEncoding(); unsigned Size = getSizeForEncoding(Streamer, FDEEncoding); - if (VerboseAsm) Streamer.AddComment("Range Start"); Streamer.EmitSymbolValue(Frame.Begin, Size); // Range Length const MCExpr *Range = MakeStartMinusEndExpr(Streamer, *Frame.Begin, *Frame.End, 0); - if (VerboseAsm) Streamer.AddComment("Range Length"); - Streamer.EmitAbsValue(Range, 4); + emitAbsValue(Streamer, Range, 4); // Compact Encoding Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4); - if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding: 0x" + - Twine::utohexstr(Encoding)); Streamer.EmitIntValue(Encoding, Size); // Personality Function Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_absptr); - if (VerboseAsm) Streamer.AddComment("Personality Function"); if (!DwarfEHFrameOnly && Frame.Personality) Streamer.EmitSymbolValue(Frame.Personality, Size); else @@ -1318,7 +1228,6 @@ void FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer, // LSDA Size = getSizeForEncoding(Streamer, Frame.LsdaEncoding); - if (VerboseAsm) Streamer.AddComment("LSDA"); if (!DwarfEHFrameOnly && Frame.Lsda) Streamer.EmitSymbolValue(Frame.Lsda, Size); else @@ -1335,27 +1244,22 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, MCContext &context = streamer.getContext(); const MCRegisterInfo *MRI = context.getRegisterInfo(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); - bool verboseAsm = streamer.isVerboseAsm(); MCSymbol *sectionStart = context.CreateTempSymbol(); streamer.EmitLabel(sectionStart); - CIENum++; MCSymbol *sectionEnd = context.CreateTempSymbol(); // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart, *sectionEnd, 4); - if (verboseAsm) streamer.AddComment("CIE Length"); - streamer.EmitAbsValue(Length, 4); + emitAbsValue(streamer, Length, 4); // CIE ID unsigned CIE_ID = IsEH ? 0 : -1; - if (verboseAsm) streamer.AddComment("CIE ID Tag"); streamer.EmitIntValue(CIE_ID, 4); // Version - if (verboseAsm) streamer.AddComment("DW_CIE_VERSION"); // For DWARF2, we use CIE version 1 // For DWARF3+, we use CIE version 3 uint8_t CIEVersion = context.getDwarfVersion() <= 2 ? 1 : 3; @@ -1364,7 +1268,6 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, // Augmentation String SmallString<8> Augmentation; if (IsEH) { - if (verboseAsm) streamer.AddComment("CIE Augmentation"); Augmentation += "z"; if (personality) Augmentation += "P"; @@ -1378,15 +1281,12 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, streamer.EmitIntValue(0, 1); // Code Alignment Factor - if (verboseAsm) streamer.AddComment("CIE Code Alignment Factor"); streamer.EmitULEB128IntValue(context.getAsmInfo()->getMinInstAlignment()); // Data Alignment Factor - if (verboseAsm) streamer.AddComment("CIE Data Alignment Factor"); streamer.EmitSLEB128IntValue(getDataAlignmentFactor(streamer)); // Return Address Register - if (verboseAsm) streamer.AddComment("CIE Return Address Column"); if (CIEVersion == 1) { assert(MRI->getRARegister() <= 255 && "DWARF 2 encodes return_address_register in one byte"); @@ -1411,24 +1311,21 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCObjectStreamer &streamer, // Encoding of the FDE pointers augmentationLength += 1; - if (verboseAsm) streamer.AddComment("Augmentation Size"); streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data (optional) if (personality) { // Personality Encoding - EmitEncodingByte(streamer, personalityEncoding, - "Personality Encoding"); + emitEncodingByte(streamer, personalityEncoding); // Personality - if (verboseAsm) streamer.AddComment("Personality"); EmitPersonality(streamer, *personality, personalityEncoding); } if (lsda) - EmitEncodingByte(streamer, lsdaEncoding, "LSDA Encoding"); + emitEncodingByte(streamer, lsdaEncoding); // Encoding of the FDE pointers - EmitEncodingByte(streamer, MOFI->getFDEEncoding(), "FDE Encoding"); + emitEncodingByte(streamer, MOFI->getFDEEncoding()); } // Initial Instructions @@ -1454,12 +1351,10 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, MCSymbol *fdeStart = context.CreateTempSymbol(); MCSymbol *fdeEnd = context.CreateTempSymbol(); const MCObjectFileInfo *MOFI = context.getObjectFileInfo(); - bool verboseAsm = streamer.isVerboseAsm(); // Length const MCExpr *Length = MakeStartMinusEndExpr(streamer, *fdeStart, *fdeEnd, 0); - if (verboseAsm) streamer.AddComment("FDE Length"); - streamer.EmitAbsValue(Length, 4); + emitAbsValue(streamer, Length, 4); streamer.EmitLabel(fdeStart); @@ -1468,12 +1363,11 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, if (IsEH) { const MCExpr *offset = MakeStartMinusEndExpr(streamer, cieStart, *fdeStart, 0); - if (verboseAsm) streamer.AddComment("FDE CIE Offset"); - streamer.EmitAbsValue(offset, 4); + emitAbsValue(streamer, offset, 4); } else if (!asmInfo->doesDwarfUseRelocationsAcrossSections()) { const MCExpr *offset = MakeStartMinusEndExpr(streamer, *SectionStart, cieStart, 0); - streamer.EmitAbsValue(offset, 4); + emitAbsValue(streamer, offset, 4); } else { streamer.EmitSymbolValue(&cieStart, 4); } @@ -1482,13 +1376,12 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, unsigned PCEncoding = IsEH ? MOFI->getFDEEncoding() : (unsigned)dwarf::DW_EH_PE_absptr; unsigned PCSize = getSizeForEncoding(streamer, PCEncoding); - EmitFDESymbol(streamer, *frame.Begin, PCEncoding, IsEH, "FDE initial location"); + emitFDESymbol(streamer, *frame.Begin, PCEncoding, IsEH); // PC Range const MCExpr *Range = MakeStartMinusEndExpr(streamer, *frame.Begin, *frame.End, 0); - if (verboseAsm) streamer.AddComment("FDE address range"); - streamer.EmitAbsValue(Range, PCSize); + emitAbsValue(streamer, Range, PCSize); if (IsEH) { // Augmentation Data Length @@ -1497,13 +1390,11 @@ MCSymbol *FrameEmitterImpl::EmitFDE(MCObjectStreamer &streamer, if (frame.Lsda) augmentationLength += getSizeForEncoding(streamer, frame.LsdaEncoding); - if (verboseAsm) streamer.AddComment("Augmentation size"); streamer.EmitULEB128IntValue(augmentationLength); // Augmentation Data if (frame.Lsda) - EmitFDESymbol(streamer, *frame.Lsda, frame.LsdaEncoding, true, - "Language Specific Data Area"); + emitFDESymbol(streamer, *frame.Lsda, frame.LsdaEncoding, true); } // Call Frame Instructions diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 7c70540..bdc4a84 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" @@ -38,19 +39,23 @@ using namespace llvm; MCELFStreamer::~MCELFStreamer() { } -void MCELFStreamer::InitSections() { +void MCELFStreamer::InitSections(bool NoExecStack) { // This emulates the same behavior of GNU as. This makes it easier // to compare the output as the major sections are in the same order. - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); + MCContext &Ctx = getContext(); + SwitchSection(Ctx.getObjectFileInfo()->getTextSection()); EmitCodeAlignment(4); - SwitchSection(getContext().getObjectFileInfo()->getDataSection()); + SwitchSection(Ctx.getObjectFileInfo()->getDataSection()); EmitCodeAlignment(4); - SwitchSection(getContext().getObjectFileInfo()->getBSSSection()); + SwitchSection(Ctx.getObjectFileInfo()->getBSSSection()); EmitCodeAlignment(4); - SwitchSection(getContext().getObjectFileInfo()->getTextSection()); + SwitchSection(Ctx.getObjectFileInfo()->getTextSection()); + + if (NoExecStack) + SwitchSection(Ctx.getAsmInfo()->getNonexecutableStackSection(Ctx)); } void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { @@ -87,10 +92,19 @@ void MCELFStreamer::ChangeSection(const MCSection *Section, MCSectionData *CurSection = getCurrentSectionData(); if (CurSection && CurSection->isBundleLocked()) report_fatal_error("Unterminated .bundle_lock when changing a section"); - const MCSymbol *Grp = static_cast(Section)->getGroup(); + + MCAssembler &Asm = getAssembler(); + auto *SectionELF = static_cast(Section); + const MCSymbol *Grp = SectionELF->getGroup(); if (Grp) - getAssembler().getOrCreateSymbolData(*Grp); + Asm.getOrCreateSymbolData(*Grp); + this->MCObjectStreamer::ChangeSection(Section, Subsection); + MCSymbol *SectionSymbol = getContext().getOrCreateSectionSymbol(*SectionELF); + if (SectionSymbol->isUndefined()) { + EmitLabel(SectionSymbol); + MCELF::SetType(Asm.getSymbolData(*SectionSymbol), ELF::STT_SECTION); + } } void MCELFStreamer::EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) { @@ -448,11 +462,13 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, } else { DF = new MCDataFragment(); insert(DF); - if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { - // If this is a new fragment created for a bundle-locked group, and the - // group was marked as "align_to_end", set a flag in the fragment. - DF->setAlignToBundleEnd(true); - } + } + if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) { + // If this fragment is for a group marked "align_to_end", set a flag + // in the fragment. This can happen after the fragment has already been + // created if there are nested bundle_align groups and an inner one + // is the one marked align_to_end. + DF->setAlignToBundleEnd(true); } // We're now emitting an instruction in a bundle group, so this flag has @@ -474,10 +490,11 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst, void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) { assert(AlignPow2 <= 30 && "Invalid bundle alignment"); MCAssembler &Assembler = getAssembler(); - if (Assembler.getBundleAlignSize() == 0 && AlignPow2 > 0) - Assembler.setBundleAlignSize(1 << AlignPow2); + if (AlignPow2 > 0 && (Assembler.getBundleAlignSize() == 0 || + Assembler.getBundleAlignSize() == 1U << AlignPow2)) + Assembler.setBundleAlignSize(1U << AlignPow2); else - report_fatal_error(".bundle_align_mode should be only set once per file"); + report_fatal_error(".bundle_align_mode cannot be changed once set"); } void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { @@ -487,12 +504,12 @@ void MCELFStreamer::EmitBundleLock(bool AlignToEnd) { // if (!getAssembler().isBundlingEnabled()) report_fatal_error(".bundle_lock forbidden when bundling is disabled"); - else if (SD->isBundleLocked()) - report_fatal_error("Nesting of .bundle_lock is forbidden"); + + if (!SD->isBundleLocked()) + SD->setBundleGroupBeforeFirstInst(true); SD->setBundleLockState(AlignToEnd ? MCSectionData::BundleLockedAlignToEnd : MCSectionData::BundleLocked); - SD->setBundleGroupBeforeFirstInst(true); } void MCELFStreamer::EmitBundleUnlock() { @@ -543,12 +560,10 @@ void MCELFStreamer::FinishImpl() { MCStreamer *llvm::createELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *CE, - bool RelaxAll, bool NoExecStack) { + bool RelaxAll) { MCELFStreamer *S = new MCELFStreamer(Context, MAB, OS, CE); if (RelaxAll) S->getAssembler().setRelaxAll(true); - if (NoExecStack) - S->getAssembler().setNoExecStack(true); return S; } diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index f724716..709dc6b 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -49,12 +49,8 @@ void MCExpr::print(raw_ostream &OS) const { else OS << Sym; - if (SRE.getKind() != MCSymbolRefExpr::VK_None) { - if (SRE.getMCAsmInfo().useParensForSymbolVariant()) - OS << '(' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()) << ')'; - else - OS << '@' << MCSymbolRefExpr::getVariantKindName(SRE.getKind()); - } + if (SRE.getKind() != MCSymbolRefExpr::VK_None) + SRE.printVariantKind(OS); return; } @@ -150,6 +146,15 @@ const MCConstantExpr *MCConstantExpr::Create(int64_t Value, MCContext &Ctx) { /* *** */ +MCSymbolRefExpr::MCSymbolRefExpr(const MCSymbol *Symbol, VariantKind Kind, + const MCAsmInfo *MAI) + : MCExpr(MCExpr::SymbolRef), Kind(Kind), + UseParensForSymbolVariant(MAI->useParensForSymbolVariant()), + HasSubsectionsViaSymbols(MAI->hasSubsectionsViaSymbols()), + Symbol(Symbol) { + assert(Symbol); +} + const MCSymbolRefExpr *MCSymbolRefExpr::Create(const MCSymbol *Sym, VariantKind Kind, MCContext &Ctx) { @@ -192,6 +197,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_ARM_TARGET1: return "target1"; case VK_ARM_TARGET2: return "target2"; case VK_ARM_PREL31: return "prel31"; + case VK_ARM_SBREL: return "sbrel"; case VK_ARM_TLSLDO: return "tlsldo"; case VK_ARM_TLSCALL: return "tlscall"; case VK_ARM_TLSDESC: return "tlsdesc"; @@ -247,6 +253,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; case VK_PPC_TLSLD: return "tlsld"; + case VK_PPC_LOCAL: return "local"; case VK_Mips_GPREL: return "GPREL"; case VK_Mips_GOT_CALL: return "GOT_CALL"; case VK_Mips_GOT16: return "GOT16"; @@ -273,175 +280,105 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) { case VK_Mips_CALL_LO16: return "CALL_LO16"; case VK_Mips_PCREL_HI16: return "PCREL_HI16"; case VK_Mips_PCREL_LO16: return "PCREL_LO16"; - case VK_COFF_IMGREL32: return "IMGREL32"; + case VK_COFF_IMGREL32: return "IMGREL"; } llvm_unreachable("Invalid variant kind"); } MCSymbolRefExpr::VariantKind MCSymbolRefExpr::getVariantKindForName(StringRef Name) { - return StringSwitch(Name) - .Case("GOT", VK_GOT) + return StringSwitch(Name.lower()) .Case("got", VK_GOT) - .Case("GOTOFF", VK_GOTOFF) .Case("gotoff", VK_GOTOFF) - .Case("GOTPCREL", VK_GOTPCREL) .Case("gotpcrel", VK_GOTPCREL) - .Case("GOT_PREL", VK_GOTPCREL) .Case("got_prel", VK_GOTPCREL) - .Case("GOTTPOFF", VK_GOTTPOFF) .Case("gottpoff", VK_GOTTPOFF) - .Case("INDNTPOFF", VK_INDNTPOFF) .Case("indntpoff", VK_INDNTPOFF) - .Case("NTPOFF", VK_NTPOFF) .Case("ntpoff", VK_NTPOFF) - .Case("GOTNTPOFF", VK_GOTNTPOFF) .Case("gotntpoff", VK_GOTNTPOFF) - .Case("PLT", VK_PLT) .Case("plt", VK_PLT) - .Case("TLSGD", VK_TLSGD) .Case("tlsgd", VK_TLSGD) - .Case("TLSLD", VK_TLSLD) .Case("tlsld", VK_TLSLD) - .Case("TLSLDM", VK_TLSLDM) .Case("tlsldm", VK_TLSLDM) - .Case("TPOFF", VK_TPOFF) .Case("tpoff", VK_TPOFF) - .Case("DTPOFF", VK_DTPOFF) .Case("dtpoff", VK_DTPOFF) - .Case("TLVP", VK_TLVP) .Case("tlvp", VK_TLVP) - .Case("TLVPPAGE", VK_TLVPPAGE) .Case("tlvppage", VK_TLVPPAGE) - .Case("TLVPPAGEOFF", VK_TLVPPAGEOFF) .Case("tlvppageoff", VK_TLVPPAGEOFF) - .Case("PAGE", VK_PAGE) .Case("page", VK_PAGE) - .Case("PAGEOFF", VK_PAGEOFF) .Case("pageoff", VK_PAGEOFF) - .Case("GOTPAGE", VK_GOTPAGE) .Case("gotpage", VK_GOTPAGE) - .Case("GOTPAGEOFF", VK_GOTPAGEOFF) .Case("gotpageoff", VK_GOTPAGEOFF) - .Case("IMGREL", VK_COFF_IMGREL32) .Case("imgrel", VK_COFF_IMGREL32) - .Case("SECREL32", VK_SECREL) .Case("secrel32", VK_SECREL) - .Case("L", VK_PPC_LO) .Case("l", VK_PPC_LO) - .Case("H", VK_PPC_HI) .Case("h", VK_PPC_HI) - .Case("HA", VK_PPC_HA) .Case("ha", VK_PPC_HA) - .Case("HIGHER", VK_PPC_HIGHER) .Case("higher", VK_PPC_HIGHER) - .Case("HIGHERA", VK_PPC_HIGHERA) .Case("highera", VK_PPC_HIGHERA) - .Case("HIGHEST", VK_PPC_HIGHEST) .Case("highest", VK_PPC_HIGHEST) - .Case("HIGHESTA", VK_PPC_HIGHESTA) .Case("highesta", VK_PPC_HIGHESTA) - .Case("GOT@L", VK_PPC_GOT_LO) .Case("got@l", VK_PPC_GOT_LO) - .Case("GOT@H", VK_PPC_GOT_HI) .Case("got@h", VK_PPC_GOT_HI) - .Case("GOT@HA", VK_PPC_GOT_HA) .Case("got@ha", VK_PPC_GOT_HA) - .Case("TOCBASE", VK_PPC_TOCBASE) + .Case("local", VK_PPC_LOCAL) .Case("tocbase", VK_PPC_TOCBASE) - .Case("TOC", VK_PPC_TOC) .Case("toc", VK_PPC_TOC) - .Case("TOC@L", VK_PPC_TOC_LO) .Case("toc@l", VK_PPC_TOC_LO) - .Case("TOC@H", VK_PPC_TOC_HI) .Case("toc@h", VK_PPC_TOC_HI) - .Case("TOC@HA", VK_PPC_TOC_HA) .Case("toc@ha", VK_PPC_TOC_HA) - .Case("TLS", VK_PPC_TLS) .Case("tls", VK_PPC_TLS) - .Case("DTPMOD", VK_PPC_DTPMOD) .Case("dtpmod", VK_PPC_DTPMOD) - .Case("TPREL", VK_PPC_TPREL) .Case("tprel", VK_PPC_TPREL) - .Case("TPREL@L", VK_PPC_TPREL_LO) .Case("tprel@l", VK_PPC_TPREL_LO) - .Case("TPREL@H", VK_PPC_TPREL_HI) .Case("tprel@h", VK_PPC_TPREL_HI) - .Case("TPREL@HA", VK_PPC_TPREL_HA) .Case("tprel@ha", VK_PPC_TPREL_HA) - .Case("TPREL@HIGHER", VK_PPC_TPREL_HIGHER) .Case("tprel@higher", VK_PPC_TPREL_HIGHER) - .Case("TPREL@HIGHERA", VK_PPC_TPREL_HIGHERA) .Case("tprel@highera", VK_PPC_TPREL_HIGHERA) - .Case("TPREL@HIGHEST", VK_PPC_TPREL_HIGHEST) .Case("tprel@highest", VK_PPC_TPREL_HIGHEST) - .Case("TPREL@HIGHESTA", VK_PPC_TPREL_HIGHESTA) .Case("tprel@highesta", VK_PPC_TPREL_HIGHESTA) - .Case("DTPREL", VK_PPC_DTPREL) .Case("dtprel", VK_PPC_DTPREL) - .Case("DTPREL@L", VK_PPC_DTPREL_LO) .Case("dtprel@l", VK_PPC_DTPREL_LO) - .Case("DTPREL@H", VK_PPC_DTPREL_HI) .Case("dtprel@h", VK_PPC_DTPREL_HI) - .Case("DTPREL@HA", VK_PPC_DTPREL_HA) .Case("dtprel@ha", VK_PPC_DTPREL_HA) - .Case("DTPREL@HIGHER", VK_PPC_DTPREL_HIGHER) .Case("dtprel@higher", VK_PPC_DTPREL_HIGHER) - .Case("DTPREL@HIGHERA", VK_PPC_DTPREL_HIGHERA) .Case("dtprel@highera", VK_PPC_DTPREL_HIGHERA) - .Case("DTPREL@HIGHEST", VK_PPC_DTPREL_HIGHEST) .Case("dtprel@highest", VK_PPC_DTPREL_HIGHEST) - .Case("DTPREL@HIGHESTA", VK_PPC_DTPREL_HIGHESTA) .Case("dtprel@highesta", VK_PPC_DTPREL_HIGHESTA) - .Case("GOT@TPREL", VK_PPC_GOT_TPREL) .Case("got@tprel", VK_PPC_GOT_TPREL) - .Case("GOT@TPREL@L", VK_PPC_GOT_TPREL_LO) .Case("got@tprel@l", VK_PPC_GOT_TPREL_LO) - .Case("GOT@TPREL@H", VK_PPC_GOT_TPREL_HI) .Case("got@tprel@h", VK_PPC_GOT_TPREL_HI) - .Case("GOT@TPREL@HA", VK_PPC_GOT_TPREL_HA) .Case("got@tprel@ha", VK_PPC_GOT_TPREL_HA) - .Case("GOT@DTPREL", VK_PPC_GOT_DTPREL) .Case("got@dtprel", VK_PPC_GOT_DTPREL) - .Case("GOT@DTPREL@L", VK_PPC_GOT_DTPREL_LO) .Case("got@dtprel@l", VK_PPC_GOT_DTPREL_LO) - .Case("GOT@DTPREL@H", VK_PPC_GOT_DTPREL_HI) .Case("got@dtprel@h", VK_PPC_GOT_DTPREL_HI) - .Case("GOT@DTPREL@HA", VK_PPC_GOT_DTPREL_HA) .Case("got@dtprel@ha", VK_PPC_GOT_DTPREL_HA) - .Case("GOT@TLSGD", VK_PPC_GOT_TLSGD) .Case("got@tlsgd", VK_PPC_GOT_TLSGD) - .Case("GOT@TLSGD@L", VK_PPC_GOT_TLSGD_LO) .Case("got@tlsgd@l", VK_PPC_GOT_TLSGD_LO) - .Case("GOT@TLSGD@H", VK_PPC_GOT_TLSGD_HI) .Case("got@tlsgd@h", VK_PPC_GOT_TLSGD_HI) - .Case("GOT@TLSGD@HA", VK_PPC_GOT_TLSGD_HA) .Case("got@tlsgd@ha", VK_PPC_GOT_TLSGD_HA) - .Case("GOT@TLSLD", VK_PPC_GOT_TLSLD) .Case("got@tlsld", VK_PPC_GOT_TLSLD) - .Case("GOT@TLSLD@L", VK_PPC_GOT_TLSLD_LO) .Case("got@tlsld@l", VK_PPC_GOT_TLSLD_LO) - .Case("GOT@TLSLD@H", VK_PPC_GOT_TLSLD_HI) .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) - .Case("GOT@TLSLD@HA", VK_PPC_GOT_TLSLD_HA) .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) - .Case("NONE", VK_ARM_NONE) .Case("none", VK_ARM_NONE) - .Case("TARGET1", VK_ARM_TARGET1) .Case("target1", VK_ARM_TARGET1) - .Case("TARGET2", VK_ARM_TARGET2) .Case("target2", VK_ARM_TARGET2) - .Case("PREL31", VK_ARM_PREL31) .Case("prel31", VK_ARM_PREL31) - .Case("TLSLDO", VK_ARM_TLSLDO) + .Case("sbrel", VK_ARM_SBREL) .Case("tlsldo", VK_ARM_TLSLDO) - .Case("TLSCALL", VK_ARM_TLSCALL) .Case("tlscall", VK_ARM_TLSCALL) - .Case("TLSDESC", VK_ARM_TLSDESC) .Case("tlsdesc", VK_ARM_TLSDESC) .Default(VK_Invalid); } +void MCSymbolRefExpr::printVariantKind(raw_ostream &OS) const { + if (UseParensForSymbolVariant) + OS << '(' << MCSymbolRefExpr::getVariantKindName(getKind()) << ')'; + else + OS << '@' << MCSymbolRefExpr::getVariantKindName(getKind()); +} + /* *** */ void MCTargetExpr::anchor() {} @@ -467,9 +404,27 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const { return EvaluateAsAbsolute(Res, &Asm, nullptr, nullptr); } +int64_t MCExpr::evaluateKnownAbsolute(const MCAsmLayout &Layout) const { + int64_t Res; + bool Abs = + evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr, true); + (void)Abs; + assert(Abs && "Not actually absolute"); + return Res; +} + bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, const SectionAddrMap *Addrs) const { + // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us + // absolutize differences across sections and that is what the MachO writer + // uses Addrs for. + return evaluateAsAbsolute(Res, Asm, Layout, Addrs, Addrs); +} + +bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, + const MCAsmLayout *Layout, + const SectionAddrMap *Addrs, bool InSet) const { MCValue Value; // Fast path constants. @@ -478,12 +433,8 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm, return true; } - // FIXME: The use if InSet = Addrs is a hack. Setting InSet causes us - // absolutize differences across sections and that is what the MachO writer - // uses Addrs for. - bool IsRelocatable = - EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, /*InSet*/ Addrs, - /*ForceVarExpansion*/ false); + bool IsRelocatable = EvaluateAsRelocatableImpl( + Value, Asm, Layout, nullptr, Addrs, InSet, /*ForceVarExpansion*/ false); // Record the current value. Res = Value.getConstant(); @@ -632,27 +583,31 @@ static bool EvaluateSymbolicAdd(const MCAssembler *Asm, } bool MCExpr::EvaluateAsRelocatable(MCValue &Res, - const MCAsmLayout *Layout) const { + const MCAsmLayout *Layout, + const MCFixup *Fixup) const { MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; - return EvaluateAsRelocatableImpl(Res, Assembler, Layout, nullptr, false, - /*ForceVarExpansion*/ false); + return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, + false, /*ForceVarExpansion*/ false); } -bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout) const { +bool MCExpr::EvaluateAsValue(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const { MCAssembler *Assembler = Layout ? &Layout->getAssembler() : nullptr; - return EvaluateAsRelocatableImpl(Res, Assembler, Layout, nullptr, false, - /*ForceVarExpansion*/ true); + return EvaluateAsRelocatableImpl(Res, Assembler, Layout, Fixup, nullptr, + false, /*ForceVarExpansion*/ true); } bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCAsmLayout *Layout, + const MCFixup *Fixup, const SectionAddrMap *Addrs, bool InSet, bool ForceVarExpansion) const { ++stats::MCExprEvaluate; switch (getKind()) { case Target: - return cast(this)->EvaluateAsRelocatableImpl(Res, Layout); + return cast(this)->EvaluateAsRelocatableImpl(Res, Layout, + Fixup); case Constant: Res = MCValue::get(cast(this)->getValue()); @@ -661,16 +616,15 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, case SymbolRef: { const MCSymbolRefExpr *SRE = cast(this); const MCSymbol &Sym = SRE->getSymbol(); - const MCAsmInfo &MCAsmInfo = SRE->getMCAsmInfo(); // Evaluate recursively if this is a variable. if (Sym.isVariable() && SRE->getKind() == MCSymbolRefExpr::VK_None) { if (Sym.getVariableValue()->EvaluateAsRelocatableImpl( - Res, Asm, Layout, Addrs, true, ForceVarExpansion)) { + Res, Asm, Layout, Fixup, Addrs, true, ForceVarExpansion)) { const MCSymbolRefExpr *A = Res.getSymA(); const MCSymbolRefExpr *B = Res.getSymB(); - if (MCAsmInfo.hasSubsectionsViaSymbols()) { + if (SRE->hasSubsectionsViaSymbols()) { // FIXME: This is small hack. Given // a = b + 4 // .long a @@ -697,8 +651,9 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCUnaryExpr *AUE = cast(this); MCValue Value; - if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, Addrs, - InSet, ForceVarExpansion)) + if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Asm, Layout, + Fixup, Addrs, InSet, + ForceVarExpansion)) return false; switch (AUE->getOpcode()) { @@ -731,10 +686,12 @@ bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res, const MCAssembler *Asm, const MCBinaryExpr *ABE = cast(this); MCValue LHSValue, RHSValue; - if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, Addrs, - InSet, ForceVarExpansion) || - !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, Addrs, - InSet, ForceVarExpansion)) + if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Asm, Layout, + Fixup, Addrs, InSet, + ForceVarExpansion) || + !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Asm, Layout, + Fixup, Addrs, InSet, + ForceVarExpansion)) return false; // We only support a few operations on non-constant expressions, handle diff --git a/lib/MC/MCExternalSymbolizer.cpp b/lib/MC/MCExternalSymbolizer.cpp deleted file mode 100644 index 7c3073a..0000000 --- a/lib/MC/MCExternalSymbolizer.cpp +++ /dev/null @@ -1,198 +0,0 @@ -//===-- lib/MC/MCExternalSymbolizer.cpp - External symbolizer ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCExternalSymbolizer.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/raw_ostream.h" -#include - -using namespace llvm; - -// This function tries to add a symbolic operand in place of the immediate -// Value in the MCInst. The immediate Value has had any PC adjustment made by -// the caller. If the instruction is a branch instruction then IsBranch is true, -// else false. If the getOpInfo() function was set as part of the -// setupForSymbolicDisassembly() call then that function is called to get any -// symbolic information at the Address for this instruction. If that returns -// non-zero then the symbolic information it returns is used to create an MCExpr -// and that is added as an operand to the MCInst. If getOpInfo() returns zero -// and IsBranch is true then a symbol look up for Value is done and if a symbol -// is found an MCExpr is created with that, else an MCExpr with Value is -// created. This function returns true if it adds an operand to the MCInst and -// false otherwise. -bool MCExternalSymbolizer::tryAddingSymbolicOperand(MCInst &MI, - raw_ostream &cStream, - int64_t Value, - uint64_t Address, - bool IsBranch, - uint64_t Offset, - uint64_t InstSize) { - struct LLVMOpInfo1 SymbolicOp; - std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); - SymbolicOp.Value = Value; - - if (!GetOpInfo || - !GetOpInfo(DisInfo, Address, Offset, InstSize, 1, &SymbolicOp)) { - // Clear SymbolicOp.Value from above and also all other fields. - std::memset(&SymbolicOp, '\0', sizeof(struct LLVMOpInfo1)); - - // At this point, GetOpInfo() did not find any relocation information about - // this operand and we are left to use the SymbolLookUp() call back to guess - // if the Value is the address of a symbol. In the case this is a branch - // that always makes sense to guess. But in the case of an immediate it is - // a bit more questionable if it is an address of a symbol or some other - // reference. So if the immediate Value comes from a width of 1 byte, - // InstSize, we will not guess it is an address of a symbol. Because in - // object files assembled starting at address 0 this usually leads to - // incorrect symbolication. - if (!SymbolLookUp || (InstSize == 1 && !IsBranch)) - return false; - - uint64_t ReferenceType; - if (IsBranch) - ReferenceType = LLVMDisassembler_ReferenceType_In_Branch; - else - ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; - const char *ReferenceName; - const char *Name = SymbolLookUp(DisInfo, Value, &ReferenceType, Address, - &ReferenceName); - if (Name) { - SymbolicOp.AddSymbol.Name = Name; - SymbolicOp.AddSymbol.Present = true; - // If Name is a C++ symbol name put the human readable name in a comment. - if(ReferenceType == LLVMDisassembler_ReferenceType_DeMangled_Name) - cStream << ReferenceName; - } - // For branches always create an MCExpr so it gets printed as hex address. - else if (IsBranch) { - SymbolicOp.Value = Value; - } - if(ReferenceType == LLVMDisassembler_ReferenceType_Out_SymbolStub) - cStream << "symbol stub for: " << ReferenceName; - else if(ReferenceType == LLVMDisassembler_ReferenceType_Out_Objc_Message) - cStream << "Objc message: " << ReferenceName; - if (!Name && !IsBranch) - return false; - } - - const MCExpr *Add = nullptr; - if (SymbolicOp.AddSymbol.Present) { - if (SymbolicOp.AddSymbol.Name) { - StringRef Name(SymbolicOp.AddSymbol.Name); - MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); - Add = MCSymbolRefExpr::Create(Sym, Ctx); - } else { - Add = MCConstantExpr::Create((int)SymbolicOp.AddSymbol.Value, Ctx); - } - } - - const MCExpr *Sub = nullptr; - if (SymbolicOp.SubtractSymbol.Present) { - if (SymbolicOp.SubtractSymbol.Name) { - StringRef Name(SymbolicOp.SubtractSymbol.Name); - MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name); - Sub = MCSymbolRefExpr::Create(Sym, Ctx); - } else { - Sub = MCConstantExpr::Create((int)SymbolicOp.SubtractSymbol.Value, Ctx); - } - } - - const MCExpr *Off = nullptr; - if (SymbolicOp.Value != 0) - Off = MCConstantExpr::Create(SymbolicOp.Value, Ctx); - - const MCExpr *Expr; - if (Sub) { - const MCExpr *LHS; - if (Add) - LHS = MCBinaryExpr::CreateSub(Add, Sub, Ctx); - else - LHS = MCUnaryExpr::CreateMinus(Sub, Ctx); - if (Off) - Expr = MCBinaryExpr::CreateAdd(LHS, Off, Ctx); - else - Expr = LHS; - } else if (Add) { - if (Off) - Expr = MCBinaryExpr::CreateAdd(Add, Off, Ctx); - else - Expr = Add; - } else { - if (Off) - Expr = Off; - else - Expr = MCConstantExpr::Create(0, Ctx); - } - - Expr = RelInfo->createExprForCAPIVariantKind(Expr, SymbolicOp.VariantKind); - if (!Expr) - return false; - - MI.addOperand(MCOperand::CreateExpr(Expr)); - return true; -} - -// This function tries to add a comment as to what is being referenced by a load -// instruction with the base register that is the Pc. These can often be values -// in a literal pool near the Address of the instruction. The Address of the -// instruction and its immediate Value are used as a possible literal pool entry. -// The SymbolLookUp call back will return the name of a symbol referenced by the -// literal pool's entry if the referenced address is that of a symbol. Or it -// will return a pointer to a literal 'C' string if the referenced address of -// the literal pool's entry is an address into a section with C string literals. -// Or if the reference is to an Objective-C data structure it will return a -// specific reference type for it and a string. -void MCExternalSymbolizer::tryAddingPcLoadReferenceComment(raw_ostream &cStream, - int64_t Value, - uint64_t Address) { - if (SymbolLookUp) { - uint64_t ReferenceType = LLVMDisassembler_ReferenceType_In_PCrel_Load; - const char *ReferenceName; - (void)SymbolLookUp(DisInfo, Value, &ReferenceType, Address, &ReferenceName); - if(ReferenceType == LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr) - cStream << "literal pool symbol address: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr) { - cStream << "literal pool for: \""; - cStream.write_escaped(ReferenceName); - cStream << "\""; - } - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref) - cStream << "Objc cfstring ref: @\"" << ReferenceName << "\""; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Message) - cStream << "Objc message: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref) - cStream << "Objc message ref: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref) - cStream << "Objc selector ref: " << ReferenceName; - else if(ReferenceType == - LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref) - cStream << "Objc class ref: " << ReferenceName; - } -} - -namespace llvm { -MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, - MCRelocationInfo *RelInfo) { - assert(Ctx && "No MCContext given for symbolic disassembly"); - - return new MCExternalSymbolizer(*Ctx, - std::unique_ptr(RelInfo), - GetOpInfo, SymbolLookUp, DisInfo); -} -} diff --git a/lib/MC/MCLinkerOptimizationHint.cpp b/lib/MC/MCLinkerOptimizationHint.cpp index 3f8d620..7739878 100644 --- a/lib/MC/MCLinkerOptimizationHint.cpp +++ b/lib/MC/MCLinkerOptimizationHint.cpp @@ -9,8 +9,8 @@ #include "llvm/MC/MCLinkerOptimizationHint.h" #include "llvm/MC/MCAsmLayout.h" -#include "llvm/Support/LEB128.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/Support/LEB128.h" using namespace llvm; diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 9e8bc94..a147c3d 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -55,6 +55,12 @@ public: : MCObjectStreamer(Context, MAB, OS, Emitter), LabelSections(label) {} + /// state management + void reset() override { + HasSectionLabel.clear(); + MCObjectStreamer::reset(); + } + /// @name MCStreamer Interface /// @{ @@ -90,8 +96,8 @@ public: unsigned ByteAlignment) override; void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, uint64_t Size = 0, unsigned ByteAlignment = 0) override; - virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, - uint64_t Size, unsigned ByteAlignment = 0) override; + void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, + unsigned ByteAlignment = 0) override; void EmitFileDirective(StringRef Filename) override { // FIXME: Just ignore the .file; it isn't important enough to fail the diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index d543402..fc56728 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -29,7 +29,6 @@ namespace { return true; } - void EmitCOFFSecRel32(MCSymbol const *Symbol) override {} void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) override {} void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = nullptr, diff --git a/lib/MC/MCObjectFileInfo.cpp b/lib/MC/MCObjectFileInfo.cpp index aeb9299..858181d 100644 --- a/lib/MC/MCObjectFileInfo.cpp +++ b/lib/MC/MCObjectFileInfo.cpp @@ -24,7 +24,7 @@ static bool useCompactUnwind(const Triple &T) { return false; // aarch64 always has it. - if (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64) + if (T.getArch() == Triple::aarch64) return true; // Use it on newer version of OS X. @@ -43,8 +43,7 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { // MachO SupportsWeakOmittedEHFrame = false; - if (T.isOSDarwin() && - (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64)) + if (T.isOSDarwin() && T.getArch() == Triple::aarch64) SupportsCompactUnwindWithoutEHFrame = true; PersonalityEncoding = dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel @@ -178,7 +177,7 @@ void MCObjectFileInfo::InitMachOMCObjectFileInfo(Triple T) { if (T.getArch() == Triple::x86_64 || T.getArch() == Triple::x86) CompactUnwindDwarfEHFrameOnly = 0x04000000; - else if (T.getArch() == Triple::arm64 || T.getArch() == Triple::aarch64) + else if (T.getArch() == Triple::aarch64) CompactUnwindDwarfEHFrameOnly = 0x03000000; } @@ -274,6 +273,12 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { case Triple::mips64el: FDECFIEncoding = dwarf::DW_EH_PE_sdata8; break; + case Triple::x86_64: + FDECFIEncoding = dwarf::DW_EH_PE_pcrel | + ((CMModel == CodeModel::Large) ? dwarf::DW_EH_PE_sdata8 + : dwarf::DW_EH_PE_sdata4); + + break; default: FDECFIEncoding = dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4; break; @@ -287,6 +292,7 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { if (Ctx->getAsmInfo()->getExceptionHandlingType() == ExceptionHandling::ARM) break; // Fallthrough if not using EHABI + case Triple::ppc: case Triple::x86: PersonalityEncoding = (RelocM == Reloc::PIC_) ? dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 @@ -321,8 +327,6 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { break; case Triple::aarch64: case Triple::aarch64_be: - case Triple::arm64: - case Triple::arm64_be: // The small model guarantees static code/data size < 4GB, but not where it // will be in memory. Most of these could end up >2GB away so even a signed // pc-relative 32-bit address is insufficient, theoretically. @@ -403,7 +407,7 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { // platform. EHSectionType = ELF::SHT_PROGBITS; EHSectionFlags = ELF::SHF_ALLOC; - if (T.getOS() == Triple::Solaris) { + if (T.isOSSolaris()) { if (T.getArch() == Triple::x86_64) EHSectionType = ELF::SHT_X86_64_UNWIND; else @@ -565,6 +569,9 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { DwarfInfoDWOSection = Ctx->getELFSection(".debug_info.dwo", ELF::SHT_PROGBITS, 0, SectionKind::getMetadata()); + DwarfTypesDWOSection = + Ctx->getELFSection(".debug_types.dwo", ELF::SHT_PROGBITS, 0, + SectionKind::getMetadata()); DwarfAbbrevDWOSection = Ctx->getELFSection(".debug_abbrev.dwo", ELF::SHT_PROGBITS, 0, SectionKind::getMetadata()); @@ -584,15 +591,19 @@ void MCObjectFileInfo::InitELFMCObjectFileInfo(Triple T) { DwarfAddrSection = Ctx->getELFSection(".debug_addr", ELF::SHT_PROGBITS, 0, SectionKind::getMetadata()); + + StackMapSection = + Ctx->getELFSection(".llvm_stackmaps", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC, + SectionKind::getMetadata()); + } void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { bool IsWoA = T.getArch() == Triple::arm || T.getArch() == Triple::thumb; - // The object file format cannot represent common symbols with explicit - // alignments. - CommDirectiveSupportsAlignment = false; + CommDirectiveSupportsAlignment = true; // COFF BSSSection = @@ -740,6 +751,10 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); + DwarfTypesDWOSection = + Ctx->getCOFFSection(".debug_types.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); DwarfAbbrevDWOSection = Ctx->getCOFFSection(".debug_abbrev.dwo", COFF::IMAGE_SCN_MEM_DISCARDABLE | @@ -772,6 +787,27 @@ void MCObjectFileInfo::InitCOFFMCObjectFileInfo(Triple T) { COFF::IMAGE_SCN_MEM_READ, SectionKind::getMetadata()); + DwarfAccelNamesSection = + Ctx->getCOFFSection(".apple_names", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfAccelNamespaceSection = + Ctx->getCOFFSection(".apple_namespaces", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfAccelTypesSection = + Ctx->getCOFFSection(".apple_types", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DwarfAccelObjCSection = + Ctx->getCOFFSection(".apple_objc", + COFF::IMAGE_SCN_MEM_DISCARDABLE | + COFF::IMAGE_SCN_MEM_READ, + SectionKind::getMetadata()); + DrectveSection = Ctx->getCOFFSection(".drectve", COFF::IMAGE_SCN_LNK_INFO | @@ -829,7 +865,7 @@ void MCObjectFileInfo::InitMCObjectFileInfo(StringRef T, Reloc::Model relocm, // cellspu-apple-darwin. Perhaps we should fix in Triple? if ((Arch == Triple::x86 || Arch == Triple::x86_64 || Arch == Triple::arm || Arch == Triple::thumb || - Arch == Triple::arm64 || Arch == Triple::aarch64 || + Arch == Triple::aarch64 || Arch == Triple::ppc || Arch == Triple::ppc64 || Arch == Triple::UnknownArch) && (TT.isOSDarwin() || TT.isOSBinFormatMachO())) { @@ -851,13 +887,6 @@ const MCSection *MCObjectFileInfo::getDwarfTypesSection(uint64_t Hash) const { SectionKind::getMetadata(), 0, utostr(Hash)); } -const MCSection * -MCObjectFileInfo::getDwarfTypesDWOSection(uint64_t Hash) const { - return Ctx->getELFSection(".debug_types.dwo", ELF::SHT_PROGBITS, - ELF::SHF_GROUP, SectionKind::getMetadata(), 0, - utostr(Hash)); -} - void MCObjectFileInfo::InitEHFrameSection() { if (Env == IsMachO) EHFrameSection = diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index a721b59..08fe501 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -42,6 +42,21 @@ MCObjectStreamer::~MCObjectStreamer() { delete Assembler; } +void MCObjectStreamer::flushPendingLabels(MCFragment *F) { + if (PendingLabels.size()) { + if (!F) { + F = new MCDataFragment(); + CurSectionData->getFragmentList().insert(CurInsertionPoint, F); + F->setParent(CurSectionData); + } + for (MCSymbolData *SD : PendingLabels) { + SD->setFragment(F); + SD->setOffset(0); + } + PendingLabels.clear(); + } +} + void MCObjectStreamer::reset() { if (Assembler) Assembler->reset(); @@ -49,6 +64,7 @@ void MCObjectStreamer::reset() { CurInsertionPoint = MCSectionData::iterator(); EmitEHFrame = true; EmitDebugFrame = false; + PendingLabels.clear(); MCStreamer::reset(); } @@ -72,7 +88,7 @@ MCFragment *MCObjectStreamer::getCurrentFragment() const { return nullptr; } -MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { +MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() { MCDataFragment *F = dyn_cast_or_null(getCurrentFragment()); // When bundling is enabled, we don't want to add data to a fragment that // already has instructions (see MCELFStreamer::EmitInstToData for details) @@ -127,15 +143,17 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { MCStreamer::EmitLabel(Symbol); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - - // FIXME: This is wasteful, we don't necessarily need to create a data - // fragment. Instead, we should mark the symbol as pointing into the data - // fragment if it exists, otherwise we should just queue the label and set its - // fragment pointer when we emit the next fragment. - MCDataFragment *F = getOrCreateDataFragment(); assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); - SD.setFragment(F); - SD.setOffset(F->getContents().size()); + + // If there is a current fragment, mark the symbol as pointing into it. + // Otherwise queue the label and set its fragment pointer when we emit the + // next fragment. + if (auto *F = dyn_cast_or_null(getCurrentFragment())) { + SD.setFragment(F); + SD.setOffset(F->getContents().size()); + } else { + PendingLabels.push_back(&SD); + } } void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { @@ -144,7 +162,6 @@ void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { EmitULEB128IntValue(IntValue); return; } - Value = ForceExpAbs(Value); insert(new MCLEBFragment(*Value, false)); } @@ -154,7 +171,6 @@ void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) { EmitSLEB128IntValue(IntValue); return; } - Value = ForceExpAbs(Value); insert(new MCLEBFragment(*Value, true)); } @@ -166,6 +182,7 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, void MCObjectStreamer::ChangeSection(const MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); + flushPendingLabels(nullptr); CurSectionData = &getAssembler().getOrCreateSectionData(*Section); @@ -266,33 +283,54 @@ void MCObjectStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, Isa, Discriminator, FileName); } +static const MCExpr *buildSymbolDiff(MCObjectStreamer &OS, const MCSymbol *A, + const MCSymbol *B) { + MCContext &Context = OS.getContext(); + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + const MCExpr *ARef = MCSymbolRefExpr::Create(A, Variant, Context); + const MCExpr *BRef = MCSymbolRefExpr::Create(B, Variant, Context); + const MCExpr *AddrDelta = + MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context); + return AddrDelta; +} + +static void emitDwarfSetLineAddr(MCObjectStreamer &OS, int64_t LineDelta, + const MCSymbol *Label, int PointerSize) { + // emit the sequence to set the address + OS.EmitIntValue(dwarf::DW_LNS_extended_op, 1); + OS.EmitULEB128IntValue(PointerSize + 1); + OS.EmitIntValue(dwarf::DW_LNE_set_address, 1); + OS.EmitSymbolValue(Label, PointerSize); + + // emit the sequence for the LineDelta (from 1) and a zero address delta. + MCDwarfLineAddr::Emit(&OS, LineDelta, 0); +} + void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, unsigned PointerSize) { if (!LastLabel) { - EmitDwarfSetLineAddr(LineDelta, Label, PointerSize); + emitDwarfSetLineAddr(*this, LineDelta, Label, PointerSize); return; } - const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel); + const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel); int64_t Res; if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) { MCDwarfLineAddr::Emit(this, LineDelta, Res); return; } - AddrDelta = ForceExpAbs(AddrDelta); insert(new MCDwarfLineAddrFragment(LineDelta, *AddrDelta)); } void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel, const MCSymbol *Label) { - const MCExpr *AddrDelta = BuildSymbolDiff(getContext(), Label, LastLabel); + const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel); int64_t Res; if (AddrDelta->EvaluateAsAbsolute(Res, getAssembler())) { MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res); return; } - AddrDelta = ForceExpAbs(AddrDelta); insert(new MCDwarfCallFrameFragment(*AddrDelta)); } @@ -367,7 +405,9 @@ void MCObjectStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue) { } void MCObjectStreamer::EmitZeros(uint64_t NumBytes) { - unsigned ItemSize = getCurrentSection().first->isVirtualSection() ? 0 : 1; + const MCSection *Sec = getCurrentSection().first; + assert(Sec && "need a section"); + unsigned ItemSize = Sec->isVirtualSection() ? 0 : 1; insert(new MCFillFragment(0, ItemSize, NumBytes)); } @@ -379,5 +419,6 @@ void MCObjectStreamer::FinishImpl() { // Dump out the dwarf file & directory tables and line tables. MCDwarfLineTable::Emit(this); + flushPendingLabels(nullptr); getAssembler().Finish(); } diff --git a/lib/MC/MCParser/AsmLexer.cpp b/lib/MC/MCParser/AsmLexer.cpp index 145ad4a..5c8ec66 100644 --- a/lib/MC/MCParser/AsmLexer.cpp +++ b/lib/MC/MCParser/AsmLexer.cpp @@ -417,7 +417,7 @@ AsmToken AsmLexer::LexQuote() { StringRef AsmLexer::LexUntilEndOfStatement() { TokStart = CurPtr; - while (!isAtStartOfComment(*CurPtr) && // Start of line comment. + while (!isAtStartOfComment(CurPtr) && // Start of line comment. !isAtStatementSeparator(CurPtr) && // End of statement marker. *CurPtr != '\n' && *CurPtr != '\r' && (*CurPtr != 0 || CurPtr != CurBuf.end())) { @@ -458,9 +458,17 @@ const AsmToken AsmLexer::peekTok(bool ShouldSkipSpace) { return Token; } -bool AsmLexer::isAtStartOfComment(char Char) { - // FIXME: This won't work for multi-character comment indicators like "//". - return Char == *MAI.getCommentString(); +bool AsmLexer::isAtStartOfComment(const char *Ptr) { + const char *CommentString = MAI.getCommentString(); + + if (CommentString[1] == '\0') + return CommentString[0] == Ptr[0]; + + // FIXME: special case for the bogus "##" comment string in X86MCAsmInfoDarwin + if (CommentString[1] == '#') + return CommentString[0] == Ptr[0]; + + return strncmp(Ptr, CommentString, strlen(CommentString)) == 0; } bool AsmLexer::isAtStatementSeparator(const char *Ptr) { @@ -473,7 +481,7 @@ AsmToken AsmLexer::LexToken() { // This always consumes at least one character. int CurChar = getNextChar(); - if (isAtStartOfComment(CurChar)) { + if (isAtStartOfComment(TokStart)) { // If this comment starts with a '#', then return the Hash token and let // the assembler parser see if it can be parsed as a cpp line filename // comment. We do this only if we are at the start of a line. diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index ed1d704..8eff90a 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -45,10 +45,6 @@ #include using namespace llvm; -static cl::opt -FatalAssemblerWarnings("fatal-assembler-warnings", - cl::desc("Consider warnings as error")); - MCAsmParserSemaCallback::~MCAsmParserSemaCallback() {} namespace { @@ -73,19 +69,13 @@ struct MCAsmMacro { MCAsmMacroParameters Parameters; public: - MCAsmMacro(StringRef N, StringRef B, ArrayRef P) : - Name(N), Body(B), Parameters(P) {} + MCAsmMacro(StringRef N, StringRef B, MCAsmMacroParameters P) + : Name(N), Body(B), Parameters(std::move(P)) {} }; /// \brief Helper class for storing information about an active macro /// instantiation. struct MacroInstantiation { - /// The macro being instantiated. - const MCAsmMacro *TheMacro; - - /// The macro instantiation with substitutions. - MemoryBuffer *Instantiation; - /// The location of the instantiation. SMLoc InstantiationLoc; @@ -95,9 +85,11 @@ struct MacroInstantiation { /// The location where parsing should resume upon instantiation completion. SMLoc ExitLoc; + /// The depth of TheCondStack at the start of the instantiation. + size_t CondStackDepth; + public: - MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB, SMLoc EL, - MemoryBuffer *I); + MacroInstantiation(SMLoc IL, int EB, SMLoc EL, size_t CondStackDepth); }; struct ParseStatementInfo { @@ -129,7 +121,7 @@ private: SourceMgr &SrcMgr; SourceMgr::DiagHandlerTy SavedDiagHandler; void *SavedDiagContext; - MCAsmParserExtension *PlatformParser; + std::unique_ptr PlatformParser; /// This is the current buffer index we're lexing from as managed by the /// SourceMgr object. @@ -144,7 +136,7 @@ private: StringMap ExtensionDirectiveMap; /// \brief Map of currently defined macros. - StringMap MacroMap; + StringMap MacroMap; /// \brief Stack of active macro instantiations. std::vector ActiveMacros; @@ -246,7 +238,8 @@ public: private: - bool parseStatement(ParseStatementInfo &Info); + bool parseStatement(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI); void eatToEndOfLine(); bool parseCppHashLineFilenameComment(const SMLoc &L); @@ -269,7 +262,7 @@ private: const MCAsmMacro* lookupMacro(StringRef Name); /// \brief Define a new macro with the given name and information. - void defineMacro(StringRef Name, const MCAsmMacro& Macro); + void defineMacro(StringRef Name, MCAsmMacro Macro); /// \brief Undefine a macro. If no such macro was defined, it's a no-op. void undefineMacro(StringRef Name); @@ -355,9 +348,10 @@ private: DK_CFI_REMEMBER_STATE, DK_CFI_RESTORE_STATE, DK_CFI_SAME_VALUE, DK_CFI_RESTORE, DK_CFI_ESCAPE, DK_CFI_SIGNAL_FRAME, DK_CFI_UNDEFINED, DK_CFI_REGISTER, DK_CFI_WINDOW_SAVE, - DK_MACROS_ON, DK_MACROS_OFF, DK_MACRO, DK_ENDM, DK_ENDMACRO, DK_PURGEM, + DK_MACROS_ON, DK_MACROS_OFF, + DK_MACRO, DK_EXITM, DK_ENDM, DK_ENDMACRO, DK_PURGEM, DK_SLEB128, DK_ULEB128, - DK_ERR, DK_ERROR, + DK_ERR, DK_ERROR, DK_WARNING, DK_END }; @@ -407,6 +401,7 @@ private: // macro directives bool parseDirectivePurgeMacro(SMLoc DirectiveLoc); + bool parseDirectiveExitMacro(StringRef Directive); bool parseDirectiveEndMacro(StringRef Directive); bool parseDirectiveMacro(SMLoc DirectiveLoc); bool parseDirectiveMacrosOnOff(StringRef Directive); @@ -474,6 +469,9 @@ private: // ".err" or ".error" bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage); + // ".warning" + bool parseDirectiveWarning(SMLoc DirectiveLoc); + void initializeDirectiveKindMap(); }; } @@ -504,34 +502,24 @@ AsmParser::AsmParser(SourceMgr &_SM, MCContext &_Ctx, MCStreamer &_Out, // Initialize the platform / file format parser. switch (_Ctx.getObjectFileInfo()->getObjectFileType()) { case MCObjectFileInfo::IsCOFF: - PlatformParser = createCOFFAsmParser(); - PlatformParser->Initialize(*this); - break; + PlatformParser.reset(createCOFFAsmParser()); + break; case MCObjectFileInfo::IsMachO: - PlatformParser = createDarwinAsmParser(); - PlatformParser->Initialize(*this); - IsDarwin = true; - break; + PlatformParser.reset(createDarwinAsmParser()); + IsDarwin = true; + break; case MCObjectFileInfo::IsELF: - PlatformParser = createELFAsmParser(); - PlatformParser->Initialize(*this); - break; + PlatformParser.reset(createELFAsmParser()); + break; } + PlatformParser->Initialize(*this); initializeDirectiveKindMap(); } AsmParser::~AsmParser() { assert((HadError || ActiveMacros.empty()) && "Unexpected active macro instantiation!"); - - // Destroy any macros. - for (StringMap::iterator it = MacroMap.begin(), - ie = MacroMap.end(); - it != ie; ++it) - delete it->getValue(); - - delete PlatformParser; } void AsmParser::printMacroInstantiations() { @@ -550,7 +538,7 @@ void AsmParser::Note(SMLoc L, const Twine &Msg, ArrayRef Ranges) { } bool AsmParser::Warning(SMLoc L, const Twine &Msg, ArrayRef Ranges) { - if (FatalAssemblerWarnings) + if (getTargetParser().getTargetOptions().MCFatalWarnings) return Error(L, Msg, Ranges); printMessage(L, SourceMgr::DK_Warning, Msg, Ranges); printMacroInstantiations(); @@ -619,7 +607,7 @@ const AsmToken &AsmParser::Lex() { bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // Create the initial section, if requested. if (!NoInitialTextSection) - Out.InitSections(); + Out.InitSections(false); // Prime the lexer. Lex(); @@ -643,7 +631,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { // While we have input, parse each statement. while (Lexer.isNot(AsmToken::Eof)) { ParseStatementInfo Info; - if (!parseStatement(Info)) + if (!parseStatement(Info, nullptr)) continue; // We had an error, validate that one was emitted and recover by skipping to @@ -702,7 +690,7 @@ bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) { void AsmParser::checkForValidSection() { if (!ParsingInlineAsm && !getStreamer().getCurrentSection().first) { TokError("expected section directive before assembly directive"); - Out.InitSections(); + Out.InitSections(false); } } @@ -1188,7 +1176,8 @@ bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res, /// ::= EndOfStatement /// ::= Label* Directive ...Operands... EndOfStatement /// ::= Label* Identifier OperandList* EndOfStatement -bool AsmParser::parseStatement(ParseStatementInfo &Info) { +bool AsmParser::parseStatement(ParseStatementInfo &Info, + MCAsmParserSemaCallback *SI) { if (Lexer.is(AsmToken::EndOfStatement)) { Out.AddBlankLine(); Lex(); @@ -1298,10 +1287,20 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { // FIXME: This doesn't diagnose assignment to a symbol which has been // implicitly marked as external. MCSymbol *Sym; - if (LocalLabelVal == -1) + if (LocalLabelVal == -1) { + if (ParsingInlineAsm && SI) { + StringRef RewrittenLabel = SI->LookupInlineAsmLabel(IDVal, getSourceManager(), IDLoc, true); + assert(RewrittenLabel.size() && "We should have an internal name here."); + Info.AsmRewrites->push_back(AsmRewrite(AOK_Label, IDLoc, + IDVal.size(), RewrittenLabel)); + IDVal = RewrittenLabel; + } Sym = getContext().GetOrCreateSymbol(IDVal); - else + } else Sym = Ctx.CreateDirectionalLocalSymbol(LocalLabelVal); + + Sym->redefineIfPossible(); + if (!Sym->isUndefined() || Sym->isVariable()) return Error(IDLoc, "invalid symbol redefinition"); @@ -1542,6 +1541,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { return parseDirectiveMacrosOnOff(IDVal); case DK_MACRO: return parseDirectiveMacro(IDLoc); + case DK_EXITM: + return parseDirectiveExitMacro(IDVal); case DK_ENDM: case DK_ENDMACRO: return parseDirectiveEndMacro(IDVal); @@ -1553,6 +1554,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { return parseDirectiveError(IDLoc, false); case DK_ERROR: return parseDirectiveError(IDLoc, true); + case DK_WARNING: + return parseDirectiveWarning(IDLoc); } return Error(IDLoc, "unknown directive"); @@ -1595,14 +1598,18 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { // directive for the instruction. if (!HadError && getContext().getGenDwarfForAssembly() && getContext().getGenDwarfSectionSyms().count( - getStreamer().getCurrentSection().first)) { - - unsigned Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); + getStreamer().getCurrentSection().first)) { + unsigned Line; + if (ActiveMacros.empty()) + Line = SrcMgr.FindLineNumber(IDLoc, CurBuffer); + else + Line = SrcMgr.FindLineNumber(ActiveMacros.back()->InstantiationLoc, + ActiveMacros.back()->ExitBuffer); // If we previously parsed a cpp hash file line comment then make sure the // current Dwarf File is for the CppHashFilename if not then emit the // Dwarf File table for it and adjust the line number for the .loc. - if (CppHashFilename.size() != 0) { + if (CppHashFilename.size()) { unsigned FileNumber = getStreamer().EmitDwarfFileDirective( 0, StringRef(), CppHashFilename); getContext().setGenDwarfFileNumber(FileNumber); @@ -1630,7 +1637,7 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info) { // If parsing succeeded, match the instruction. if (!HadError) { - unsigned ErrorInfo; + uint64_t ErrorInfo; getTargetParser().MatchAndEmitInstruction(IDLoc, Info.Opcode, Info.ParsedOperands, Out, ErrorInfo, ParsingInlineAsm); @@ -1856,10 +1863,10 @@ bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body, return false; } -MacroInstantiation::MacroInstantiation(const MCAsmMacro *M, SMLoc IL, int EB, - SMLoc EL, MemoryBuffer *I) - : TheMacro(M), Instantiation(I), InstantiationLoc(IL), ExitBuffer(EB), - ExitLoc(EL) {} +MacroInstantiation::MacroInstantiation(SMLoc IL, int EB, SMLoc EL, + size_t CondStackDepth) + : InstantiationLoc(IL), ExitBuffer(EB), ExitLoc(EL), + CondStackDepth(CondStackDepth) {} static bool isOperator(AsmToken::TokenKind kind) { switch (kind) { @@ -2078,21 +2085,15 @@ bool AsmParser::parseMacroArguments(const MCAsmMacro *M, } const MCAsmMacro *AsmParser::lookupMacro(StringRef Name) { - StringMap::iterator I = MacroMap.find(Name); - return (I == MacroMap.end()) ? nullptr : I->getValue(); + StringMap::iterator I = MacroMap.find(Name); + return (I == MacroMap.end()) ? nullptr : &I->getValue(); } -void AsmParser::defineMacro(StringRef Name, const MCAsmMacro &Macro) { - MacroMap[Name] = new MCAsmMacro(Macro); +void AsmParser::defineMacro(StringRef Name, MCAsmMacro Macro) { + MacroMap.insert(std::make_pair(Name, std::move(Macro))); } -void AsmParser::undefineMacro(StringRef Name) { - StringMap::iterator I = MacroMap.find(Name); - if (I != MacroMap.end()) { - delete I->getValue(); - MacroMap.erase(I); - } -} +void AsmParser::undefineMacro(StringRef Name) { MacroMap.erase(Name); } bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // Arbitrarily limit macro nesting depth, to match 'as'. We can eliminate @@ -2117,17 +2118,17 @@ bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) { // instantiation. OS << ".endmacro\n"; - MemoryBuffer *Instantiation = + std::unique_ptr Instantiation = MemoryBuffer::getMemBufferCopy(OS.str(), ""); // Create the macro instantiation object and add to the current macro // instantiation stack. MacroInstantiation *MI = new MacroInstantiation( - M, NameLoc, CurBuffer, getTok().getLoc(), Instantiation); + NameLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()); ActiveMacros.push_back(MI); // Jump to the macro instantiation and prime the lexer. - CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); + CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); Lex(); @@ -2219,6 +2220,8 @@ bool AsmParser::parseAssignment(StringRef Name, bool allow_redef, } else Sym = getContext().GetOrCreateSymbol(Name); + Sym->setRedefinable(allow_redef); + // Do the assignment. Out.EmitAssignment(Sym, Value); if (NoDeadStrip) @@ -2600,12 +2603,14 @@ bool AsmParser::parseDirectiveFill() { if (!isUInt<32>(FillExpr) && FillSize > 4) Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits"); - int64_t NonZeroFillSize = FillSize > 4 ? 4 : FillSize; - FillExpr &= ~0ULL >> (64 - NonZeroFillSize * 8); - - for (uint64_t i = 0, e = NumValues; i != e; ++i) { - getStreamer().EmitIntValue(FillExpr, NonZeroFillSize); - getStreamer().EmitIntValue(0, FillSize - NonZeroFillSize); + if (NumValues > 0) { + int64_t NonZeroFillSize = FillSize > 4 ? 4 : FillSize; + FillExpr &= ~0ULL >> (64 - NonZeroFillSize * 8); + for (uint64_t i = 0, e = NumValues; i != e; ++i) { + getStreamer().EmitIntValue(FillExpr, NonZeroFillSize); + if (NonZeroFillSize < FillSize) + getStreamer().EmitIntValue(0, FillSize - NonZeroFillSize); + } } return false; @@ -3292,7 +3297,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { if (Qualifier == "req") Parameter.Required = true; - else if (Qualifier == "vararg" && !IsDarwin) + else if (Qualifier == "vararg") Parameter.Vararg = true; else return Error(QualLoc, Qualifier + " is not a valid parameter qualifier " @@ -3313,7 +3318,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { "'" + Parameter.Name + "' in macro '" + Name + "'"); } - Parameters.push_back(Parameter); + Parameters.push_back(std::move(Parameter)); if (getLexer().is(AsmToken::Comma)) Lex(); @@ -3365,7 +3370,7 @@ bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) { const char *BodyEnd = EndToken.getLoc().getPointer(); StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); checkForBadMacro(DirectiveLoc, Name, Body, Parameters); - defineMacro(Name, MCAsmMacro(Name, Body, Parameters)); + defineMacro(Name, MCAsmMacro(Name, Body, std::move(Parameters))); return false; } @@ -3471,6 +3476,26 @@ void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name, "found in body which will have no effect"); } +/// parseDirectiveExitMacro +/// ::= .exitm +bool AsmParser::parseDirectiveExitMacro(StringRef Directive) { + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in '" + Directive + "' directive"); + + if (!isInsideMacroInstantiation()) + return TokError("unexpected '" + Directive + "' in file, " + "no current macro definition"); + + // Exit all conditionals that are active in the current macro. + while (TheCondStack.size() != ActiveMacros.back()->CondStackDepth) { + TheCondState = TheCondStack.back(); + TheCondStack.pop_back(); + } + + handleMacroExit(); + return false; +} + /// parseDirectiveEndMacro /// ::= .endm /// ::= .endmacro @@ -4073,6 +4098,32 @@ bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) { return true; } +/// parseDirectiveWarning +/// ::= .warning [string] +bool AsmParser::parseDirectiveWarning(SMLoc L) { + if (!TheCondStack.empty()) { + if (TheCondStack.back().Ignore) { + eatToEndOfStatement(); + return false; + } + } + + StringRef Message = ".warning directive invoked in source file"; + if (Lexer.isNot(AsmToken::EndOfStatement)) { + if (Lexer.isNot(AsmToken::String)) { + TokError(".warning argument must be a string"); + eatToEndOfStatement(); + return true; + } + + Message = getTok().getStringContents(); + Lex(); + } + + Warning(L, Message); + return false; +} + /// parseDirectiveEndIf /// ::= .endif bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) { @@ -4200,11 +4251,13 @@ void AsmParser::initializeDirectiveKindMap() { DirectiveKindMap[".macros_on"] = DK_MACROS_ON; DirectiveKindMap[".macros_off"] = DK_MACROS_OFF; DirectiveKindMap[".macro"] = DK_MACRO; + DirectiveKindMap[".exitm"] = DK_EXITM; DirectiveKindMap[".endm"] = DK_ENDM; DirectiveKindMap[".endmacro"] = DK_ENDMACRO; DirectiveKindMap[".purgem"] = DK_PURGEM; DirectiveKindMap[".err"] = DK_ERR; DirectiveKindMap[".error"] = DK_ERROR; + DirectiveKindMap[".warning"] = DK_WARNING; } MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { @@ -4246,7 +4299,8 @@ MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) { StringRef Body = StringRef(BodyStart, BodyEnd - BodyStart); // We Are Anonymous. - MacroLikeBodies.push_back(MCAsmMacro(StringRef(), Body, None)); + MacroLikeBodies.push_back( + MCAsmMacro(StringRef(), Body, MCAsmMacroParameters())); return &MacroLikeBodies.back(); } @@ -4254,17 +4308,17 @@ void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc, raw_svector_ostream &OS) { OS << ".endr\n"; - MemoryBuffer *Instantiation = + std::unique_ptr Instantiation = MemoryBuffer::getMemBufferCopy(OS.str(), ""); // Create the macro instantiation object and add to the current macro // instantiation stack. MacroInstantiation *MI = new MacroInstantiation( - M, DirectiveLoc, CurBuffer, getTok().getLoc(), Instantiation); + DirectiveLoc, CurBuffer, getTok().getLoc(), TheCondStack.size()); ActiveMacros.push_back(MI); // Jump to the macro instantiation and prime the lexer. - CurBuffer = SrcMgr.AddNewSourceBuffer(MI->Instantiation, SMLoc()); + CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation), SMLoc()); Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer()); Lex(); } @@ -4490,7 +4544,7 @@ bool AsmParser::parseMSInlineAsm( unsigned OutputIdx = 0; while (getLexer().isNot(AsmToken::Eof)) { ParseStatementInfo Info(&AsmStrRewrites); - if (parseStatement(Info)) + if (parseStatement(Info, &SI)) return true; if (Info.ParseError) @@ -4616,6 +4670,9 @@ bool AsmParser::parseMSInlineAsm( case AOK_ImmPrefix: OS << "$$"; break; + case AOK_Label: + OS << Ctx.getAsmInfo()->getPrivateLabelPrefix() << AR.Label; + break; case AOK_Input: OS << '$' << InputIdx++; break; diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index 5ecf9e5..18bdb03 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -364,6 +364,10 @@ bool COFFAsmParser::ParseDirectiveSection(StringRef, SMLoc) { Flags |= COFF::IMAGE_SCN_LNK_COMDAT; + if (!getLexer().is(AsmToken::Identifier)) + return TokError("expected comdat type such as 'discard' or 'largest' " + "after protection bits"); + if (parseCOMDATType(Type)) return true; @@ -578,7 +582,7 @@ bool COFFAsmParser::ParseSEHDirectiveHandlerData(StringRef, SMLoc) { } bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { - unsigned Reg; + unsigned Reg = 0; if (ParseSEHRegisterNumber(Reg)) return true; @@ -591,7 +595,7 @@ bool COFFAsmParser::ParseSEHDirectivePushReg(StringRef, SMLoc L) { } bool COFFAsmParser::ParseSEHDirectiveSetFrame(StringRef, SMLoc L) { - unsigned Reg; + unsigned Reg = 0; int64_t Off; if (ParseSEHRegisterNumber(Reg)) return true; @@ -632,7 +636,7 @@ bool COFFAsmParser::ParseSEHDirectiveAllocStack(StringRef, SMLoc) { } bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { - unsigned Reg; + unsigned Reg = 0; int64_t Off; if (ParseSEHRegisterNumber(Reg)) return true; @@ -659,7 +663,7 @@ bool COFFAsmParser::ParseSEHDirectiveSaveReg(StringRef, SMLoc L) { // FIXME: This method is inherently x86-specific. It should really be in the // x86 backend. bool COFFAsmParser::ParseSEHDirectiveSaveXMM(StringRef, SMLoc L) { - unsigned Reg; + unsigned Reg = 0; int64_t Off; if (ParseSEHRegisterNumber(Reg)) return true; diff --git a/lib/MC/MCParser/DarwinAsmParser.cpp b/lib/MC/MCParser/DarwinAsmParser.cpp index b2a6785..3ea745e 100644 --- a/lib/MC/MCParser/DarwinAsmParser.cpp +++ b/lib/MC/MCParser/DarwinAsmParser.cpp @@ -638,13 +638,13 @@ bool DarwinAsmParser::parseDirectiveSecureLogUnique(StringRef, SMLoc IDLoc) { // Open the secure log file if we haven't already. raw_ostream *OS = getContext().getSecureLog(); if (!OS) { - std::string Err; - OS = new raw_fd_ostream(SecureLogFile, Err, + std::error_code EC; + OS = new raw_fd_ostream(SecureLogFile, EC, sys::fs::F_Append | sys::fs::F_Text); - if (!Err.empty()) { + if (EC) { delete OS; return Error(IDLoc, Twine("can't open secure log file: ") + - SecureLogFile + " (" + Err + ")"); + SecureLogFile + " (" + EC.message() + ")"); } getContext().setSecureLog(OS); } diff --git a/lib/MC/MCParser/ELFAsmParser.cpp b/lib/MC/MCParser/ELFAsmParser.cpp index 98b2b3b..e302004 100644 --- a/lib/MC/MCParser/ELFAsmParser.cpp +++ b/lib/MC/MCParser/ELFAsmParser.cpp @@ -555,7 +555,7 @@ EndStmt: std::make_pair(ELFSection, std::make_pair(nullptr, nullptr))); if (InsertResult.second) { if (getContext().getDwarfVersion() <= 2) - Error(loc, "DWARF2 only supports one section per compilation unit"); + Warning(loc, "DWARF2 only supports one section per compilation unit"); MCSymbol *SectionStartSymbol = getContext().CreateTempSymbol(); getStreamer().EmitLabel(SectionStartSymbol); diff --git a/lib/MC/MCParser/MCAsmLexer.cpp b/lib/MC/MCParser/MCAsmLexer.cpp index 530814b..795cc85 100644 --- a/lib/MC/MCParser/MCAsmLexer.cpp +++ b/lib/MC/MCParser/MCAsmLexer.cpp @@ -30,3 +30,7 @@ SMLoc AsmToken::getLoc() const { SMLoc AsmToken::getEndLoc() const { return SMLoc::getFromPointer(Str.data() + Str.size()); } + +SMRange AsmToken::getLocRange() const { + return SMRange(getLoc(), getEndLoc()); +} diff --git a/lib/MC/MCParser/MCAsmParser.cpp b/lib/MC/MCParser/MCAsmParser.cpp index e417aa9..290dcb2 100644 --- a/lib/MC/MCParser/MCAsmParser.cpp +++ b/lib/MC/MCParser/MCAsmParser.cpp @@ -29,7 +29,7 @@ void MCAsmParser::setTargetParser(MCTargetAsmParser &P) { TargetParser->Initialize(*this); } -const AsmToken &MCAsmParser::getTok() { +const AsmToken &MCAsmParser::getTok() const { return getLexer().getTok(); } diff --git a/lib/MC/MCRelocationInfo.cpp b/lib/MC/MCRelocationInfo.cpp deleted file mode 100644 index a00c009..0000000 --- a/lib/MC/MCRelocationInfo.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//==-- lib/MC/MCRelocationInfo.cpp -------------------------------*- C++ -*-==// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCRelocationInfo.h" -#include "llvm-c/Disassembler.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/TargetRegistry.h" - -using namespace llvm; - -MCRelocationInfo::MCRelocationInfo(MCContext &Ctx) - : Ctx(Ctx) { -} - -MCRelocationInfo::~MCRelocationInfo() { -} - -const MCExpr * -MCRelocationInfo::createExprForRelocation(object::RelocationRef Rel) { - return nullptr; -} - -const MCExpr * -MCRelocationInfo::createExprForCAPIVariantKind(const MCExpr *SubExpr, - unsigned VariantKind) { - if (VariantKind != LLVMDisassembler_VariantKind_None) - return nullptr; - return SubExpr; -} - -MCRelocationInfo *llvm::createMCRelocationInfo(StringRef TT, MCContext &Ctx) { - return new MCRelocationInfo(Ctx); -} diff --git a/lib/MC/MCSectionCOFF.cpp b/lib/MC/MCSectionCOFF.cpp index fc2bd36..e95845f 100644 --- a/lib/MC/MCSectionCOFF.cpp +++ b/lib/MC/MCSectionCOFF.cpp @@ -47,18 +47,22 @@ void MCSectionCOFF::PrintSwitchToSection(const MCAsmInfo &MAI, } OS << "\t.section\t" << getSectionName() << ",\""; - if (getKind().isText()) + if (getCharacteristics() & COFF::IMAGE_SCN_MEM_EXECUTE) OS << 'x'; - else if (getKind().isBSS()) - OS << 'b'; - if (getKind().isWriteable()) + if (getCharacteristics() & COFF::IMAGE_SCN_MEM_WRITE) OS << 'w'; - else + else if (getCharacteristics() & COFF::IMAGE_SCN_MEM_READ) OS << 'r'; - if (getCharacteristics() & COFF::IMAGE_SCN_MEM_DISCARDABLE) - OS << 'n'; + else + OS << 'y'; if (getCharacteristics() & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) OS << 'd'; + if (getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) + OS << 'b'; + if (getCharacteristics() & COFF::IMAGE_SCN_LNK_REMOVE) + OS << 'n'; + if (getCharacteristics() & COFF::IMAGE_SCN_MEM_SHARED) + OS << 's'; OS << '"'; if (getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { diff --git a/lib/MC/MCSectionELF.cpp b/lib/MC/MCSectionELF.cpp index 09eb3e7..a29bb97 100644 --- a/lib/MC/MCSectionELF.cpp +++ b/lib/MC/MCSectionELF.cpp @@ -19,8 +19,8 @@ using namespace llvm; MCSectionELF::~MCSectionELF() {} // anchor. -// ShouldOmitSectionDirective - Decides whether a '.section' directive -// should be printed before the section name +// Decides whether a '.section' directive +// should be printed before the section name. bool MCSectionELF::ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const { diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 46e80cc..f11ee66 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -48,37 +48,16 @@ MCStreamer::~MCStreamer() { } void MCStreamer::reset() { + DwarfFrameInfos.clear(); for (unsigned i = 0; i < getNumWinFrameInfos(); ++i) delete WinFrameInfos[i]; WinFrameInfos.clear(); CurrentWinFrameInfo = nullptr; + SymbolOrdering.clear(); SectionStack.clear(); SectionStack.push_back(std::pair()); } -const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, - const MCSymbol *A, - const MCSymbol *B) { - MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; - const MCExpr *ARef = - MCSymbolRefExpr::Create(A, Variant, Context); - const MCExpr *BRef = - MCSymbolRefExpr::Create(B, Variant, Context); - const MCExpr *AddrDelta = - MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context); - return AddrDelta; -} - -const MCExpr *MCStreamer::ForceExpAbs(const MCExpr* Expr) { - assert(!isa(Expr)); - if (Context.getAsmInfo()->hasAggressiveSymbolFolding()) - return Expr; - - MCSymbol *ABS = Context.CreateTempSymbol(); - EmitAssignment(ABS, Expr); - return MCSymbolRefExpr::Create(ABS, Context); -} - raw_ostream &MCStreamer::GetCommentOS() { // By default, discard comments. return nulls(); @@ -92,22 +71,10 @@ void MCStreamer::generateCompactUnwindEncodings(MCAsmBackend *MAB) { (MAB ? MAB->generateCompactUnwindEncoding(FI.Instructions) : 0); } -void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta, - const MCSymbol *Label, int PointerSize) { - // emit the sequence to set the address - EmitIntValue(dwarf::DW_LNS_extended_op, 1); - EmitULEB128IntValue(PointerSize + 1); - EmitIntValue(dwarf::DW_LNE_set_address, 1); - EmitSymbolValue(Label, PointerSize); - - // emit the sequence for the LineDelta (from 1) and a zero address delta. - MCDwarfLineAddr::Emit(this, LineDelta, 0); -} - /// EmitIntValue - Special case of EmitValue that avoids the client having to /// pass in a MCExpr for constant integers. void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size) { - assert(Size <= 8 && "Invalid size"); + assert(1 <= Size && Size <= 8 && "Invalid size"); assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) && "Invalid size"); char buf[8]; @@ -137,12 +104,6 @@ void MCStreamer::EmitSLEB128IntValue(int64_t Value) { EmitBytes(OSE.str()); } -void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size) { - const MCExpr *ABS = ForceExpAbs(Value); - EmitValue(ABS, Size); -} - - void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc) { EmitValueImpl(Value, Size, Loc); @@ -221,7 +182,7 @@ void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) { } -void MCStreamer::InitSections() { +void MCStreamer::InitSections(bool NoExecStack) { SwitchSection(getContext().getObjectFileInfo()->getTextSection()); } @@ -246,12 +207,6 @@ void MCStreamer::EmitLabel(MCSymbol *Symbol) { TS->emitLabel(Symbol); } -void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) { - EnsureValidDwarfFrame(); - MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); - CurFrame->CompactUnwindEncoding = CompactUnwindEncoding; -} - void MCStreamer::EmitCFISections(bool EH, bool Debug) { assert(EH || Debug); } @@ -265,6 +220,16 @@ void MCStreamer::EmitCFIStartProc(bool IsSimple) { Frame.IsSimple = IsSimple; EmitCFIStartProcImpl(Frame); + const MCAsmInfo* MAI = Context.getAsmInfo(); + if (MAI) { + for (const MCCFIInstruction& Inst : MAI->getInitialFrameState()) { + if (Inst.getOperation() == MCCFIInstruction::OpDefCfa || + Inst.getOperation() == MCCFIInstruction::OpDefCfaRegister) { + Frame.CurrentCfaRegister = Inst.getRegister(); + } + } + } + DwarfFrameInfos.push_back(Frame); } @@ -296,6 +261,7 @@ void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { MCCFIInstruction::createDefCfa(Label, Register, Offset); MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); + CurFrame->CurrentCfaRegister = static_cast(Register); } void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { @@ -320,6 +286,7 @@ void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { MCCFIInstruction::createDefCfaRegister(Label, Register); MCDwarfFrameInfo *CurFrame = getCurrentDwarfFrameInfo(); CurFrame->Instructions.push_back(Instruction); + CurFrame->CurrentCfaRegister = static_cast(Register); } void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { @@ -429,11 +396,11 @@ void MCStreamer::EnsureValidWinFrameInfo() { void MCStreamer::EmitWinCFIStartProc(const MCSymbol *Symbol) { if (CurrentWinFrameInfo && !CurrentWinFrameInfo->End) report_fatal_error("Starting a function before ending the previous one!"); - MCWinFrameInfo *Frame = new MCWinFrameInfo; - Frame->Begin = getContext().CreateTempSymbol(); - Frame->Function = Symbol; - EmitLabel(Frame->Begin); - WinFrameInfos.push_back(Frame); + + MCSymbol *StartProc = getContext().CreateTempSymbol(); + EmitLabel(StartProc); + + WinFrameInfos.push_back(new WinEH::FrameInfo(Symbol, StartProc)); CurrentWinFrameInfo = WinFrameInfos.back(); } @@ -441,18 +408,20 @@ void MCStreamer::EmitWinCFIEndProc() { EnsureValidWinFrameInfo(); if (CurrentWinFrameInfo->ChainedParent) report_fatal_error("Not all chained regions terminated!"); - CurrentWinFrameInfo->End = getContext().CreateTempSymbol(); - EmitLabel(CurrentWinFrameInfo->End); + + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + CurrentWinFrameInfo->End = Label; } void MCStreamer::EmitWinCFIStartChained() { EnsureValidWinFrameInfo(); - MCWinFrameInfo *Frame = new MCWinFrameInfo; - Frame->Begin = getContext().CreateTempSymbol(); - Frame->Function = CurrentWinFrameInfo->Function; - Frame->ChainedParent = CurrentWinFrameInfo; - EmitLabel(Frame->Begin); - WinFrameInfos.push_back(Frame); + + MCSymbol *StartProc = getContext().CreateTempSymbol(); + EmitLabel(StartProc); + + WinFrameInfos.push_back(new WinEH::FrameInfo(CurrentWinFrameInfo->Function, + StartProc, CurrentWinFrameInfo)); CurrentWinFrameInfo = WinFrameInfos.back(); } @@ -460,9 +429,13 @@ void MCStreamer::EmitWinCFIEndChained() { EnsureValidWinFrameInfo(); if (!CurrentWinFrameInfo->ChainedParent) report_fatal_error("End of a chained region outside a chained region!"); - CurrentWinFrameInfo->End = getContext().CreateTempSymbol(); - EmitLabel(CurrentWinFrameInfo->End); - CurrentWinFrameInfo = CurrentWinFrameInfo->ChainedParent; + + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + + CurrentWinFrameInfo->End = Label; + CurrentWinFrameInfo = + const_cast(CurrentWinFrameInfo->ChainedParent); } void MCStreamer::EmitWinEHHandler(const MCSymbol *Sym, bool Unwind, @@ -567,8 +540,11 @@ void MCStreamer::EmitWinCFIPushFrame(bool Code) { void MCStreamer::EmitWinCFIEndProlog() { EnsureValidWinFrameInfo(); - CurrentWinFrameInfo->PrologEnd = getContext().CreateTempSymbol(); - EmitLabel(CurrentWinFrameInfo->PrologEnd); + + MCSymbol *Label = getContext().CreateTempSymbol(); + EmitLabel(Label); + + CurrentWinFrameInfo->PrologEnd = Label; } void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { @@ -592,10 +568,6 @@ void MCStreamer::EmitRawText(const Twine &T) { } void MCStreamer::EmitWindowsUnwindTables() { - if (!getNumWinFrameInfos()) - return; - - MCWin64EHUnwindEmitter::Emit(*this); } void MCStreamer::Finish() { diff --git a/lib/MC/MCSubtargetInfo.cpp b/lib/MC/MCSubtargetInfo.cpp index 4424c91..b8e42bd 100644 --- a/lib/MC/MCSubtargetInfo.cpp +++ b/lib/MC/MCSubtargetInfo.cpp @@ -17,8 +17,6 @@ using namespace llvm; -MCSchedModel MCSchedModel::DefaultSchedModel; // For unknown processors. - /// InitMCProcessorInfo - Set or change the CPU (optionally supplemented /// with feature string). Recompute feature bits and scheduling model. void @@ -33,7 +31,7 @@ MCSubtargetInfo::InitCPUSchedModel(StringRef CPU) { if (!CPU.empty()) CPUSchedModel = getSchedModelForCPU(CPU); else - CPUSchedModel = &MCSchedModel::DefaultSchedModel; + CPUSchedModel = MCSchedModel::GetDefaultSchedModel(); } void @@ -78,7 +76,7 @@ uint64_t MCSubtargetInfo::ToggleFeature(StringRef FS) { } -const MCSchedModel * +MCSchedModel MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const { assert(ProcSchedModels && "Processor machine model not available!"); @@ -97,15 +95,15 @@ MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const { errs() << "'" << CPU << "' is not a recognized processor for this target" << " (ignoring processor)\n"; - return &MCSchedModel::DefaultSchedModel; + return MCSchedModel::GetDefaultSchedModel(); } assert(Found->Value && "Missing processor SchedModel value"); - return (const MCSchedModel *)Found->Value; + return *(const MCSchedModel *)Found->Value; } InstrItineraryData MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const { - const MCSchedModel *SchedModel = getSchedModelForCPU(CPU); + const MCSchedModel SchedModel = getSchedModelForCPU(CPU); return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths); } diff --git a/lib/MC/MCTargetOptions.cpp b/lib/MC/MCTargetOptions.cpp index efd724a..1258d9e 100644 --- a/lib/MC/MCTargetOptions.cpp +++ b/lib/MC/MCTargetOptions.cpp @@ -7,14 +7,19 @@ // //===----------------------------------------------------------------------===// +#include "llvm/ADT/StringRef.h" #include "llvm/MC/MCTargetOptions.h" namespace llvm { MCTargetOptions::MCTargetOptions() : SanitizeAddress(false), MCRelaxAll(false), MCNoExecStack(false), - MCSaveTempLabels(false), MCUseDwarfDirectory(false), - ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false), - DwarfVersion(0) {} + MCFatalWarnings(false), MCSaveTempLabels(false), + MCUseDwarfDirectory(false), ShowMCEncoding(false), ShowMCInst(false), + AsmVerbose(false), DwarfVersion(0), ABIName() {} + +StringRef MCTargetOptions::getABIName() const { + return ABIName; +} } // end namespace llvm diff --git a/lib/MC/MCWin64EH.cpp b/lib/MC/MCWin64EH.cpp index 95e1983..dfadb3c 100644 --- a/lib/MC/MCWin64EH.cpp +++ b/lib/MC/MCWin64EH.cpp @@ -53,10 +53,10 @@ static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCExpr *Diff = MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(LHS, Context), MCSymbolRefExpr::Create(RHS, Context), Context); - Streamer.EmitAbsValue(Diff, 1); + Streamer.EmitValue(Diff, 1); } -static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin, +static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst) { uint8_t b2; uint16_t w; @@ -136,7 +136,7 @@ static void EmitSymbolRefWithOfs(MCStreamer &streamer, } static void EmitRuntimeFunction(MCStreamer &streamer, - const MCWinFrameInfo *info) { + const WinEH::FrameInfo *info) { MCContext &context = streamer.getContext(); streamer.EmitValueToAlignment(4); @@ -147,14 +147,17 @@ static void EmitRuntimeFunction(MCStreamer &streamer, context), 4); } -static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info) { +static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) { // If this UNWIND_INFO already has a symbol, it's already been emitted. - if (info->Symbol) return; + if (info->Symbol) + return; MCContext &context = streamer.getContext(); + MCSymbol *Label = context.CreateTempSymbol(); + streamer.EmitValueToAlignment(4); - info->Symbol = context.CreateTempSymbol(); - streamer.EmitLabel(info->Symbol); + streamer.EmitLabel(Label); + info->Symbol = Label; // Upper 3 bits are the version number (currently 1). uint8_t flags = 0x01; @@ -215,65 +218,14 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWinFrameInfo *info) { } } -StringRef MCWin64EHUnwindEmitter::GetSectionSuffix(const MCSymbol *func) { - if (!func || !func->isInSection()) return ""; - const MCSection *section = &func->getSection(); - const MCSectionCOFF *COFFSection; - if ((COFFSection = dyn_cast(section))) { - StringRef name = COFFSection->getSectionName(); - size_t dollar = name.find('$'); - size_t dot = name.find('.', 1); - if (dollar == StringRef::npos && dot == StringRef::npos) - return ""; - if (dot == StringRef::npos) - return name.substr(dollar); - if (dollar == StringRef::npos || dot < dollar) - return name.substr(dot); - return name.substr(dollar); - } - return ""; -} - -static const MCSection *getWin64EHTableSection(StringRef suffix, - MCContext &context) { - if (suffix == "") - return context.getObjectFileInfo()->getXDataSection(); - - return context.getCOFFSection((".xdata"+suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getDataRel()); -} - -static const MCSection *getWin64EHFuncTableSection(StringRef suffix, - MCContext &context) { - if (suffix == "") - return context.getObjectFileInfo()->getPDataSection(); - return context.getCOFFSection((".pdata"+suffix).str(), - COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | - COFF::IMAGE_SCN_MEM_READ, - SectionKind::getDataRel()); -} - -void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer, - MCWinFrameInfo *info) { - // Switch sections (the static function above is meant to be called from - // here and from Emit(). - MCContext &context = streamer.getContext(); - const MCSection *xdataSect = - getWin64EHTableSection(GetSectionSuffix(info->Function), context); - streamer.SwitchSection(xdataSect); - - llvm::EmitUnwindInfo(streamer, info); -} - -void MCWin64EHUnwindEmitter::Emit(MCStreamer &Streamer) { +namespace Win64EH { +void UnwindEmitter::Emit(MCStreamer &Streamer) const { MCContext &Context = Streamer.getContext(); // Emit the unwind info structs first. for (const auto &CFI : Streamer.getWinFrameInfos()) { const MCSection *XData = - getWin64EHTableSection(GetSectionSuffix(CFI->Function), Context); + getXDataSection(CFI->Function, Context); Streamer.SwitchSection(XData); EmitUnwindInfo(Streamer, CFI); } @@ -281,11 +233,23 @@ void MCWin64EHUnwindEmitter::Emit(MCStreamer &Streamer) { // Now emit RUNTIME_FUNCTION entries. for (const auto &CFI : Streamer.getWinFrameInfos()) { const MCSection *PData = - getWin64EHFuncTableSection(GetSectionSuffix(CFI->Function), Context); + getPDataSection(CFI->Function, Context); Streamer.SwitchSection(PData); EmitRuntimeFunction(Streamer, CFI); } } +void UnwindEmitter::EmitUnwindInfo(MCStreamer &Streamer, + WinEH::FrameInfo *info) const { + // Switch sections (the static function above is meant to be called from + // here and from Emit(). + MCContext &context = Streamer.getContext(); + const MCSection *xdataSect = + getXDataSection(info->Function, context); + Streamer.SwitchSection(xdataSect); + + llvm::EmitUnwindInfo(Streamer, info); +} +} } // End of namespace llvm diff --git a/lib/MC/MCWinEH.cpp b/lib/MC/MCWinEH.cpp new file mode 100644 index 0000000..47eaf0f --- /dev/null +++ b/lib/MC/MCWinEH.cpp @@ -0,0 +1,77 @@ +//===- lib/MC/MCWinEH.cpp - Windows EH implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCObjectFileInfo.h" +#include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCWinEH.h" +#include "llvm/Support/COFF.h" + +namespace llvm { +namespace WinEH { + +/// We can't have one section for all .pdata or .xdata because the Microsoft +/// linker seems to want all code relocations to refer to the same object file +/// section. If the code described is comdat, create a new comdat section +/// associated with that comdat. If the code described is not in the main .text +/// section, make a new section for it. Otherwise use the main unwind info +/// section. +static const MCSection *getUnwindInfoSection( + StringRef SecName, const MCSectionCOFF *UnwindSec, const MCSymbol *Function, + MCContext &Context) { + if (Function && Function->isInSection()) { + // If Function is in a COMDAT, get or create an unwind info section in that + // COMDAT group. + const MCSectionCOFF *FunctionSection = + cast(&Function->getSection()); + if (FunctionSection->getCharacteristics() & COFF::IMAGE_SCN_LNK_COMDAT) { + return Context.getAssociativeCOFFSection( + UnwindSec, FunctionSection->getCOMDATSymbol()); + } + + // If Function is in a section other than .text, create a new .pdata section. + // Otherwise use the plain .pdata section. + if (const auto *Section = dyn_cast(FunctionSection)) { + StringRef CodeSecName = Section->getSectionName(); + if (CodeSecName == ".text") + return UnwindSec; + + if (CodeSecName.startswith(".text$")) + CodeSecName = CodeSecName.substr(6); + + return Context.getCOFFSection( + (SecName + Twine('$') + CodeSecName).str(), + COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ, + SectionKind::getDataRel()); + } + } + + return UnwindSec; + +} + +const MCSection *UnwindEmitter::getPDataSection(const MCSymbol *Function, + MCContext &Context) { + const MCSectionCOFF *PData = + cast(Context.getObjectFileInfo()->getPDataSection()); + return getUnwindInfoSection(".pdata", PData, Function, Context); +} + +const MCSection *UnwindEmitter::getXDataSection(const MCSymbol *Function, + MCContext &Context) { + const MCSectionCOFF *XData = + cast(Context.getObjectFileInfo()->getXDataSection()); + return getUnwindInfoSection(".xdata", XData, Function, Context); +} + +} +} + diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp index 5214398..588d424 100644 --- a/lib/MC/MachObjectWriter.cpp +++ b/lib/MC/MachObjectWriter.cpp @@ -41,7 +41,7 @@ void MachObjectWriter::reset() { bool MachObjectWriter:: doesSymbolRequireExternRelocation(const MCSymbolData *SD) { // Undefined symbols are always extern. - if (SD->Symbol->isUndefined()) + if (SD->getSymbol().isUndefined()) return true; // References to weak definitions require external relocation entries; the @@ -84,7 +84,7 @@ uint64_t MachObjectWriter::getSymbolAddress(const MCSymbolData* SD, MCValue Target; - if (!S.getVariableValue()->EvaluateAsRelocatable(Target, &Layout)) + if (!S.getVariableValue()->EvaluateAsRelocatable(Target, &Layout, nullptr)) report_fatal_error("unable to evaluate offset for variable '" + S.getName() + "'"); @@ -418,7 +418,7 @@ void MachObjectWriter::WriteLinkeditLoadCommand(uint32_t Type, static unsigned ComputeLinkerOptionsLoadCommandSize( const std::vector &Options, bool is64Bit) { - unsigned Size = sizeof(MachO::linker_options_command); + unsigned Size = sizeof(MachO::linker_option_command); for (unsigned i = 0, e = Options.size(); i != e; ++i) Size += Options[i].size() + 1; return RoundUpToAlignment(Size, is64Bit ? 8 : 4); @@ -431,10 +431,10 @@ void MachObjectWriter::WriteLinkerOptionsLoadCommand( uint64_t Start = OS.tell(); (void) Start; - Write32(MachO::LC_LINKER_OPTIONS); + Write32(MachO::LC_LINKER_OPTION); Write32(Size); Write32(Options.size()); - uint64_t BytesWritten = sizeof(MachO::linker_options_command); + uint64_t BytesWritten = sizeof(MachO::linker_option_command); for (unsigned i = 0, e = Options.size(); i != e; ++i) { // Write each string, including the null byte. const std::string &Option = Options[i]; @@ -448,14 +448,11 @@ void MachObjectWriter::WriteLinkerOptionsLoadCommand( assert(OS.tell() - Start == Size); } - -void MachObjectWriter::RecordRelocation(const MCAssembler &Asm, +void MachObjectWriter::RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) { + const MCFixup &Fixup, MCValue Target, + bool &IsPCRel, uint64_t &FixedValue) { TargetObjectWriter->RecordRelocation(this, Asm, Layout, Fragment, Fixup, Target, FixedValue); } @@ -525,15 +522,10 @@ void MachObjectWriter::BindIndirectSymbols(MCAssembler &Asm) { } /// ComputeSymbolTable - Compute the symbol table data -/// -/// \param StringTable [out] - The string table data. -/// \param StringIndexMap [out] - Map from symbol names to offsets in the -/// string table. -void MachObjectWriter:: -ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, - std::vector &LocalSymbolData, - std::vector &ExternalSymbolData, - std::vector &UndefinedSymbolData) { +void MachObjectWriter::ComputeSymbolTable( + MCAssembler &Asm, std::vector &LocalSymbolData, + std::vector &ExternalSymbolData, + std::vector &UndefinedSymbolData) { // Build section lookup table. DenseMap SectionIndexMap; unsigned Index = 1; @@ -542,37 +534,34 @@ ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, SectionIndexMap[&it->getSection()] = Index; assert(Index <= 256 && "Too many sections!"); - // Index 0 is always the empty string. - StringMap StringIndexMap; - StringTable += '\x00'; + // Build the string table. + for (MCSymbolData &SD : Asm.symbols()) { + const MCSymbol &Symbol = SD.getSymbol(); + if (!Asm.isSymbolLinkerVisible(Symbol)) + continue; + + StringTable.add(Symbol.getName()); + } + StringTable.finalize(StringTableBuilder::MachO); - // Build the symbol arrays and the string table, but only for non-local - // symbols. + // Build the symbol arrays but only for non-local symbols. // - // The particular order that we collect the symbols and create the string - // table, then sort the symbols is chosen to match 'as'. Even though it - // doesn't matter for correctness, this is important for letting us diff .o - // files. + // The particular order that we collect and then sort the symbols is chosen to + // match 'as'. Even though it doesn't matter for correctness, this is + // important for letting us diff .o files. for (MCSymbolData &SD : Asm.symbols()) { const MCSymbol &Symbol = SD.getSymbol(); // Ignore non-linker visible symbols. - if (!Asm.isSymbolLinkerVisible(SD.getSymbol())) + if (!Asm.isSymbolLinkerVisible(Symbol)) continue; if (!SD.isExternal() && !Symbol.isUndefined()) continue; - uint64_t &Entry = StringIndexMap[Symbol.getName()]; - if (!Entry) { - Entry = StringTable.size(); - StringTable += Symbol.getName(); - StringTable += '\x00'; - } - MachSymbolData MSD; MSD.SymbolData = &SD; - MSD.StringIndex = Entry; + MSD.StringIndex = StringTable.getOffset(Symbol.getName()); if (Symbol.isUndefined()) { MSD.SectionIndex = 0; @@ -592,22 +581,15 @@ ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, const MCSymbol &Symbol = SD.getSymbol(); // Ignore non-linker visible symbols. - if (!Asm.isSymbolLinkerVisible(SD.getSymbol())) + if (!Asm.isSymbolLinkerVisible(Symbol)) continue; if (SD.isExternal() || Symbol.isUndefined()) continue; - uint64_t &Entry = StringIndexMap[Symbol.getName()]; - if (!Entry) { - Entry = StringTable.size(); - StringTable += Symbol.getName(); - StringTable += '\x00'; - } - MachSymbolData MSD; MSD.SymbolData = &SD; - MSD.StringIndex = Entry; + MSD.StringIndex = StringTable.getOffset(Symbol.getName()); if (Symbol.isAbsolute()) { MSD.SectionIndex = 0; @@ -632,9 +614,21 @@ ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable, for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i) UndefinedSymbolData[i].SymbolData->setIndex(Index++); - // The string table is padded to a multiple of 4. - while (StringTable.size() % 4) - StringTable += '\x00'; + for (const MCSectionData &SD : Asm) { + std::vector &Relocs = Relocations[&SD]; + for (RelAndSymbol &Rel : Relocs) { + if (!Rel.Sym) + continue; + + // Set the Index and the IsExtern bit. + unsigned Index = Rel.Sym->getIndex(); + assert(isInt<24>(Index)); + if (IsLittleEndian) + Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (-1 << 24)) | Index | (1 << 27); + else + Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4); + } + } } void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm, @@ -664,7 +658,7 @@ void MachObjectWriter::markAbsoluteVariableSymbols(MCAssembler &Asm, // and neither symbol is external, mark the variable as absolute. const MCExpr *Expr = SD.getSymbol().getVariableValue(); MCValue Value; - if (Expr->EvaluateAsRelocatable(Value, &Layout)) { + if (Expr->EvaluateAsRelocatable(Value, &Layout, nullptr)) { if (Value.getSymA() && Value.getSymB()) const_cast(&SD.getSymbol())->setAbsolute(); } @@ -681,10 +675,6 @@ void MachObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, // Mark symbol difference expressions in variables (from .set or = directives) // as absolute. markAbsoluteVariableSymbols(Asm, Layout); - - // Compute symbol table information and bind symbol indices. - ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData, - UndefinedSymbolData); } bool MachObjectWriter:: @@ -745,6 +735,10 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, return false; } + // If they are not in the same section, we can't compute the diff. + if (&SecA != &SecB) + return false; + const MCFragment *FA = Asm.getSymbolData(SA).getFragment(); // Bail if the symbol has no fragment. @@ -752,12 +746,7 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, return false; A_Base = FA->getAtom(); - if (!A_Base) - return false; - B_Base = FB.getAtom(); - if (!B_Base) - return false; // If the atoms are the same, they are guaranteed to have the same address. if (A_Base == B_Base) @@ -769,6 +758,10 @@ IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, void MachObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { + // Compute symbol table information and bind symbol indices. + ComputeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData, + UndefinedSymbolData); + unsigned NumSections = Asm.size(); const MCAssembler::VersionMinInfoType &VersionInfo = Layout.getAssembler().getVersionMinInfo(); @@ -859,7 +852,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize; for (MCAssembler::const_iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it) { - std::vector &Relocs = Relocations[it]; + std::vector &Relocs = Relocations[it]; unsigned NumRelocs = Relocs.size(); uint64_t SectionStart = SectionDataStart + getSectionAddress(it); WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs); @@ -922,7 +915,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, sizeof(MachO::nlist_64) : sizeof(MachO::nlist)); WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols, - StringTableOffset, StringTable.size()); + StringTableOffset, StringTable.data().size()); WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols, FirstExternalSymbol, NumExternalSymbols, @@ -953,10 +946,10 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, ie = Asm.end(); it != ie; ++it) { // Write the section relocation entries, in reverse order to match 'as' // (approximately, the exact algorithm is more complicated than this). - std::vector &Relocs = Relocations[it]; + std::vector &Relocs = Relocations[it]; for (unsigned i = 0, e = Relocs.size(); i != e; ++i) { - Write32(Relocs[e - i - 1].r_word0); - Write32(Relocs[e - i - 1].r_word1); + Write32(Relocs[e - i - 1].MRE.r_word0); + Write32(Relocs[e - i - 1].MRE.r_word1); } } @@ -1028,7 +1021,7 @@ void MachObjectWriter::WriteObject(MCAssembler &Asm, WriteNlist(UndefinedSymbolData[i], Layout); // Write the string table. - OS << StringTable.str(); + OS << StringTable.data(); } } diff --git a/lib/MC/Makefile b/lib/MC/Makefile index a10f17e..bf8b7c0 100644 --- a/lib/MC/Makefile +++ b/lib/MC/Makefile @@ -10,7 +10,7 @@ LEVEL = ../.. LIBRARYNAME = LLVMMC BUILD_ARCHIVE := 1 -PARALLEL_DIRS := MCAnalysis MCParser MCDisassembler +PARALLEL_DIRS := MCParser MCDisassembler include $(LEVEL)/Makefile.common diff --git a/lib/MC/StringTableBuilder.cpp b/lib/MC/StringTableBuilder.cpp index db58ece..9de9363 100644 --- a/lib/MC/StringTableBuilder.cpp +++ b/lib/MC/StringTableBuilder.cpp @@ -9,6 +9,8 @@ #include "llvm/MC/StringTableBuilder.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/COFF.h" +#include "llvm/Support/Endian.h" using namespace llvm; @@ -25,19 +27,32 @@ static bool compareBySuffix(StringRef a, StringRef b) { return sizeA > sizeB; } -void StringTableBuilder::finalize() { +void StringTableBuilder::finalize(Kind kind) { SmallVector Strings; + Strings.reserve(StringIndexMap.size()); + for (auto i = StringIndexMap.begin(), e = StringIndexMap.end(); i != e; ++i) Strings.push_back(i->getKey()); std::sort(Strings.begin(), Strings.end(), compareBySuffix); - // FIXME: Starting with a null byte is ELF specific. Generalize this so we - // can use the class with other object formats. - StringTable += '\x00'; + switch (kind) { + case ELF: + case MachO: + // Start the table with a NUL byte. + StringTable += '\x00'; + break; + case WinCOFF: + // Make room to write the table size later. + StringTable.append(4, '\x00'); + break; + } StringRef Previous; for (StringRef s : Strings) { + if (kind == WinCOFF) + assert(s.size() > COFF::NameSize && "Short string in COFF string table!"); + if (Previous.endswith(s)) { StringIndexMap[s] = StringTable.size() - 1 - s.size(); continue; @@ -48,4 +63,26 @@ void StringTableBuilder::finalize() { StringTable += '\x00'; Previous = s; } + + switch (kind) { + case ELF: + break; + case MachO: + // Pad to multiple of 4. + while (StringTable.size() % 4) + StringTable += '\x00'; + break; + case WinCOFF: + // Write the table size in the first word. + assert(StringTable.size() <= std::numeric_limits::max()); + uint32_t size = static_cast(StringTable.size()); + support::endian::write( + StringTable.data(), size); + break; + } +} + +void StringTableBuilder::clear() { + StringTable.clear(); + StringIndexMap.clear(); } diff --git a/lib/MC/SubtargetFeature.cpp b/lib/MC/SubtargetFeature.cpp index 27525c7..587be54 100644 --- a/lib/MC/SubtargetFeature.cpp +++ b/lib/MC/SubtargetFeature.cpp @@ -27,7 +27,7 @@ using namespace llvm; /// hasFlag - Determine if a feature has a flag; '+' or '-' /// -static inline bool hasFlag(const StringRef Feature) { +static inline bool hasFlag(StringRef Feature) { assert(!Feature.empty() && "Empty string"); // Get first character char Ch = Feature[0]; @@ -37,13 +37,13 @@ static inline bool hasFlag(const StringRef Feature) { /// StripFlag - Return string stripped of flag. /// -static inline std::string StripFlag(const StringRef Feature) { +static inline std::string StripFlag(StringRef Feature) { return hasFlag(Feature) ? Feature.substr(1) : Feature; } /// isEnabled - Return true if enable flag; '+'. /// -static inline bool isEnabled(const StringRef Feature) { +static inline bool isEnabled(StringRef Feature) { assert(!Feature.empty() && "Empty string"); // Get first character char Ch = Feature[0]; @@ -53,8 +53,8 @@ static inline bool isEnabled(const StringRef Feature) { /// Split - Splits a string of comma separated items in to a vector of strings. /// -static void Split(std::vector &V, const StringRef S) { - SmallVector Tmp; +static void Split(std::vector &V, StringRef S) { + SmallVector Tmp; S.split(Tmp, ",", -1, false /* KeepEmpty */); V.assign(Tmp.begin(), Tmp.end()); } @@ -81,7 +81,7 @@ static std::string Join(const std::vector &V) { } /// Adding features. -void SubtargetFeatures::AddFeature(const StringRef String) { +void SubtargetFeatures::AddFeature(StringRef String) { // Don't add empty features or features we already have. if (!String.empty()) // Convert to lowercase, prepend flag if we don't already have a flag. @@ -136,7 +136,7 @@ static void Help(ArrayRef CPUTable, // SubtargetFeatures Implementation //===----------------------------------------------------------------------===// -SubtargetFeatures::SubtargetFeatures(const StringRef Initial) { +SubtargetFeatures::SubtargetFeatures(StringRef Initial) { // Break up string into separate features Split(Features, Initial); } @@ -181,7 +181,7 @@ void ClearImpliedBits(uint64_t &Bits, const SubtargetFeatureKV *FeatureEntry, /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. uint64_t -SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature, +SubtargetFeatures::ToggleFeature(uint64_t Bits, StringRef Feature, ArrayRef FeatureTable) { // Find feature in table. @@ -213,7 +213,7 @@ SubtargetFeatures::ToggleFeature(uint64_t Bits, const StringRef Feature, /// getFeatureBits - Get feature bits a CPU. /// uint64_t -SubtargetFeatures::getFeatureBits(const StringRef CPU, +SubtargetFeatures::getFeatureBits(StringRef CPU, ArrayRef CPUTable, ArrayRef FeatureTable) { diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 824895b..d8729bd 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -13,9 +13,9 @@ #include "llvm/MC/MCWinCOFFObjectWriter.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" @@ -26,8 +26,10 @@ #include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" +#include "llvm/MC/StringTableBuilder.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TimeValue.h" #include @@ -71,7 +73,6 @@ public: MCSymbolData const *MCData; COFFSymbol(StringRef name); - size_t size() const; void set_name_offset(uint32_t Offset); bool should_keep() const; @@ -102,20 +103,6 @@ public: static size_t size(); }; -// This class holds the COFF string table. -class StringTable { - typedef StringMap map; - map Map; - - void update_length(); -public: - std::vector Data; - - StringTable(); - size_t size() const; - size_t insert(StringRef String); -}; - class WinCOFFObjectWriter : public MCObjectWriter { public: @@ -131,13 +118,26 @@ public: COFF::header Header; sections Sections; symbols Symbols; - StringTable Strings; + StringTableBuilder Strings; // Maps used during object file creation. section_map SectionMap; symbol_map SymbolMap; + bool UseBigObj; + WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS); + + void reset() override { + memset(&Header, 0, sizeof(Header)); + Header.Machine = TargetObjectWriter->getMachine(); + Sections.clear(); + Symbols.clear(); + Strings.clear(); + SectionMap.clear(); + SymbolMap.clear(); + MCObjectWriter::reset(); + } COFFSymbol *createSymbol(StringRef Name); COFFSymbol *GetOrCreateCOFFSymbol(const MCSymbol * Symbol); @@ -150,8 +150,8 @@ public: void DefineSymbol(MCSymbolData const &SymbolData, MCAssembler &Assembler, const MCAsmLayout &Layout); - void MakeSymbolReal(COFFSymbol &S, size_t Index); - void MakeSectionReal(COFFSection &S, size_t Number); + void SetSymbolName(COFFSymbol &S); + void SetSectionName(COFFSection &S); bool ExportSymbol(const MCSymbol &Symbol, MCAssembler &Asm); @@ -170,7 +170,12 @@ public: void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; - void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, + bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCFragment &FB, bool InSet, + bool IsPCRel) const override; + + void RecordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) override; @@ -179,12 +184,9 @@ public: }; } -static inline void write_uint32_le(void *Data, uint32_t const &Value) { - uint8_t *Ptr = reinterpret_cast(Data); - Ptr[0] = (Value & 0x000000FF) >> 0; - Ptr[1] = (Value & 0x0000FF00) >> 8; - Ptr[2] = (Value & 0x00FF0000) >> 16; - Ptr[3] = (Value & 0xFF000000) >> 24; +static inline void write_uint32_le(void *Data, uint32_t Value) { + support::endian::write(Data, + Value); } //------------------------------------------------------------------------------ @@ -199,10 +201,6 @@ COFFSymbol::COFFSymbol(StringRef name) memset(&Data, 0, sizeof(Data)); } -size_t COFFSymbol::size() const { - return COFF::SymbolSize + (Data.NumberOfAuxSymbols * COFF::SymbolSize); -} - // In the case that the name does not fit within 8 bytes, the offset // into the string table is stored in the last 4 bytes instead, leaving // the first 4 bytes as 0. @@ -254,55 +252,11 @@ size_t COFFSection::size() { } //------------------------------------------------------------------------------ -// StringTable class implementation - -/// Write the length of the string table into Data. -/// The length of the string table includes uint32 length header. -void StringTable::update_length() { - write_uint32_le(&Data.front(), Data.size()); -} - -StringTable::StringTable() { - // The string table data begins with the length of the entire string table - // including the length header. Allocate space for this header. - Data.resize(4); - update_length(); -} - -size_t StringTable::size() const { - return Data.size(); -} - -/// Add String to the table iff it is not already there. -/// @returns the index into the string table where the string is now located. -size_t StringTable::insert(StringRef String) { - map::iterator i = Map.find(String); - - if (i != Map.end()) - return i->second; - - size_t Offset = Data.size(); - - // Insert string data into string table. - Data.insert(Data.end(), String.begin(), String.end()); - Data.push_back('\0'); - - // Put a reference to it in the map. - Map[String] = Offset; - - // Update the internal length field. - update_length(); - - return Offset; -} - -//------------------------------------------------------------------------------ // WinCOFFObjectWriter class implementation WinCOFFObjectWriter::WinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_ostream &OS) - : MCObjectWriter(OS, true) - , TargetObjectWriter(MOTW) { + : MCObjectWriter(OS, true), TargetObjectWriter(MOTW) { memset(&Header, 0, sizeof(Header)); Header.Machine = TargetObjectWriter->getMachine(); @@ -312,12 +266,12 @@ COFFSymbol *WinCOFFObjectWriter::createSymbol(StringRef Name) { return createCOFFEntity(Name, Symbols); } -COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol * Symbol){ +COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(const MCSymbol *Symbol) { symbol_map::iterator i = SymbolMap.find(Symbol); if (i != SymbolMap.end()) return i->second; - COFFSymbol *RetSymbol - = createCOFFEntity(Symbol->getName(), Symbols); + COFFSymbol *RetSymbol = + createCOFFEntity(Symbol->getName(), Symbols); SymbolMap[Symbol] = RetSymbol; return RetSymbol; } @@ -469,9 +423,9 @@ void WinCOFFObjectWriter::DefineSymbol(MCSymbolData const &SymbolData, coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE; } else { const MCSymbolData &BaseData = Assembler.getSymbolData(*Base); - if (BaseData.Fragment) { + if (BaseData.getFragment()) { COFFSection *Sec = - SectionMap[&BaseData.Fragment->getParent()->getSection()]; + SectionMap[&BaseData.getFragment()->getParent()->getSection()]; if (coff_symbol->Section && coff_symbol->Section != Sec) report_fatal_error("conflicting sections for symbol"); @@ -511,11 +465,9 @@ static void encodeBase64StringEntry(char* Buffer, uint64_t Value) { } } -/// making a section real involves assigned it a number and putting -/// name into the string table if needed -void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) { +void WinCOFFObjectWriter::SetSectionName(COFFSection &S) { if (S.Name.size() > COFF::NameSize) { - uint64_t StringTableEntry = Strings.insert(S.Name.c_str()); + uint64_t StringTableEntry = Strings.getOffset(S.Name); if (StringTableEntry <= Max6DecimalOffset) { std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry)); @@ -533,20 +485,13 @@ void WinCOFFObjectWriter::MakeSectionReal(COFFSection &S, size_t Number) { } } else std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size()); - - S.Number = Number; - S.Symbol->Data.SectionNumber = S.Number; - S.Symbol->Aux[0].Aux.SectionDefinition.Number = S.Number; } -void WinCOFFObjectWriter::MakeSymbolReal(COFFSymbol &S, size_t Index) { - if (S.Name.size() > COFF::NameSize) { - size_t StringTableEntry = Strings.insert(S.Name.c_str()); - - S.set_name_offset(StringTableEntry); - } else +void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) { + if (S.Name.size() > COFF::NameSize) + S.set_name_offset(Strings.getOffset(S.Name)); + else std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size()); - S.Index = Index; } bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol, @@ -578,19 +523,39 @@ bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) { // entity writing methods void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) { - WriteLE16(Header.Machine); - WriteLE16(Header.NumberOfSections); - WriteLE32(Header.TimeDateStamp); - WriteLE32(Header.PointerToSymbolTable); - WriteLE32(Header.NumberOfSymbols); - WriteLE16(Header.SizeOfOptionalHeader); - WriteLE16(Header.Characteristics); + if (UseBigObj) { + WriteLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN); + WriteLE16(0xFFFF); + WriteLE16(COFF::BigObjHeader::MinBigObjectVersion); + WriteLE16(Header.Machine); + WriteLE32(Header.TimeDateStamp); + for (uint8_t MagicChar : COFF::BigObjMagic) + Write8(MagicChar); + WriteLE32(0); + WriteLE32(0); + WriteLE32(0); + WriteLE32(0); + WriteLE32(Header.NumberOfSections); + WriteLE32(Header.PointerToSymbolTable); + WriteLE32(Header.NumberOfSymbols); + } else { + WriteLE16(Header.Machine); + WriteLE16(static_cast(Header.NumberOfSections)); + WriteLE32(Header.TimeDateStamp); + WriteLE32(Header.PointerToSymbolTable); + WriteLE32(Header.NumberOfSymbols); + WriteLE16(Header.SizeOfOptionalHeader); + WriteLE16(Header.Characteristics); + } } void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) { WriteBytes(StringRef(S.Data.Name, COFF::NameSize)); WriteLE32(S.Data.Value); - WriteLE16(S.Data.SectionNumber); + if (UseBigObj) + WriteLE32(S.Data.SectionNumber); + else + WriteLE16(static_cast(S.Data.SectionNumber)); WriteLE16(S.Data.Type); Write8(S.Data.StorageClass); Write8(S.Data.NumberOfAuxSymbols); @@ -608,6 +573,8 @@ void WinCOFFObjectWriter::WriteAuxiliarySymbols( WriteLE32(i->Aux.FunctionDefinition.PointerToLinenumber); WriteLE32(i->Aux.FunctionDefinition.PointerToNextFunction); WriteZeros(sizeof(i->Aux.FunctionDefinition.unused)); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATbfAndefSymbol: WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused1)); @@ -615,24 +582,32 @@ void WinCOFFObjectWriter::WriteAuxiliarySymbols( WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused2)); WriteLE32(i->Aux.bfAndefSymbol.PointerToNextFunction); WriteZeros(sizeof(i->Aux.bfAndefSymbol.unused3)); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATWeakExternal: WriteLE32(i->Aux.WeakExternal.TagIndex); WriteLE32(i->Aux.WeakExternal.Characteristics); WriteZeros(sizeof(i->Aux.WeakExternal.unused)); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; case ATFile: - WriteBytes(StringRef(reinterpret_cast(i->Aux.File.FileName), - sizeof(i->Aux.File.FileName))); + WriteBytes( + StringRef(reinterpret_cast(&i->Aux), + UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size)); break; case ATSectionDefinition: WriteLE32(i->Aux.SectionDefinition.Length); WriteLE16(i->Aux.SectionDefinition.NumberOfRelocations); WriteLE16(i->Aux.SectionDefinition.NumberOfLinenumbers); WriteLE32(i->Aux.SectionDefinition.CheckSum); - WriteLE16(i->Aux.SectionDefinition.Number); + WriteLE16(static_cast(i->Aux.SectionDefinition.Number)); Write8(i->Aux.SectionDefinition.Selection); WriteZeros(sizeof(i->Aux.SectionDefinition.unused)); + WriteLE16(static_cast(i->Aux.SectionDefinition.Number >> 16)); + if (UseBigObj) + WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size); break; } } @@ -665,38 +640,7 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) { // "Define" each section & symbol. This creates section & symbol // entries in the staging area. - - static_assert(sizeof(((COFF::AuxiliaryFile *)nullptr)->FileName) == COFF::SymbolSize, - "size mismatch for COFF::AuxiliaryFile::FileName"); - for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end(); - FI != FE; ++FI) { - // round up to calculate the number of auxiliary symbols required - unsigned Count = (FI->size() + COFF::SymbolSize - 1) / COFF::SymbolSize; - - COFFSymbol *file = createSymbol(".file"); - file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG; - file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; - file->Aux.resize(Count); - - unsigned Offset = 0; - unsigned Length = FI->size(); - for (auto & Aux : file->Aux) { - Aux.AuxType = ATFile; - - if (Length > COFF::SymbolSize) { - memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, COFF::SymbolSize); - Length = Length - COFF::SymbolSize; - } else { - memcpy(Aux.Aux.File.FileName, FI->c_str() + Offset, Length); - memset(&Aux.Aux.File.FileName[Length], 0, COFF::SymbolSize - Length); - Length = 0; - } - - Offset = Offset + COFF::SymbolSize; - } - } - - for (const auto & Section : Asm) + for (const auto &Section : Asm) DefineSection(Section); for (MCSymbolData &SD : Asm.symbols()) @@ -704,13 +648,22 @@ void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm, DefineSymbol(SD, Asm, Layout); } -void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, - const MCAsmLayout &Layout, - const MCFragment *Fragment, - const MCFixup &Fixup, - MCValue Target, - bool &IsPCRel, - uint64_t &FixedValue) { +bool WinCOFFObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl( + const MCAssembler &Asm, const MCSymbolData &DataA, const MCFragment &FB, + bool InSet, bool IsPCRel) const { + // MS LINK expects to be able to replace all references to a function with a + // thunk to implement their /INCREMENTAL feature. Make sure we don't optimize + // away any relocations to functions. + if ((((DataA.getFlags() & COFF::SF_TypeMask) >> COFF::SF_TypeShift) >> + COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION) + return false; + return MCObjectWriter::IsSymbolRefDifferenceFullyResolvedImpl(Asm, DataA, FB, + InSet, IsPCRel); +} + +void WinCOFFObjectWriter::RecordRelocation( + MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, + const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) { assert(Target.getSymA() && "Relocation must reference a symbol!"); const MCSymbol &Symbol = Target.getSymA()->getSymbol(); @@ -755,7 +708,7 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, // Offset of the symbol in the section int64_t a = Layout.getSymbolOffset(&B_SD); - // Ofeset of the relocation in the section + // Offset of the relocation in the section int64_t b = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); FixedValue = b - a; @@ -776,8 +729,8 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, // Turn relocations for temporary symbols into section relocations. if (coff_symbol->MCData->getSymbol().isTemporary() || CrossSection) { Reloc.Symb = coff_symbol->Section->Symbol; - FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->Fragment) - + coff_symbol->MCData->getOffset(); + FixedValue += Layout.getFragmentOffset(coff_symbol->MCData->getFragment()) + + coff_symbol->MCData->getOffset(); } else Reloc.Symb = coff_symbol; @@ -839,26 +792,67 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) { + size_t SectionsSize = Sections.size(); + if (SectionsSize > static_cast(INT32_MAX)) + report_fatal_error( + "PE COFF object files can't have more than 2147483647 sections"); + // Assign symbol and section indexes and offsets. - Header.NumberOfSections = 0; + int32_t NumberOfSections = static_cast(SectionsSize); + + UseBigObj = NumberOfSections > COFF::MaxNumberOfSections16; + + DenseMap SectionIndices( + NextPowerOf2(NumberOfSections)); - DenseMap SectionIndices; - for (auto & Section : Sections) { - size_t Number = ++Header.NumberOfSections; + // Assign section numbers. + size_t Number = 1; + for (const auto &Section : Sections) { SectionIndices[Section.get()] = Number; - MakeSectionReal(*Section, Number); + Section->Number = Number; + Section->Symbol->Data.SectionNumber = Number; + Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Number; + ++Number; } + Header.NumberOfSections = NumberOfSections; Header.NumberOfSymbols = 0; - for (auto & Symbol : Symbols) { + for (auto FI = Asm.file_names_begin(), FE = Asm.file_names_end(); + FI != FE; ++FI) { + // round up to calculate the number of auxiliary symbols required + unsigned SymbolSize = UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size; + unsigned Count = (FI->size() + SymbolSize - 1) / SymbolSize; + + COFFSymbol *file = createSymbol(".file"); + file->Data.SectionNumber = COFF::IMAGE_SYM_DEBUG; + file->Data.StorageClass = COFF::IMAGE_SYM_CLASS_FILE; + file->Aux.resize(Count); + + unsigned Offset = 0; + unsigned Length = FI->size(); + for (auto &Aux : file->Aux) { + Aux.AuxType = ATFile; + + if (Length > SymbolSize) { + memcpy(&Aux.Aux, FI->c_str() + Offset, SymbolSize); + Length = Length - SymbolSize; + } else { + memcpy(&Aux.Aux, FI->c_str() + Offset, Length); + memset((char *)&Aux.Aux + Length, 0, SymbolSize - Length); + break; + } + + Offset += SymbolSize; + } + } + + for (auto &Symbol : Symbols) { // Update section number & offset for symbols that have them. if (Symbol->Section) Symbol->Data.SectionNumber = Symbol->Section->Number; - if (Symbol->should_keep()) { - MakeSymbolReal(*Symbol, Header.NumberOfSymbols++); - + Symbol->Index = Header.NumberOfSymbols++; // Update auxiliary symbol info. Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size(); Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols; @@ -866,8 +860,24 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, Symbol->Index = -1; } + // Build string table. + for (const auto &S : Sections) + if (S->Name.size() > COFF::NameSize) + Strings.add(S->Name); + for (const auto &S : Symbols) + if (S->should_keep() && S->Name.size() > COFF::NameSize) + Strings.add(S->Name); + Strings.finalize(StringTableBuilder::WinCOFF); + + // Set names. + for (const auto &S : Sections) + SetSectionName(*S); + for (auto &S : Symbols) + if (S->should_keep()) + SetSymbolName(*S); + // Fixup weak external references. - for (auto & Symbol : Symbols) { + for (auto &Symbol : Symbols) { if (Symbol->Other) { assert(Symbol->Index != -1); assert(Symbol->Aux.size() == 1 && "Symbol must contain one aux symbol!"); @@ -878,7 +888,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, } // Fixup associative COMDAT sections. - for (auto & Section : Sections) { + for (auto &Section : Sections) { if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) continue; @@ -908,10 +918,13 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, unsigned offset = 0; - offset += COFF::HeaderSize; + if (UseBigObj) + offset += COFF::Header32Size; + else + offset += COFF::Header16Size; offset += COFF::SectionSize * Header.NumberOfSections; - for (const auto & Section : Asm) { + for (const auto &Section : Asm) { COFFSection *Sec = SectionMap[&Section.getSection()]; if (Sec->Number == -1) @@ -929,7 +942,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff; if (RelocationsOverflow) { - // Signal overflow by setting NumberOfSections to max value. Actual + // Signal overflow by setting NumberOfRelocations to max value. Actual // size is found in reloc #0. Microsoft tools understand this. Sec->Header.NumberOfRelocations = 0xffff; } else { @@ -944,7 +957,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, offset += COFF::RelocationSize * Sec->Relocations.size(); - for (auto & Relocation : Sec->Relocations) { + for (auto &Relocation : Sec->Relocations) { assert(Relocation.Symb->Index != -1); Relocation.Data.SymbolTableIndex = Relocation.Symb->Index; } @@ -974,7 +987,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, sections::iterator i, ie; MCAssembler::const_iterator j, je; - for (auto & Section : Sections) { + for (auto &Section : Sections) { if (Section->Number != -1) { if (Section->Relocations.size() >= 0xffff) Section->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL; @@ -1010,7 +1023,7 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, WriteRelocation(r); } - for (const auto & Relocation : (*i)->Relocations) + for (const auto &Relocation : (*i)->Relocations) WriteRelocation(Relocation.Data); } else assert((*i)->Header.PointerToRelocations == 0 && @@ -1021,11 +1034,11 @@ void WinCOFFObjectWriter::WriteObject(MCAssembler &Asm, assert(OS.tell() == Header.PointerToSymbolTable && "Header::PointerToSymbolTable is insane!"); - for (auto & Symbol : Symbols) + for (auto &Symbol : Symbols) if (Symbol->Index != -1) WriteSymbol(*Symbol); - OS.write((char const *)&Strings.Data.front(), Strings.Data.size()); + OS.write(Strings.data().data(), Strings.data().size()); } MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_) : diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index d391a3f..41a3da7 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringExtras.h" -#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmLayout.h" #include "llvm/MC/MCAssembler.h" @@ -23,13 +22,14 @@ #include "llvm/MC/MCObjectStreamer.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionCOFF.h" +#include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MCValue.h" -#include "llvm/MC/MCWin64EH.h" #include "llvm/MC/MCWinCOFFStreamer.h" #include "llvm/Support/COFF.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" @@ -61,7 +61,7 @@ void MCWinCOFFStreamer::EmitInstToData(const MCInst &Inst, DF->getContents().append(Code.begin(), Code.end()); } -void MCWinCOFFStreamer::InitSections() { +void MCWinCOFFStreamer::InitSections(bool NoExecStack) { // FIXME: this is identical to the ELF one. // This emulates the same behavior of GNU as. This makes it easier // to compare the output as the major sections are in the same order. @@ -133,7 +133,7 @@ void MCWinCOFFStreamer::EmitCOFFSymbolStorageClass(int StorageClass) { if (!CurSymbol) FatalError("storage class specified outside of symbol definition"); - if (StorageClass & ~0xff) + if (StorageClass & ~COFF::SSC_Invalid) FatalError(Twine("storage class value '") + itostr(StorageClass) + "' out of range"); @@ -163,7 +163,7 @@ void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) { const MCSymbolRefExpr *SRE = MCSymbolRefExpr::Create(Symbol, getContext()); MCFixup Fixup = MCFixup::Create(DF->getContents().size(), SRE, FK_SecRel_2); DF->getFixups().push_back(Fixup); - DF->getContents().resize(DF->getContents().size() + 4, 0); + DF->getContents().resize(DF->getContents().size() + 2, 0); } void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { @@ -184,14 +184,35 @@ void MCWinCOFFStreamer::EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, Symbol->getSection().getVariant() == MCSection::SV_COFF) && "Got non-COFF section in the COFF backend!"); - if (ByteAlignment > 32) - report_fatal_error("alignment is limited to 32-bytes"); + const Triple &T = getContext().getObjectFileInfo()->getTargetTriple(); + if (T.isKnownWindowsMSVCEnvironment()) { + if (ByteAlignment > 32) + report_fatal_error("alignment is limited to 32-bytes"); + + // Round size up to alignment so that we will honor the alignment request. + Size = std::max(Size, static_cast(ByteAlignment)); + } AssignSection(Symbol, nullptr); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); SD.setExternal(true); SD.setCommon(Size, ByteAlignment); + + if (!T.isKnownWindowsMSVCEnvironment() && ByteAlignment > 1) { + SmallString<128> Directive; + raw_svector_ostream OS(Directive); + const MCObjectFileInfo *MFI = getContext().getObjectFileInfo(); + + OS << " -aligncomm:\"" << Symbol->getName() << "\"," + << Log2_32_Ceil(ByteAlignment); + OS.flush(); + + PushSection(); + SwitchSection(MFI->getDrectveSection()); + EmitBytes(Directive); + PopSection(); + } } void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, diff --git a/lib/Object/Archive.cpp b/lib/Object/Archive.cpp index e32bdd5..5aada91 100644 --- a/lib/Object/Archive.cpp +++ b/lib/Object/Archive.cpp @@ -22,6 +22,7 @@ using namespace llvm; using namespace object; static const char *const Magic = "!\n"; +static const char *const ThinMagic = "!\n"; void Archive::anchor() { } @@ -86,7 +87,10 @@ Archive::Child::Child(const Archive *Parent, const char *Start) const ArchiveMemberHeader *Header = reinterpret_cast(Start); - Data = StringRef(Start, sizeof(ArchiveMemberHeader) + Header->getSize()); + uint64_t Size = sizeof(ArchiveMemberHeader); + if (!Parent->IsThin || Header->getName() == "/" || Header->getName() == "//") + Size += Header->getSize(); + Data = StringRef(Start, Size); // Setup StartOfFile and PaddingBytes. StartOfFile = sizeof(ArchiveMemberHeader); @@ -100,6 +104,12 @@ Archive::Child::Child(const Archive *Parent, const char *Start) } } +uint64_t Archive::Child::getSize() const { + if (Parent->IsThin) + return getHeader()->getSize(); + return Data.size() - StartOfFile; +} + Archive::Child Archive::Child::getNext() const { size_t SpaceToSkip = Data.size(); // If it's odd, add 1 to make it even. @@ -109,7 +119,7 @@ Archive::Child Archive::Child::getNext() const { const char *NextLoc = Data.data() + SpaceToSkip; // Check to see if this is past the end of the archive. - if (NextLoc >= Parent->Data->getBufferEnd()) + if (NextLoc >= Parent->Data.getBufferEnd()) return Child(Parent, nullptr); return Child(Parent, NextLoc); @@ -159,44 +169,40 @@ ErrorOr Archive::Child::getName() const { return name; } -ErrorOr> -Archive::Child::getMemoryBuffer(bool FullPath) const { +ErrorOr Archive::Child::getMemoryBufferRef() const { ErrorOr NameOrErr = getName(); if (std::error_code EC = NameOrErr.getError()) return EC; StringRef Name = NameOrErr.get(); - SmallString<128> Path; - std::unique_ptr Ret(MemoryBuffer::getMemBuffer( - getBuffer(), - FullPath - ? (Twine(Parent->getFileName()) + "(" + Name + ")").toStringRef(Path) - : Name, - false)); - return std::move(Ret); + return MemoryBufferRef(getBuffer(), Name); } ErrorOr> Archive::Child::getAsBinary(LLVMContext *Context) const { - ErrorOr> BuffOrErr = getMemoryBuffer(); + ErrorOr BuffOrErr = getMemoryBufferRef(); if (std::error_code EC = BuffOrErr.getError()) return EC; - return createBinary(std::move(*BuffOrErr), Context); + return createBinary(BuffOrErr.get(), Context); } -ErrorOr Archive::create(std::unique_ptr Source) { +ErrorOr> Archive::create(MemoryBufferRef Source) { std::error_code EC; - std::unique_ptr Ret(new Archive(std::move(Source), EC)); + std::unique_ptr Ret(new Archive(Source, EC)); if (EC) return EC; - return Ret.release(); + return std::move(Ret); } -Archive::Archive(std::unique_ptr Source, std::error_code &ec) - : Binary(Binary::ID_Archive, std::move(Source)), SymbolTable(child_end()) { +Archive::Archive(MemoryBufferRef Source, std::error_code &ec) + : Binary(Binary::ID_Archive, Source), SymbolTable(child_end()) { + StringRef Buffer = Data.getBuffer(); // Check for sufficient magic. - if (Data->getBufferSize() < 8 || - StringRef(Data->getBufferStart(), 8) != Magic) { + if (Buffer.startswith(ThinMagic)) { + IsThin = true; + } else if (Buffer.startswith(Magic)) { + IsThin = false; + } else { ec = object_error::invalid_file_type; return; } @@ -248,7 +254,7 @@ Archive::Archive(std::unique_ptr Source, std::error_code &ec) if (ec) return; Name = NameOrErr.get(); - if (Name == "__.SYMDEF SORTED") { + if (Name == "__.SYMDEF SORTED" || Name == "__.SYMDEF") { SymbolTable = i; ++i; } @@ -310,13 +316,13 @@ Archive::Archive(std::unique_ptr Source, std::error_code &ec) } Archive::child_iterator Archive::child_begin(bool SkipInternal) const { - if (Data->getBufferSize() == 8) // empty archive. + if (Data.getBufferSize() == 8) // empty archive. return child_end(); if (SkipInternal) return FirstRegular; - const char *Loc = Data->getBufferStart() + strlen(Magic); + const char *Loc = Data.getBufferStart() + strlen(Magic); Child c(this, Loc); return c; } diff --git a/lib/Object/Binary.cpp b/lib/Object/Binary.cpp index 552d5db..c56eeb1 100644 --- a/lib/Object/Binary.cpp +++ b/lib/Object/Binary.cpp @@ -27,24 +27,23 @@ using namespace object; Binary::~Binary() {} -Binary::Binary(unsigned int Type, std::unique_ptr Source) - : TypeID(Type), Data(std::move(Source)) {} +Binary::Binary(unsigned int Type, MemoryBufferRef Source) + : TypeID(Type), Data(Source) {} -StringRef Binary::getData() const { - return Data->getBuffer(); -} +StringRef Binary::getData() const { return Data.getBuffer(); } -StringRef Binary::getFileName() const { - return Data->getBufferIdentifier(); -} +StringRef Binary::getFileName() const { return Data.getBufferIdentifier(); } + +MemoryBufferRef Binary::getMemoryBufferRef() const { return Data; } -ErrorOr object::createBinary(std::unique_ptr Buffer, - LLVMContext *Context) { - sys::fs::file_magic Type = sys::fs::identify_magic(Buffer->getBuffer()); +ErrorOr> object::createBinary(MemoryBufferRef Buffer, + LLVMContext *Context) { + sys::fs::file_magic Type = sys::fs::identify_magic(Buffer.getBuffer()); switch (Type) { case sys::fs::file_magic::archive: - return Archive::create(std::move(Buffer)); + return Archive::create(Buffer); + case sys::fs::file_magic::elf: case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: @@ -65,7 +64,7 @@ ErrorOr object::createBinary(std::unique_ptr Buffer, case sys::fs::file_magic::bitcode: return ObjectFile::createSymbolicFile(Buffer, Type, Context); case sys::fs::file_magic::macho_universal_binary: - return MachOUniversalBinary::create(std::move(Buffer)); + return MachOUniversalBinary::create(Buffer); case sys::fs::file_magic::unknown: case sys::fs::file_magic::windows_resource: // Unrecognized object file format. @@ -74,10 +73,18 @@ ErrorOr object::createBinary(std::unique_ptr Buffer, llvm_unreachable("Unexpected Binary File Type"); } -ErrorOr object::createBinary(StringRef Path) { +ErrorOr> object::createBinary(StringRef Path) { ErrorOr> FileOrErr = MemoryBuffer::getFileOrSTDIN(Path); if (std::error_code EC = FileOrErr.getError()) return EC; - return createBinary(std::move(*FileOrErr)); + std::unique_ptr &Buffer = FileOrErr.get(); + + ErrorOr> BinOrErr = + createBinary(Buffer->getMemBufferRef()); + if (std::error_code EC = BinOrErr.getError()) + return EC; + std::unique_ptr &Bin = BinOrErr.get(); + + return OwningBinary(std::move(Bin), std::move(Buffer)); } diff --git a/lib/Object/COFFObjectFile.cpp b/lib/Object/COFFObjectFile.cpp index 46ef87d..cde6fdc 100644 --- a/lib/Object/COFFObjectFile.cpp +++ b/lib/Object/COFFObjectFile.cpp @@ -25,14 +25,13 @@ using namespace llvm; using namespace object; -using support::ulittle8_t; using support::ulittle16_t; using support::ulittle32_t; +using support::ulittle64_t; using support::little16_t; // Returns false if size is greater than the buffer size. And sets ec. -static bool checkSize(const MemoryBuffer &M, std::error_code &EC, - uint64_t Size) { +static bool checkSize(MemoryBufferRef M, std::error_code &EC, uint64_t Size) { if (M.getBufferSize() < Size) { EC = object_error::unexpected_eof; return false; @@ -40,17 +39,25 @@ static bool checkSize(const MemoryBuffer &M, std::error_code &EC, return true; } +static std::error_code checkOffset(MemoryBufferRef M, uintptr_t Addr, + const uint64_t Size) { + if (Addr + Size < Addr || Addr + Size < Size || + Addr + Size > uintptr_t(M.getBufferEnd()) || + Addr < uintptr_t(M.getBufferStart())) { + return object_error::unexpected_eof; + } + return object_error::success; +} + // Sets Obj unless any bytes in [addr, addr + size) fall outsize of m. // Returns unexpected_eof if error. template -static std::error_code getObject(const T *&Obj, const MemoryBuffer &M, - const uint8_t *Ptr, - const size_t Size = sizeof(T)) { +static std::error_code getObject(const T *&Obj, MemoryBufferRef M, + const void *Ptr, + const uint64_t Size = sizeof(T)) { uintptr_t Addr = uintptr_t(Ptr); - if (Addr + Size < Addr || Addr + Size < Size || - Addr + Size > uintptr_t(M.getBufferEnd())) { - return object_error::unexpected_eof; - } + if (std::error_code EC = checkOffset(M, Addr, Size)) + return EC; Obj = reinterpret_cast(Addr); return object_error::success; } @@ -89,20 +96,19 @@ static bool decodeBase64StringEntry(StringRef Str, uint32_t &Result) { return false; } -const coff_symbol *COFFObjectFile::toSymb(DataRefImpl Ref) const { - const coff_symbol *Addr = reinterpret_cast(Ref.p); +template +const coff_symbol_type *COFFObjectFile::toSymb(DataRefImpl Ref) const { + const coff_symbol_type *Addr = + reinterpret_cast(Ref.p); -# ifndef NDEBUG + assert(!checkOffset(Data, uintptr_t(Addr), sizeof(*Addr))); +#ifndef NDEBUG // Verify that the symbol points to a valid entry in the symbol table. uintptr_t Offset = uintptr_t(Addr) - uintptr_t(base()); - if (Offset < COFFHeader->PointerToSymbolTable - || Offset >= COFFHeader->PointerToSymbolTable - + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) - report_fatal_error("Symbol was outside of symbol table."); - assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) - == 0 && "Symbol did not point to the beginning of a symbol"); -# endif + assert((Offset - getPointerToSymbolTable()) % sizeof(coff_symbol_type) == 0 && + "Symbol did not point to the beginning of a symbol"); +#endif return Addr; } @@ -112,8 +118,7 @@ const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { # ifndef NDEBUG // Verify that the section points to a valid entry in the section table. - if (Addr < SectionTable - || Addr >= (SectionTable + COFFHeader->NumberOfSections)) + if (Addr < SectionTable || Addr >= (SectionTable + getNumberOfSections())) report_fatal_error("Section was outside of section table."); uintptr_t Offset = uintptr_t(Addr) - uintptr_t(SectionTable); @@ -125,112 +130,180 @@ const coff_section *COFFObjectFile::toSec(DataRefImpl Ref) const { } void COFFObjectFile::moveSymbolNext(DataRefImpl &Ref) const { - const coff_symbol *Symb = toSymb(Ref); - Symb += 1 + Symb->NumberOfAuxSymbols; - Ref.p = reinterpret_cast(Symb); + auto End = reinterpret_cast(StringTable); + if (SymbolTable16) { + const coff_symbol16 *Symb = toSymb(Ref); + Symb += 1 + Symb->NumberOfAuxSymbols; + Ref.p = std::min(reinterpret_cast(Symb), End); + } else if (SymbolTable32) { + const coff_symbol32 *Symb = toSymb(Ref); + Symb += 1 + Symb->NumberOfAuxSymbols; + Ref.p = std::min(reinterpret_cast(Symb), End); + } else { + llvm_unreachable("no symbol table pointer!"); + } } std::error_code COFFObjectFile::getSymbolName(DataRefImpl Ref, StringRef &Result) const { - const coff_symbol *Symb = toSymb(Ref); + COFFSymbolRef Symb = getCOFFSymbol(Ref); return getSymbolName(Symb, Result); } std::error_code COFFObjectFile::getSymbolAddress(DataRefImpl Ref, uint64_t &Result) const { - const coff_symbol *Symb = toSymb(Ref); - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(Symb->SectionNumber, Section)) - return EC; + COFFSymbolRef Symb = getCOFFSymbol(Ref); - if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) + if (Symb.isAnyUndefined()) { Result = UnknownAddressOrSize; - else if (Section) - Result = Section->VirtualAddress + Symb->Value; - else - Result = Symb->Value; + return object_error::success; + } + if (Symb.isCommon()) { + Result = UnknownAddressOrSize; + return object_error::success; + } + int32_t SectionNumber = Symb.getSectionNumber(); + if (!COFF::isReservedSectionNumber(SectionNumber)) { + const coff_section *Section = nullptr; + if (std::error_code EC = getSection(SectionNumber, Section)) + return EC; + + Result = Section->VirtualAddress + Symb.getValue(); + return object_error::success; + } + + Result = Symb.getValue(); return object_error::success; } std::error_code COFFObjectFile::getSymbolType(DataRefImpl Ref, SymbolRef::Type &Result) const { - const coff_symbol *Symb = toSymb(Ref); + COFFSymbolRef Symb = getCOFFSymbol(Ref); + int32_t SectionNumber = Symb.getSectionNumber(); Result = SymbolRef::ST_Other; - if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL && - Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { + + if (Symb.isAnyUndefined()) { Result = SymbolRef::ST_Unknown; - } else if (Symb->isFunctionDefinition()) { + } else if (Symb.isFunctionDefinition()) { Result = SymbolRef::ST_Function; - } else { - uint32_t Characteristics = 0; - if (!COFF::isReservedSectionNumber(Symb->SectionNumber)) { - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(Symb->SectionNumber, Section)) - return EC; - Characteristics = Section->Characteristics; - } - if (Characteristics & COFF::IMAGE_SCN_MEM_READ && - ~Characteristics & COFF::IMAGE_SCN_MEM_WRITE) // Read only. + } else if (Symb.isCommon()) { + Result = SymbolRef::ST_Data; + } else if (Symb.isFileRecord()) { + Result = SymbolRef::ST_File; + } else if (SectionNumber == COFF::IMAGE_SYM_DEBUG) { + Result = SymbolRef::ST_Debug; + } else if (!COFF::isReservedSectionNumber(SectionNumber)) { + const coff_section *Section = nullptr; + if (std::error_code EC = getSection(SectionNumber, Section)) + return EC; + uint32_t Characteristics = Section->Characteristics; + if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) + Result = SymbolRef::ST_Function; + else if (Characteristics & (COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | + COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) Result = SymbolRef::ST_Data; } return object_error::success; } uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const { - const coff_symbol *Symb = toSymb(Ref); + COFFSymbolRef Symb = getCOFFSymbol(Ref); uint32_t Result = SymbolRef::SF_None; - // TODO: Correctly set SF_FormatSpecific, SF_Common - - if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) { - if (Symb->Value == 0) - Result |= SymbolRef::SF_Undefined; - else - Result |= SymbolRef::SF_Common; - } - - - // TODO: This are certainly too restrictive. - if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_EXTERNAL) + if (Symb.isExternal() || Symb.isWeakExternal()) Result |= SymbolRef::SF_Global; - if (Symb->StorageClass == COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL) + if (Symb.isWeakExternal()) Result |= SymbolRef::SF_Weak; - if (Symb->SectionNumber == COFF::IMAGE_SYM_ABSOLUTE) + if (Symb.getSectionNumber() == COFF::IMAGE_SYM_ABSOLUTE) Result |= SymbolRef::SF_Absolute; + if (Symb.isFileRecord()) + Result |= SymbolRef::SF_FormatSpecific; + + if (Symb.isSectionDefinition()) + Result |= SymbolRef::SF_FormatSpecific; + + if (Symb.isCommon()) + Result |= SymbolRef::SF_Common; + + if (Symb.isAnyUndefined()) + Result |= SymbolRef::SF_Undefined; + return Result; } std::error_code COFFObjectFile::getSymbolSize(DataRefImpl Ref, uint64_t &Result) const { - // FIXME: Return the correct size. This requires looking at all the symbols - // in the same section as this symbol, and looking for either the next - // symbol, or the end of the section. - const coff_symbol *Symb = toSymb(Ref); - const coff_section *Section = nullptr; - if (std::error_code EC = getSection(Symb->SectionNumber, Section)) - return EC; + COFFSymbolRef Symb = getCOFFSymbol(Ref); - if (Symb->SectionNumber == COFF::IMAGE_SYM_UNDEFINED) + if (Symb.isAnyUndefined()) { Result = UnknownAddressOrSize; - else if (Section) - Result = Section->SizeOfRawData - Symb->Value; - else + return object_error::success; + } + if (Symb.isCommon()) { + Result = Symb.getValue(); + return object_error::success; + } + + // Let's attempt to get the size of the symbol by looking at the address of + // the symbol after the symbol in question. + uint64_t SymbAddr; + if (std::error_code EC = getSymbolAddress(Ref, SymbAddr)) + return EC; + int32_t SectionNumber = Symb.getSectionNumber(); + if (COFF::isReservedSectionNumber(SectionNumber)) { + // Absolute and debug symbols aren't sorted in any interesting way. Result = 0; + return object_error::success; + } + const section_iterator SecEnd = section_end(); + uint64_t AfterAddr = UnknownAddressOrSize; + for (const symbol_iterator &SymbI : symbols()) { + section_iterator SecI = SecEnd; + if (std::error_code EC = SymbI->getSection(SecI)) + return EC; + // Check the symbol's section, skip it if it's in the wrong section. + // First, make sure it is in any section. + if (SecI == SecEnd) + continue; + // Second, make sure it is in the same section as the symbol in question. + if (!sectionContainsSymbol(SecI->getRawDataRefImpl(), Ref)) + continue; + uint64_t Addr; + if (std::error_code EC = SymbI->getAddress(Addr)) + return EC; + // We want to compare our symbol in question with the closest possible + // symbol that comes after. + if (AfterAddr > Addr && Addr > SymbAddr) + AfterAddr = Addr; + } + if (AfterAddr == UnknownAddressOrSize) { + // No symbol comes after this one, assume that everything after our symbol + // is part of it. + const coff_section *Section = nullptr; + if (std::error_code EC = getSection(SectionNumber, Section)) + return EC; + Result = Section->SizeOfRawData - Symb.getValue(); + } else { + // Take the difference between our symbol and the symbol that comes after + // our symbol. + Result = AfterAddr - SymbAddr; + } + return object_error::success; } std::error_code COFFObjectFile::getSymbolSection(DataRefImpl Ref, section_iterator &Result) const { - const coff_symbol *Symb = toSymb(Ref); - if (COFF::isReservedSectionNumber(Symb->SectionNumber)) { + COFFSymbolRef Symb = getCOFFSymbol(Ref); + if (COFF::isReservedSectionNumber(Symb.getSectionNumber())) { Result = section_end(); } else { const coff_section *Sec = nullptr; - if (std::error_code EC = getSection(Symb->SectionNumber, Sec)) + if (std::error_code EC = getSection(Symb.getSectionNumber(), Sec)) return EC; DataRefImpl Ref; Ref.p = reinterpret_cast(Sec); @@ -251,18 +324,13 @@ std::error_code COFFObjectFile::getSectionName(DataRefImpl Ref, return getSectionName(Sec, Result); } -std::error_code COFFObjectFile::getSectionAddress(DataRefImpl Ref, - uint64_t &Result) const { +uint64_t COFFObjectFile::getSectionAddress(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - Result = Sec->VirtualAddress; - return object_error::success; + return Sec->VirtualAddress; } -std::error_code COFFObjectFile::getSectionSize(DataRefImpl Ref, - uint64_t &Result) const { - const coff_section *Sec = toSec(Ref); - Result = Sec->SizeOfRawData; - return object_error::success; +uint64_t COFFObjectFile::getSectionSize(DataRefImpl Ref) const { + return getSectionSize(toSec(Ref)); } std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, @@ -274,146 +342,117 @@ std::error_code COFFObjectFile::getSectionContents(DataRefImpl Ref, return EC; } -std::error_code COFFObjectFile::getSectionAlignment(DataRefImpl Ref, - uint64_t &Res) const { +uint64_t COFFObjectFile::getSectionAlignment(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - if (!Sec) - return object_error::parse_failed; - Res = uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); - return object_error::success; + return uint64_t(1) << (((Sec->Characteristics & 0x00F00000) >> 20) - 1); } -std::error_code COFFObjectFile::isSectionText(DataRefImpl Ref, - bool &Result) const { +bool COFFObjectFile::isSectionText(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; - return object_error::success; + return Sec->Characteristics & COFF::IMAGE_SCN_CNT_CODE; } -std::error_code COFFObjectFile::isSectionData(DataRefImpl Ref, - bool &Result) const { +bool COFFObjectFile::isSectionData(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; - return object_error::success; + return Sec->Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA; } -std::error_code COFFObjectFile::isSectionBSS(DataRefImpl Ref, - bool &Result) const { +bool COFFObjectFile::isSectionBSS(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; - return object_error::success; + return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; } -std::error_code -COFFObjectFile::isSectionRequiredForExecution(DataRefImpl Ref, - bool &Result) const { - // FIXME: Unimplemented - Result = true; - return object_error::success; -} - -std::error_code COFFObjectFile::isSectionVirtual(DataRefImpl Ref, - bool &Result) const { +bool COFFObjectFile::isSectionVirtual(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); - Result = Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; - return object_error::success; + return Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; } -std::error_code COFFObjectFile::isSectionZeroInit(DataRefImpl Ref, - bool &Result) const { - // FIXME: Unimplemented. - Result = false; - return object_error::success; -} - -std::error_code COFFObjectFile::isSectionReadOnlyData(DataRefImpl Ref, - bool &Result) const { - // FIXME: Unimplemented. - Result = false; - return object_error::success; -} - -std::error_code COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, - DataRefImpl SymbRef, - bool &Result) const { +bool COFFObjectFile::sectionContainsSymbol(DataRefImpl SecRef, + DataRefImpl SymbRef) const { const coff_section *Sec = toSec(SecRef); - const coff_symbol *Symb = toSymb(SymbRef); - const coff_section *SymbSec = nullptr; - if (std::error_code EC = getSection(Symb->SectionNumber, SymbSec)) - return EC; - if (SymbSec == Sec) - Result = true; - else - Result = false; - return object_error::success; -} - -relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { - const coff_section *Sec = toSec(Ref); - DataRefImpl Ret; - if (Sec->NumberOfRelocations == 0) { - Ret.p = 0; - } else { - auto begin = reinterpret_cast( - base() + Sec->PointerToRelocations); - if (Sec->hasExtendedRelocations()) { - // Skip the first relocation entry repurposed to store the number of - // relocations. - begin++; - } - Ret.p = reinterpret_cast(begin); - } - return relocation_iterator(RelocationRef(Ret, this)); + COFFSymbolRef Symb = getCOFFSymbol(SymbRef); + int32_t SecNumber = (Sec - SectionTable) + 1; + return SecNumber == Symb.getSectionNumber(); } static uint32_t getNumberOfRelocations(const coff_section *Sec, - const uint8_t *base) { + MemoryBufferRef M, const uint8_t *base) { // The field for the number of relocations in COFF section table is only // 16-bit wide. If a section has more than 65535 relocations, 0xFFFF is set to // NumberOfRelocations field, and the actual relocation count is stored in the // VirtualAddress field in the first relocation entry. if (Sec->hasExtendedRelocations()) { - auto *FirstReloc = reinterpret_cast( - base + Sec->PointerToRelocations); - return FirstReloc->VirtualAddress; + const coff_relocation *FirstReloc; + if (getObject(FirstReloc, M, reinterpret_cast( + base + Sec->PointerToRelocations))) + return 0; + // -1 to exclude this first relocation entry. + return FirstReloc->VirtualAddress - 1; } return Sec->NumberOfRelocations; } +static const coff_relocation * +getFirstReloc(const coff_section *Sec, MemoryBufferRef M, const uint8_t *Base) { + uint64_t NumRelocs = getNumberOfRelocations(Sec, M, Base); + if (!NumRelocs) + return nullptr; + auto begin = reinterpret_cast( + Base + Sec->PointerToRelocations); + if (Sec->hasExtendedRelocations()) { + // Skip the first relocation entry repurposed to store the number of + // relocations. + begin++; + } + if (checkOffset(M, uintptr_t(begin), sizeof(coff_relocation) * NumRelocs)) + return nullptr; + return begin; +} + +relocation_iterator COFFObjectFile::section_rel_begin(DataRefImpl Ref) const { + const coff_section *Sec = toSec(Ref); + const coff_relocation *begin = getFirstReloc(Sec, Data, base()); + DataRefImpl Ret; + Ret.p = reinterpret_cast(begin); + return relocation_iterator(RelocationRef(Ret, this)); +} + relocation_iterator COFFObjectFile::section_rel_end(DataRefImpl Ref) const { const coff_section *Sec = toSec(Ref); + const coff_relocation *I = getFirstReloc(Sec, Data, base()); + if (I) + I += getNumberOfRelocations(Sec, Data, base()); DataRefImpl Ret; - if (Sec->NumberOfRelocations == 0) { - Ret.p = 0; - } else { - auto begin = reinterpret_cast( - base() + Sec->PointerToRelocations); - uint32_t NumReloc = getNumberOfRelocations(Sec, base()); - Ret.p = reinterpret_cast(begin + NumReloc); - } + Ret.p = reinterpret_cast(I); return relocation_iterator(RelocationRef(Ret, this)); } // Initialize the pointer to the symbol table. std::error_code COFFObjectFile::initSymbolTablePtr() { - if (std::error_code EC = getObject( - SymbolTable, *Data, base() + COFFHeader->PointerToSymbolTable, - COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) - return EC; + if (COFFHeader) + if (std::error_code EC = getObject( + SymbolTable16, Data, base() + getPointerToSymbolTable(), + (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) + return EC; + + if (COFFBigObjHeader) + if (std::error_code EC = getObject( + SymbolTable32, Data, base() + getPointerToSymbolTable(), + (uint64_t)getNumberOfSymbols() * getSymbolTableEntrySize())) + return EC; // Find string table. The first four byte of the string table contains the // total size of the string table, including the size field itself. If the // string table is empty, the value of the first four byte would be 4. - const uint8_t *StringTableAddr = - base() + COFFHeader->PointerToSymbolTable + - COFFHeader->NumberOfSymbols * sizeof(coff_symbol); + uint32_t StringTableOffset = getPointerToSymbolTable() + + getNumberOfSymbols() * getSymbolTableEntrySize(); + const uint8_t *StringTableAddr = base() + StringTableOffset; const ulittle32_t *StringTableSizePtr; - if (std::error_code EC = - getObject(StringTableSizePtr, *Data, StringTableAddr)) + if (std::error_code EC = getObject(StringTableSizePtr, Data, StringTableAddr)) return EC; StringTableSize = *StringTableSizePtr; if (std::error_code EC = - getObject(StringTable, *Data, StringTableAddr, StringTableSize)) + getObject(StringTable, Data, StringTableAddr, StringTableSize)) return EC; // Treat table sizes < 4 as empty because contrary to the PECOFF spec, some @@ -477,8 +516,9 @@ std::error_code COFFObjectFile::initImportTablePtr() { return object_error::success; uint32_t ImportTableRva = DataEntry->RelativeVirtualAddress; + // -1 because the last entry is the null entry. NumberOfImportDirectory = DataEntry->Size / - sizeof(import_directory_table_entry); + sizeof(import_directory_table_entry) - 1; // Find the section that contains the RVA. This is needed because the RVA is // the import table's memory address which is different from its file offset. @@ -490,6 +530,26 @@ std::error_code COFFObjectFile::initImportTablePtr() { return object_error::success; } +// Initializes DelayImportDirectory and NumberOfDelayImportDirectory. +std::error_code COFFObjectFile::initDelayImportTablePtr() { + const data_directory *DataEntry; + if (getDataDirectory(COFF::DELAY_IMPORT_DESCRIPTOR, DataEntry)) + return object_error::success; + if (DataEntry->RelativeVirtualAddress == 0) + return object_error::success; + + uint32_t RVA = DataEntry->RelativeVirtualAddress; + NumberOfDelayImportDirectory = DataEntry->Size / + sizeof(delay_import_directory_table_entry) - 1; + + uintptr_t IntPtr = 0; + if (std::error_code EC = getRvaPtr(RVA, IntPtr)) + return EC; + DelayImportDirectory = reinterpret_cast< + const delay_import_directory_table_entry *>(IntPtr); + return object_error::success; +} + // Find the export table. std::error_code COFFObjectFile::initExportTablePtr() { // First, we get the RVA of the export table. If the file lacks a pointer to @@ -511,15 +571,34 @@ std::error_code COFFObjectFile::initExportTablePtr() { return object_error::success; } -COFFObjectFile::COFFObjectFile(std::unique_ptr Object, - std::error_code &EC) - : ObjectFile(Binary::ID_COFF, std::move(Object)), COFFHeader(nullptr), - PE32Header(nullptr), PE32PlusHeader(nullptr), DataDirectory(nullptr), - SectionTable(nullptr), SymbolTable(nullptr), StringTable(nullptr), - StringTableSize(0), ImportDirectory(nullptr), NumberOfImportDirectory(0), - ExportDirectory(nullptr) { +std::error_code COFFObjectFile::initBaseRelocPtr() { + const data_directory *DataEntry; + if (getDataDirectory(COFF::BASE_RELOCATION_TABLE, DataEntry)) + return object_error::success; + if (DataEntry->RelativeVirtualAddress == 0) + return object_error::success; + + uintptr_t IntPtr = 0; + if (std::error_code EC = getRvaPtr(DataEntry->RelativeVirtualAddress, IntPtr)) + return EC; + BaseRelocHeader = reinterpret_cast( + IntPtr); + BaseRelocEnd = reinterpret_cast( + IntPtr + DataEntry->Size); + return object_error::success; +} + +COFFObjectFile::COFFObjectFile(MemoryBufferRef Object, std::error_code &EC) + : ObjectFile(Binary::ID_COFF, Object), COFFHeader(nullptr), + COFFBigObjHeader(nullptr), PE32Header(nullptr), PE32PlusHeader(nullptr), + DataDirectory(nullptr), SectionTable(nullptr), SymbolTable16(nullptr), + SymbolTable32(nullptr), StringTable(nullptr), StringTableSize(0), + ImportDirectory(nullptr), NumberOfImportDirectory(0), + DelayImportDirectory(nullptr), NumberOfDelayImportDirectory(0), + ExportDirectory(nullptr), BaseRelocHeader(nullptr), + BaseRelocEnd(nullptr) { // Check that we at least have enough room for a header. - if (!checkSize(*Data, EC, sizeof(coff_file_header))) + if (!checkSize(Data, EC, sizeof(coff_file_header))) return; // The current location in the file where we are looking at. @@ -530,37 +609,66 @@ COFFObjectFile::COFFObjectFile(std::unique_ptr Object, bool HasPEHeader = false; // Check if this is a PE/COFF file. - if (base()[0] == 0x4d && base()[1] == 0x5a) { + if (checkSize(Data, EC, sizeof(dos_header) + sizeof(COFF::PEMagic))) { // PE/COFF, seek through MS-DOS compatibility stub and 4-byte // PE signature to find 'normal' COFF header. - if (!checkSize(*Data, EC, 0x3c + 8)) - return; - CurPtr = *reinterpret_cast(base() + 0x3c); - // Check the PE magic bytes. ("PE\0\0") - if (std::memcmp(base() + CurPtr, "PE\0\0", 4) != 0) { - EC = object_error::parse_failed; - return; + const auto *DH = reinterpret_cast(base()); + if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') { + CurPtr = DH->AddressOfNewExeHeader; + // Check the PE magic bytes. ("PE\0\0") + if (memcmp(base() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) != 0) { + EC = object_error::parse_failed; + return; + } + CurPtr += sizeof(COFF::PEMagic); // Skip the PE magic bytes. + HasPEHeader = true; } - CurPtr += 4; // Skip the PE magic bytes. - HasPEHeader = true; } - if ((EC = getObject(COFFHeader, *Data, base() + CurPtr))) + if ((EC = getObject(COFFHeader, Data, base() + CurPtr))) return; - CurPtr += sizeof(coff_file_header); + + // It might be a bigobj file, let's check. Note that COFF bigobj and COFF + // import libraries share a common prefix but bigobj is more restrictive. + if (!HasPEHeader && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN && + COFFHeader->NumberOfSections == uint16_t(0xffff) && + checkSize(Data, EC, sizeof(coff_bigobj_file_header))) { + if ((EC = getObject(COFFBigObjHeader, Data, base() + CurPtr))) + return; + + // Verify that we are dealing with bigobj. + if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion && + std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic, + sizeof(COFF::BigObjMagic)) == 0) { + COFFHeader = nullptr; + CurPtr += sizeof(coff_bigobj_file_header); + } else { + // It's not a bigobj. + COFFBigObjHeader = nullptr; + } + } + if (COFFHeader) { + // The prior checkSize call may have failed. This isn't a hard error + // because we were just trying to sniff out bigobj. + EC = object_error::success; + CurPtr += sizeof(coff_file_header); + + if (COFFHeader->isImportLibrary()) + return; + } if (HasPEHeader) { const pe32_header *Header; - if ((EC = getObject(Header, *Data, base() + CurPtr))) + if ((EC = getObject(Header, Data, base() + CurPtr))) return; const uint8_t *DataDirAddr; uint64_t DataDirSize; - if (Header->Magic == 0x10b) { + if (Header->Magic == COFF::PE32Header::PE32) { PE32Header = Header; DataDirAddr = base() + CurPtr + sizeof(pe32_header); DataDirSize = sizeof(data_directory) * PE32Header->NumberOfRvaAndSize; - } else if (Header->Magic == 0x20b) { + } else if (Header->Magic == COFF::PE32Header::PE32_PLUS) { PE32PlusHeader = reinterpret_cast(Header); DataDirAddr = base() + CurPtr + sizeof(pe32plus_header); DataDirSize = sizeof(data_directory) * PE32PlusHeader->NumberOfRvaAndSize; @@ -569,37 +677,47 @@ COFFObjectFile::COFFObjectFile(std::unique_ptr Object, EC = object_error::parse_failed; return; } - if ((EC = getObject(DataDirectory, *Data, DataDirAddr, DataDirSize))) + if ((EC = getObject(DataDirectory, Data, DataDirAddr, DataDirSize))) return; CurPtr += COFFHeader->SizeOfOptionalHeader; } - if (COFFHeader->isImportLibrary()) - return; - - if ((EC = getObject(SectionTable, *Data, base() + CurPtr, - COFFHeader->NumberOfSections * sizeof(coff_section)))) + if ((EC = getObject(SectionTable, Data, base() + CurPtr, + (uint64_t)getNumberOfSections() * sizeof(coff_section)))) return; // Initialize the pointer to the symbol table. - if (COFFHeader->PointerToSymbolTable != 0) + if (getPointerToSymbolTable() != 0) { if ((EC = initSymbolTablePtr())) return; + } else { + // We had better not have any symbols if we don't have a symbol table. + if (getNumberOfSymbols() != 0) { + EC = object_error::parse_failed; + return; + } + } // Initialize the pointer to the beginning of the import table. if ((EC = initImportTablePtr())) return; + if ((EC = initDelayImportTablePtr())) + return; // Initialize the pointer to the export table. if ((EC = initExportTablePtr())) return; + // Initialize the pointer to the base relocation table. + if ((EC = initBaseRelocPtr())) + return; + EC = object_error::success; } basic_symbol_iterator COFFObjectFile::symbol_begin_impl() const { DataRefImpl Ret; - Ret.p = reinterpret_cast(SymbolTable); + Ret.p = getSymbolTable(); return basic_symbol_iterator(SymbolRef(Ret, this)); } @@ -610,21 +728,6 @@ basic_symbol_iterator COFFObjectFile::symbol_end_impl() const { return basic_symbol_iterator(SymbolRef(Ret, this)); } -library_iterator COFFObjectFile::needed_library_begin() const { - // TODO: implement - report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); -} - -library_iterator COFFObjectFile::needed_library_end() const { - // TODO: implement - report_fatal_error("Libraries needed unimplemented in COFFObjectFile"); -} - -StringRef COFFObjectFile::getLoadName() const { - // COFF does not have this field. - return ""; -} - import_directory_iterator COFFObjectFile::import_directory_begin() const { return import_directory_iterator( ImportDirectoryEntryRef(ImportDirectory, 0, this)); @@ -635,6 +738,19 @@ import_directory_iterator COFFObjectFile::import_directory_end() const { ImportDirectoryEntryRef(ImportDirectory, NumberOfImportDirectory, this)); } +delay_import_directory_iterator +COFFObjectFile::delay_import_directory_begin() const { + return delay_import_directory_iterator( + DelayImportDirectoryEntryRef(DelayImportDirectory, 0, this)); +} + +delay_import_directory_iterator +COFFObjectFile::delay_import_directory_end() const { + return delay_import_directory_iterator( + DelayImportDirectoryEntryRef( + DelayImportDirectory, NumberOfDelayImportDirectory, this)); +} + export_directory_iterator COFFObjectFile::export_directory_begin() const { return export_directory_iterator( ExportDirectoryEntryRef(ExportDirectory, 0, this)); @@ -656,18 +772,26 @@ section_iterator COFFObjectFile::section_begin() const { section_iterator COFFObjectFile::section_end() const { DataRefImpl Ret; - int NumSections = COFFHeader->isImportLibrary() - ? 0 : COFFHeader->NumberOfSections; + int NumSections = + COFFHeader && COFFHeader->isImportLibrary() ? 0 : getNumberOfSections(); Ret.p = reinterpret_cast(SectionTable + NumSections); return section_iterator(SectionRef(Ret, this)); } +base_reloc_iterator COFFObjectFile::base_reloc_begin() const { + return base_reloc_iterator(BaseRelocRef(BaseRelocHeader, this)); +} + +base_reloc_iterator COFFObjectFile::base_reloc_end() const { + return base_reloc_iterator(BaseRelocRef(BaseRelocEnd, this)); +} + uint8_t COFFObjectFile::getBytesInAddress() const { return getArch() == Triple::x86_64 ? 8 : 4; } StringRef COFFObjectFile::getFileFormatName() const { - switch(COFFHeader->Machine) { + switch(getMachine()) { case COFF::IMAGE_FILE_MACHINE_I386: return "COFF-i386"; case COFF::IMAGE_FILE_MACHINE_AMD64: @@ -680,7 +804,7 @@ StringRef COFFObjectFile::getFileFormatName() const { } unsigned COFFObjectFile::getArch() const { - switch(COFFHeader->Machine) { + switch (getMachine()) { case COFF::IMAGE_FILE_MACHINE_I386: return Triple::x86; case COFF::IMAGE_FILE_MACHINE_AMD64: @@ -692,16 +816,24 @@ unsigned COFFObjectFile::getArch() const { } } -// This method is kept here because lld uses this. As soon as we make -// lld to use getCOFFHeader, this method will be removed. -std::error_code COFFObjectFile::getHeader(const coff_file_header *&Res) const { - return getCOFFHeader(Res); +iterator_range +COFFObjectFile::import_directories() const { + return make_range(import_directory_begin(), import_directory_end()); } -std::error_code -COFFObjectFile::getCOFFHeader(const coff_file_header *&Res) const { - Res = COFFHeader; - return object_error::success; +iterator_range +COFFObjectFile::delay_import_directories() const { + return make_range(delay_import_directory_begin(), + delay_import_directory_end()); +} + +iterator_range +COFFObjectFile::export_directories() const { + return make_range(export_directory_begin(), export_directory_end()); +} + +iterator_range COFFObjectFile::base_relocs() const { + return make_range(base_reloc_begin(), base_reloc_end()); } std::error_code COFFObjectFile::getPE32Header(const pe32_header *&Res) const { @@ -719,28 +851,32 @@ std::error_code COFFObjectFile::getDataDirectory(uint32_t Index, const data_directory *&Res) const { // Error if if there's no data directory or the index is out of range. - if (!DataDirectory) + if (!DataDirectory) { + Res = nullptr; return object_error::parse_failed; + } assert(PE32Header || PE32PlusHeader); uint32_t NumEnt = PE32Header ? PE32Header->NumberOfRvaAndSize : PE32PlusHeader->NumberOfRvaAndSize; - if (Index > NumEnt) + if (Index >= NumEnt) { + Res = nullptr; return object_error::parse_failed; + } Res = &DataDirectory[Index]; return object_error::success; } std::error_code COFFObjectFile::getSection(int32_t Index, const coff_section *&Result) const { - // Check for special index values. + Result = nullptr; if (COFF::isReservedSectionNumber(Index)) - Result = nullptr; - else if (Index > 0 && Index <= COFFHeader->NumberOfSections) + return object_error::success; + if (static_cast(Index) <= getNumberOfSections()) { // We already verified the section table data, so no need to check again. Result = SectionTable + (Index - 1); - else - return object_error::parse_failed; - return object_error::success; + return object_error::success; + } + return object_error::parse_failed; } std::error_code COFFObjectFile::getString(uint32_t Offset, @@ -754,71 +890,62 @@ std::error_code COFFObjectFile::getString(uint32_t Offset, return object_error::success; } -std::error_code COFFObjectFile::getSymbol(uint32_t Index, - const coff_symbol *&Result) const { - if (Index < COFFHeader->NumberOfSymbols) - Result = SymbolTable + Index; - else - return object_error::parse_failed; - return object_error::success; -} - -std::error_code COFFObjectFile::getSymbolName(const coff_symbol *Symbol, +std::error_code COFFObjectFile::getSymbolName(COFFSymbolRef Symbol, StringRef &Res) const { // Check for string table entry. First 4 bytes are 0. - if (Symbol->Name.Offset.Zeroes == 0) { - uint32_t Offset = Symbol->Name.Offset.Offset; + if (Symbol.getStringTableOffset().Zeroes == 0) { + uint32_t Offset = Symbol.getStringTableOffset().Offset; if (std::error_code EC = getString(Offset, Res)) return EC; return object_error::success; } - if (Symbol->Name.ShortName[7] == 0) + if (Symbol.getShortName()[COFF::NameSize - 1] == 0) // Null terminated, let ::strlen figure out the length. - Res = StringRef(Symbol->Name.ShortName); + Res = StringRef(Symbol.getShortName()); else // Not null terminated, use all 8 bytes. - Res = StringRef(Symbol->Name.ShortName, 8); + Res = StringRef(Symbol.getShortName(), COFF::NameSize); return object_error::success; } -ArrayRef COFFObjectFile::getSymbolAuxData( - const coff_symbol *Symbol) const { +ArrayRef +COFFObjectFile::getSymbolAuxData(COFFSymbolRef Symbol) const { const uint8_t *Aux = nullptr; - if (Symbol->NumberOfAuxSymbols > 0) { - // AUX data comes immediately after the symbol in COFF - Aux = reinterpret_cast(Symbol + 1); + size_t SymbolSize = getSymbolTableEntrySize(); + if (Symbol.getNumberOfAuxSymbols() > 0) { + // AUX data comes immediately after the symbol in COFF + Aux = reinterpret_cast(Symbol.getRawPtr()) + SymbolSize; # ifndef NDEBUG // Verify that the Aux symbol points to a valid entry in the symbol table. uintptr_t Offset = uintptr_t(Aux) - uintptr_t(base()); - if (Offset < COFFHeader->PointerToSymbolTable - || Offset >= COFFHeader->PointerToSymbolTable - + (COFFHeader->NumberOfSymbols * sizeof(coff_symbol))) + if (Offset < getPointerToSymbolTable() || + Offset >= + getPointerToSymbolTable() + (getNumberOfSymbols() * SymbolSize)) report_fatal_error("Aux Symbol data was outside of symbol table."); - assert((Offset - COFFHeader->PointerToSymbolTable) % sizeof(coff_symbol) - == 0 && "Aux Symbol data did not point to the beginning of a symbol"); + assert((Offset - getPointerToSymbolTable()) % SymbolSize == 0 && + "Aux Symbol data did not point to the beginning of a symbol"); # endif } - return ArrayRef(Aux, - Symbol->NumberOfAuxSymbols * sizeof(coff_symbol)); + return makeArrayRef(Aux, Symbol.getNumberOfAuxSymbols() * SymbolSize); } std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, StringRef &Res) const { StringRef Name; - if (Sec->Name[7] == 0) + if (Sec->Name[COFF::NameSize - 1] == 0) // Null terminated, let ::strlen figure out the length. Name = Sec->Name; else // Not null terminated, use all 8 bytes. - Name = StringRef(Sec->Name, 8); + Name = StringRef(Sec->Name, COFF::NameSize); // Check for string table entry. First byte is '/'. - if (Name[0] == '/') { + if (Name.startswith("/")) { uint32_t Offset; - if (Name[1] == '/') { + if (Name.startswith("//")) { if (decodeBase64StringEntry(Name.substr(2), Offset)) return object_error::parse_failed; } else { @@ -833,18 +960,41 @@ std::error_code COFFObjectFile::getSectionName(const coff_section *Sec, return object_error::success; } +uint64_t COFFObjectFile::getSectionSize(const coff_section *Sec) const { + // SizeOfRawData and VirtualSize change what they represent depending on + // whether or not we have an executable image. + // + // For object files, SizeOfRawData contains the size of section's data; + // VirtualSize is always zero. + // + // For executables, SizeOfRawData *must* be a multiple of FileAlignment; the + // actual section size is in VirtualSize. It is possible for VirtualSize to + // be greater than SizeOfRawData; the contents past that point should be + // considered to be zero. + uint32_t SectionSize; + if (Sec->VirtualSize) + SectionSize = std::min(Sec->VirtualSize, Sec->SizeOfRawData); + else + SectionSize = Sec->SizeOfRawData; + + return SectionSize; +} + std::error_code COFFObjectFile::getSectionContents(const coff_section *Sec, ArrayRef &Res) const { + // PointerToRawData and SizeOfRawData won't make sense for BSS sections, + // don't do anything interesting for them. + assert((Sec->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0 && + "BSS sections don't have contents!"); // The only thing that we need to verify is that the contents is contained // within the file bounds. We don't need to make sure it doesn't cover other // data, as there's nothing that says that is not allowed. uintptr_t ConStart = uintptr_t(base()) + Sec->PointerToRawData; - uintptr_t ConEnd = ConStart + Sec->SizeOfRawData; - if (ConEnd > uintptr_t(Data->getBufferEnd())) + uint32_t SectionSize = getSectionSize(Sec); + if (checkOffset(Data, ConStart, SectionSize)) return object_error::parse_failed; - Res = ArrayRef(reinterpret_cast(ConStart), - Sec->SizeOfRawData); + Res = makeArrayRef(reinterpret_cast(ConStart), SectionSize); return object_error::success; } @@ -864,14 +1014,26 @@ std::error_code COFFObjectFile::getRelocationAddress(DataRefImpl Rel, std::error_code COFFObjectFile::getRelocationOffset(DataRefImpl Rel, uint64_t &Res) const { - Res = toRel(Rel)->VirtualAddress; + const coff_relocation *R = toRel(Rel); + const support::ulittle32_t *VirtualAddressPtr; + if (std::error_code EC = + getObject(VirtualAddressPtr, Data, &R->VirtualAddress)) + return EC; + Res = *VirtualAddressPtr; return object_error::success; } symbol_iterator COFFObjectFile::getRelocationSymbol(DataRefImpl Rel) const { - const coff_relocation* R = toRel(Rel); + const coff_relocation *R = toRel(Rel); DataRefImpl Ref; - Ref.p = reinterpret_cast(SymbolTable + R->SymbolTableIndex); + if (R->SymbolTableIndex >= getNumberOfSymbols()) + return symbol_end(); + if (SymbolTable16) + Ref.p = reinterpret_cast(SymbolTable16 + R->SymbolTableIndex); + else if (SymbolTable32) + Ref.p = reinterpret_cast(SymbolTable32 + R->SymbolTableIndex); + else + llvm_unreachable("no symbol table pointer!"); return symbol_iterator(SymbolRef(Ref, this)); } @@ -887,9 +1049,16 @@ COFFObjectFile::getCOFFSection(const SectionRef &Section) const { return toSec(Section.getRawDataRefImpl()); } -const coff_symbol * -COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { - return toSymb(Symbol.getRawDataRefImpl()); +COFFSymbolRef COFFObjectFile::getCOFFSymbol(const DataRefImpl &Ref) const { + if (SymbolTable16) + return toSymb(Ref); + if (SymbolTable32) + return toSymb(Ref); + llvm_unreachable("no symbol table pointer!"); +} + +COFFSymbolRef COFFObjectFile::getCOFFSymbol(const SymbolRef &Symbol) const { + return getCOFFSymbol(Symbol.getRawDataRefImpl()); } const coff_relocation * @@ -907,7 +1076,7 @@ COFFObjectFile::getRelocationTypeName(DataRefImpl Rel, SmallVectorImpl &Result) const { const coff_relocation *Reloc = toRel(Rel); StringRef Res; - switch (COFFHeader->Machine) { + switch (getMachine()) { case COFF::IMAGE_FILE_MACHINE_AMD64: switch (Reloc->Type) { LLVM_COFF_SWITCH_RELOC_TYPE_NAME(IMAGE_REL_AMD64_ABSOLUTE); @@ -982,11 +1151,11 @@ std::error_code COFFObjectFile::getRelocationValueString(DataRefImpl Rel, SmallVectorImpl &Result) const { const coff_relocation *Reloc = toRel(Rel); - const coff_symbol *Symb = nullptr; - if (std::error_code EC = getSymbol(Reloc->SymbolTableIndex, Symb)) - return EC; DataRefImpl Sym; - Sym.p = reinterpret_cast(Symb); + ErrorOr Symb = getSymbol(Reloc->SymbolTableIndex); + if (std::error_code EC = Symb.getError()) + return EC; + Sym.p = reinterpret_cast(Symb->getRawPtr()); StringRef SymName; if (std::error_code EC = getSymbolName(Sym, SymName)) return EC; @@ -994,14 +1163,8 @@ COFFObjectFile::getRelocationValueString(DataRefImpl Rel, return object_error::success; } -std::error_code COFFObjectFile::getLibraryNext(DataRefImpl LibData, - LibraryRef &Result) const { - report_fatal_error("getLibraryNext not implemented in COFFObjectFile"); -} - -std::error_code COFFObjectFile::getLibraryPath(DataRefImpl LibData, - StringRef &Result) const { - report_fatal_error("getLibraryPath not implemented in COFFObjectFile"); +bool COFFObjectFile::isRelocatableObject() const { + return !DataDirectory; } bool ImportDirectoryEntryRef:: @@ -1015,29 +1178,148 @@ void ImportDirectoryEntryRef::moveNext() { std::error_code ImportDirectoryEntryRef::getImportTableEntry( const import_directory_table_entry *&Result) const { - Result = ImportTable; + Result = ImportTable + Index; return object_error::success; } +static imported_symbol_iterator +makeImportedSymbolIterator(const COFFObjectFile *Object, + uintptr_t Ptr, int Index) { + if (Object->getBytesInAddress() == 4) { + auto *P = reinterpret_cast(Ptr); + return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); + } + auto *P = reinterpret_cast(Ptr); + return imported_symbol_iterator(ImportedSymbolRef(P, Index, Object)); +} + +static imported_symbol_iterator +importedSymbolBegin(uint32_t RVA, const COFFObjectFile *Object) { + uintptr_t IntPtr = 0; + Object->getRvaPtr(RVA, IntPtr); + return makeImportedSymbolIterator(Object, IntPtr, 0); +} + +static imported_symbol_iterator +importedSymbolEnd(uint32_t RVA, const COFFObjectFile *Object) { + uintptr_t IntPtr = 0; + Object->getRvaPtr(RVA, IntPtr); + // Forward the pointer to the last entry which is null. + int Index = 0; + if (Object->getBytesInAddress() == 4) { + auto *Entry = reinterpret_cast(IntPtr); + while (*Entry++) + ++Index; + } else { + auto *Entry = reinterpret_cast(IntPtr); + while (*Entry++) + ++Index; + } + return makeImportedSymbolIterator(Object, IntPtr, Index); +} + +imported_symbol_iterator +ImportDirectoryEntryRef::imported_symbol_begin() const { + return importedSymbolBegin(ImportTable[Index].ImportLookupTableRVA, + OwningObject); +} + +imported_symbol_iterator +ImportDirectoryEntryRef::imported_symbol_end() const { + return importedSymbolEnd(ImportTable[Index].ImportLookupTableRVA, + OwningObject); +} + +iterator_range +ImportDirectoryEntryRef::imported_symbols() const { + return make_range(imported_symbol_begin(), imported_symbol_end()); +} + std::error_code ImportDirectoryEntryRef::getName(StringRef &Result) const { uintptr_t IntPtr = 0; if (std::error_code EC = - OwningObject->getRvaPtr(ImportTable->NameRVA, IntPtr)) + OwningObject->getRvaPtr(ImportTable[Index].NameRVA, IntPtr)) return EC; Result = StringRef(reinterpret_cast(IntPtr)); return object_error::success; } +std::error_code +ImportDirectoryEntryRef::getImportLookupTableRVA(uint32_t &Result) const { + Result = ImportTable[Index].ImportLookupTableRVA; + return object_error::success; +} + +std::error_code +ImportDirectoryEntryRef::getImportAddressTableRVA(uint32_t &Result) const { + Result = ImportTable[Index].ImportAddressTableRVA; + return object_error::success; +} + std::error_code ImportDirectoryEntryRef::getImportLookupEntry( const import_lookup_table_entry32 *&Result) const { uintptr_t IntPtr = 0; - if (std::error_code EC = - OwningObject->getRvaPtr(ImportTable->ImportLookupTableRVA, IntPtr)) + uint32_t RVA = ImportTable[Index].ImportLookupTableRVA; + if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) return EC; Result = reinterpret_cast(IntPtr); return object_error::success; } +bool DelayImportDirectoryEntryRef:: +operator==(const DelayImportDirectoryEntryRef &Other) const { + return Table == Other.Table && Index == Other.Index; +} + +void DelayImportDirectoryEntryRef::moveNext() { + ++Index; +} + +imported_symbol_iterator +DelayImportDirectoryEntryRef::imported_symbol_begin() const { + return importedSymbolBegin(Table[Index].DelayImportNameTable, + OwningObject); +} + +imported_symbol_iterator +DelayImportDirectoryEntryRef::imported_symbol_end() const { + return importedSymbolEnd(Table[Index].DelayImportNameTable, + OwningObject); +} + +iterator_range +DelayImportDirectoryEntryRef::imported_symbols() const { + return make_range(imported_symbol_begin(), imported_symbol_end()); +} + +std::error_code DelayImportDirectoryEntryRef::getName(StringRef &Result) const { + uintptr_t IntPtr = 0; + if (std::error_code EC = OwningObject->getRvaPtr(Table[Index].Name, IntPtr)) + return EC; + Result = StringRef(reinterpret_cast(IntPtr)); + return object_error::success; +} + +std::error_code DelayImportDirectoryEntryRef:: +getDelayImportTable(const delay_import_directory_table_entry *&Result) const { + Result = Table; + return object_error::success; +} + +std::error_code DelayImportDirectoryEntryRef:: +getImportAddress(int AddrIndex, uint64_t &Result) const { + uint32_t RVA = Table[Index].DelayImportAddressTable + + AddrIndex * (OwningObject->is64() ? 8 : 4); + uintptr_t IntPtr = 0; + if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) + return EC; + if (OwningObject->is64()) + Result = *reinterpret_cast(IntPtr); + else + Result = *reinterpret_cast(IntPtr); + return object_error::success; +} + bool ExportDirectoryEntryRef:: operator==(const ExportDirectoryEntryRef &Other) const { return ExportTable == Other.ExportTable && Index == Other.Index; @@ -1112,12 +1394,98 @@ ExportDirectoryEntryRef::getSymbolName(StringRef &Result) const { return object_error::success; } -ErrorOr -ObjectFile::createCOFFObjectFile(std::unique_ptr Object) { +bool ImportedSymbolRef:: +operator==(const ImportedSymbolRef &Other) const { + return Entry32 == Other.Entry32 && Entry64 == Other.Entry64 + && Index == Other.Index; +} + +void ImportedSymbolRef::moveNext() { + ++Index; +} + +std::error_code +ImportedSymbolRef::getSymbolName(StringRef &Result) const { + uint32_t RVA; + if (Entry32) { + // If a symbol is imported only by ordinal, it has no name. + if (Entry32[Index].isOrdinal()) + return object_error::success; + RVA = Entry32[Index].getHintNameRVA(); + } else { + if (Entry64[Index].isOrdinal()) + return object_error::success; + RVA = Entry64[Index].getHintNameRVA(); + } + uintptr_t IntPtr = 0; + if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) + return EC; + // +2 because the first two bytes is hint. + Result = StringRef(reinterpret_cast(IntPtr + 2)); + return object_error::success; +} + +std::error_code ImportedSymbolRef::getOrdinal(uint16_t &Result) const { + uint32_t RVA; + if (Entry32) { + if (Entry32[Index].isOrdinal()) { + Result = Entry32[Index].getOrdinal(); + return object_error::success; + } + RVA = Entry32[Index].getHintNameRVA(); + } else { + if (Entry64[Index].isOrdinal()) { + Result = Entry64[Index].getOrdinal(); + return object_error::success; + } + RVA = Entry64[Index].getHintNameRVA(); + } + uintptr_t IntPtr = 0; + if (std::error_code EC = OwningObject->getRvaPtr(RVA, IntPtr)) + return EC; + Result = *reinterpret_cast(IntPtr); + return object_error::success; +} + +ErrorOr> +ObjectFile::createCOFFObjectFile(MemoryBufferRef Object) { std::error_code EC; - std::unique_ptr Ret( - new COFFObjectFile(std::move(Object), EC)); + std::unique_ptr Ret(new COFFObjectFile(Object, EC)); if (EC) return EC; - return Ret.release(); + return std::move(Ret); +} + +bool BaseRelocRef::operator==(const BaseRelocRef &Other) const { + return Header == Other.Header && Index == Other.Index; +} + +void BaseRelocRef::moveNext() { + // Header->BlockSize is the size of the current block, including the + // size of the header itself. + uint32_t Size = sizeof(*Header) + + sizeof(coff_base_reloc_block_entry) * (Index + 1); + if (Size == Header->BlockSize) { + // .reloc contains a list of base relocation blocks. Each block + // consists of the header followed by entries. The header contains + // how many entories will follow. When we reach the end of the + // current block, proceed to the next block. + Header = reinterpret_cast( + reinterpret_cast(Header) + Size); + Index = 0; + } else { + ++Index; + } +} + +std::error_code BaseRelocRef::getType(uint8_t &Type) const { + auto *Entry = reinterpret_cast(Header + 1); + Type = Entry[Index].getType(); + return object_error::success; +} + +std::error_code BaseRelocRef::getRVA(uint32_t &Result) const { + auto *Entry = reinterpret_cast(Header + 1); + Result = Header->PageRVA + Entry[Index].getOffset(); + return object_error::success; } diff --git a/lib/Object/COFFYAML.cpp b/lib/Object/COFFYAML.cpp index 49c5dda..9a24b53 100644 --- a/lib/Object/COFFYAML.cpp +++ b/lib/Object/COFFYAML.cpp @@ -168,6 +168,24 @@ void ScalarEnumerationTraits::enumeration( ECase(IMAGE_REL_AMD64_PAIR); ECase(IMAGE_REL_AMD64_SSPAN32); } + +void ScalarEnumerationTraits::enumeration( + IO &IO, COFF::WindowsSubsystem &Value) { + ECase(IMAGE_SUBSYSTEM_UNKNOWN); + ECase(IMAGE_SUBSYSTEM_NATIVE); + ECase(IMAGE_SUBSYSTEM_WINDOWS_GUI); + ECase(IMAGE_SUBSYSTEM_WINDOWS_CUI); + ECase(IMAGE_SUBSYSTEM_OS2_CUI); + ECase(IMAGE_SUBSYSTEM_POSIX_CUI); + ECase(IMAGE_SUBSYSTEM_NATIVE_WINDOWS); + ECase(IMAGE_SUBSYSTEM_WINDOWS_CE_GUI); + ECase(IMAGE_SUBSYSTEM_EFI_APPLICATION); + ECase(IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER); + ECase(IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER); + ECase(IMAGE_SUBSYSTEM_EFI_ROM); + ECase(IMAGE_SUBSYSTEM_XBOX); + ECase(IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION); +} #undef ECase #define BCase(X) IO.bitSetCase(Value, #X, COFF::X); @@ -214,6 +232,21 @@ void ScalarBitSetTraits::bitset( BCase(IMAGE_SCN_MEM_READ); BCase(IMAGE_SCN_MEM_WRITE); } + +void ScalarBitSetTraits::bitset( + IO &IO, COFF::DLLCharacteristics &Value) { + BCase(IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA); + BCase(IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE); + BCase(IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY); + BCase(IMAGE_DLL_CHARACTERISTICS_NX_COMPAT); + BCase(IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION); + BCase(IMAGE_DLL_CHARACTERISTICS_NO_SEH); + BCase(IMAGE_DLL_CHARACTERISTICS_NO_BIND); + BCase(IMAGE_DLL_CHARACTERISTICS_APPCONTAINER); + BCase(IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER); + BCase(IMAGE_DLL_CHARACTERISTICS_GUARD_CF); + BCase(IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE); +} #undef BCase namespace { @@ -285,6 +318,23 @@ struct NType { RelocType Type; }; +struct NWindowsSubsystem { + NWindowsSubsystem(IO &) : Subsystem(COFF::WindowsSubsystem(0)) {} + NWindowsSubsystem(IO &, uint16_t C) : Subsystem(COFF::WindowsSubsystem(C)) {} + uint16_t denormalize(IO &) { return Subsystem; } + + COFF::WindowsSubsystem Subsystem; +}; + +struct NDLLCharacteristics { + NDLLCharacteristics(IO &) : Characteristics(COFF::DLLCharacteristics(0)) {} + NDLLCharacteristics(IO &, uint16_t C) + : Characteristics(COFF::DLLCharacteristics(C)) {} + uint16_t denormalize(IO &) { return Characteristics; } + + COFF::DLLCharacteristics Characteristics; +}; + } void MappingTraits::mapping(IO &IO, @@ -306,6 +356,59 @@ void MappingTraits::mapping(IO &IO, } } +void MappingTraits::mapping(IO &IO, + COFF::DataDirectory &DD) { + IO.mapRequired("RelativeVirtualAddress", DD.RelativeVirtualAddress); + IO.mapRequired("Size", DD.Size); +} + +void MappingTraits::mapping(IO &IO, + COFFYAML::PEHeader &PH) { + MappingNormalization NWS(IO, + PH.Header.Subsystem); + MappingNormalization NDC( + IO, PH.Header.DLLCharacteristics); + + IO.mapRequired("AddressOfEntryPoint", PH.Header.AddressOfEntryPoint); + IO.mapRequired("ImageBase", PH.Header.ImageBase); + IO.mapRequired("SectionAlignment", PH.Header.SectionAlignment); + IO.mapRequired("FileAlignment", PH.Header.FileAlignment); + IO.mapRequired("MajorOperatingSystemVersion", + PH.Header.MajorOperatingSystemVersion); + IO.mapRequired("MinorOperatingSystemVersion", + PH.Header.MinorOperatingSystemVersion); + IO.mapRequired("MajorImageVersion", PH.Header.MajorImageVersion); + IO.mapRequired("MinorImageVersion", PH.Header.MinorImageVersion); + IO.mapRequired("MajorSubsystemVersion", PH.Header.MajorSubsystemVersion); + IO.mapRequired("MinorSubsystemVersion", PH.Header.MinorSubsystemVersion); + IO.mapRequired("Subsystem", NWS->Subsystem); + IO.mapRequired("DLLCharacteristics", NDC->Characteristics); + IO.mapRequired("SizeOfStackReserve", PH.Header.SizeOfStackReserve); + IO.mapRequired("SizeOfStackCommit", PH.Header.SizeOfStackCommit); + IO.mapRequired("SizeOfHeapReserve", PH.Header.SizeOfHeapReserve); + IO.mapRequired("SizeOfHeapCommit", PH.Header.SizeOfHeapCommit); + + IO.mapOptional("ExportTable", PH.DataDirectories[COFF::EXPORT_TABLE]); + IO.mapOptional("ImportTable", PH.DataDirectories[COFF::IMPORT_TABLE]); + IO.mapOptional("ResourceTable", PH.DataDirectories[COFF::RESOURCE_TABLE]); + IO.mapOptional("ExceptionTable", PH.DataDirectories[COFF::EXCEPTION_TABLE]); + IO.mapOptional("CertificateTable", PH.DataDirectories[COFF::CERTIFICATE_TABLE]); + IO.mapOptional("BaseRelocationTable", + PH.DataDirectories[COFF::BASE_RELOCATION_TABLE]); + IO.mapOptional("Debug", PH.DataDirectories[COFF::DEBUG]); + IO.mapOptional("Architecture", PH.DataDirectories[COFF::ARCHITECTURE]); + IO.mapOptional("GlobalPtr", PH.DataDirectories[COFF::GLOBAL_PTR]); + IO.mapOptional("TlsTable", PH.DataDirectories[COFF::TLS_TABLE]); + IO.mapOptional("LoadConfigTable", + PH.DataDirectories[COFF::LOAD_CONFIG_TABLE]); + IO.mapOptional("BoundImport", PH.DataDirectories[COFF::BOUND_IMPORT]); + IO.mapOptional("IAT", PH.DataDirectories[COFF::IAT]); + IO.mapOptional("DelayImportDescriptor", + PH.DataDirectories[COFF::DELAY_IMPORT_DESCRIPTOR]); + IO.mapOptional("ClrRuntimeHeader", + PH.DataDirectories[COFF::CLR_RUNTIME_HEADER]); +} + void MappingTraits::mapping(IO &IO, COFF::header &H) { MappingNormalization NM(IO, H.Machine); MappingNormalization NC(IO, @@ -380,12 +483,15 @@ void MappingTraits::mapping(IO &IO, COFFYAML::Section &Sec) { IO, Sec.Header.Characteristics); IO.mapRequired("Name", Sec.Name); IO.mapRequired("Characteristics", NC->Characteristics); + IO.mapOptional("VirtualAddress", Sec.Header.VirtualAddress, 0U); + IO.mapOptional("VirtualSize", Sec.Header.VirtualSize, 0U); IO.mapOptional("Alignment", Sec.Alignment); IO.mapRequired("SectionData", Sec.SectionData); IO.mapOptional("Relocations", Sec.Relocations); } void MappingTraits::mapping(IO &IO, COFFYAML::Object &Obj) { + IO.mapOptional("OptionalHeader", Obj.OptionalHeader); IO.mapRequired("header", Obj.Header); IO.mapRequired("sections", Obj.Sections); IO.mapRequired("symbols", Obj.Symbols); diff --git a/lib/Object/ELF.cpp b/lib/Object/ELF.cpp index d999106..398e9e4 100644 --- a/lib/Object/ELF.cpp +++ b/lib/Object/ELF.cpp @@ -12,705 +12,71 @@ namespace llvm { namespace object { -#define LLVM_ELF_SWITCH_RELOC_TYPE_NAME(enum) \ - case ELF::enum: \ - return #enum; \ +#define ELF_RELOC(name, value) \ + case ELF::name: \ + return #name; \ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { switch (Machine) { case ELF::EM_X86_64: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_32S); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPCREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_SIZE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_GOTPC32_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_TLSDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_X86_64_IRELATIVE); +#include "llvm/Support/ELFRelocs/x86_64.def" default: break; } break; case ELF::EM_386: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_32PLT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTIE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GD_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_PUSH); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDM_POP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LDO_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_LE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_386_IRELATIVE); +#include "llvm/Support/ELFRelocs/i386.def" default: break; } break; case ELF::EM_MIPS: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_LITERAL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_OFST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SUB); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_A); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_INSERT_B); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_DELETE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SCN_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_ADD_IMMEDIATE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PJUMP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_RELGOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JALR); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_GOTTPREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_TLS_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC21_S2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC26_S2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC18_S3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC19_S2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PCHI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PCLO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS16_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS16_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS16_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_26_S1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_PC16_S1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_CALL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_DISP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_GOT_OFST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_GD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_LDM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MICROMIPS_TLS_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_NUM); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC32); +#include "llvm/Support/ELFRelocs/Mips.def" default: break; } break; case ELF::EM_AARCH64: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_PREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G2_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_UABS_G3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_MOVW_SABS_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD_PREL_LO19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_LO21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_PREL_PG_HI21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADD_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST8_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TSTBR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CONDBR19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_JUMP26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_CALL26); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST16_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST32_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST64_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LDST128_ABS_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_ADR_GOT_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_LD64_GOT_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSIE_LD_GOTTPREL_PREL19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_MOVW_TPREL_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_HI12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_ADD_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADR_PAGE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_LD64_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_ADD_LO12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_AARCH64_TLSDESC_CALL); +#include "llvm/Support/ELFRelocs/AArch64.def" default: break; } break; case ELF::EM_ARM: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PC24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ABS5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BREL_ADJ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_SWI8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_XPC25); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_XPC22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_BASE_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_7_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_15_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PCREL_23_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SBREL_11_0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_19_12_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SBREL_27_20_CK); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_SBREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_V4BX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TARGET2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PREL31); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_ABS_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_PREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_ALU_PREL_11_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_PC12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ABS32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_REL32_NOI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_PC_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ALU_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDR_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDRS_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_LDC_SB_G2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL_NC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVT_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_MOVW_BREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GOTDESC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_DESCSEQ); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PLT32_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_ABS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_PREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOT_BREL12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTOFF12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GOTRELAX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTENTRY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_GNU_VTINHERIT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_JUMP8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LDO12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_LE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_TLS_IE12GP); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_4); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_7); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_9); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_13); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_PRIVATE_15); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_ME_TOO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_ARM_THM_TLS_DESCSEQ32); +#include "llvm/Support/ELFRelocs/ARM.def" default: break; } break; case ELF::EM_HEXAGON: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_0); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_1); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_2); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GPREL16_3); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_HL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B32_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B22_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B15_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B13_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B9_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_B7_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_12_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_10_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_9_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_8_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_7_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_32_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPMOD_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_PLT_B22_PCREL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_LO16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_HI16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_6_PCREL_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOTREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_DTPREL_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_GD_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_IE_GOT_11_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_32_6_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_16_X); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_HEX_TPREL_11_X); +#include "llvm/Support/ELFRelocs/Hexagon.def" default: break; } break; case ELF::EM_PPC: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_ADDR14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_PLTREL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HA); +#include "llvm/Support/ELFRelocs/PowerPC.def" default: break; } break; case ELF::EM_PPC64: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL24); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRNTAKEN); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHERA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHESTA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHERA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHESTA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO_DS); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHERA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHEST); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHESTA); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_LO); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HI); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HA); +#include "llvm/Support/ELFRelocs/PowerPC64.def" default: break; } break; case ELF::EM_S390: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPC); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT16DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT32DBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPCDBL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PC64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLTENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_PLTOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LOAD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDCALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE12); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDM64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_IEENT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LE64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_LDO64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPMOD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_DTPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_TPOFF); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_GOTPLT20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_TLS_GOTIE20); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_390_IRELATIVE); +#include "llvm/Support/ELFRelocs/SystemZ.def" default: break; } @@ -719,90 +85,7 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { case ELF::EM_SPARC32PLUS: case ELF::EM_SPARCV9: switch (Type) { - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_NONE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP8); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP30); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HI22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_13); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LO10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT13); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOT22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WPLT30); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_COPY); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GLOB_DAT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_JMP_SLOT); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_RELATIVE); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIPLT22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOPLT10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PCPLT10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_11); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_OLO10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HH22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HM10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LM22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HH22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_HM10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PC_LM22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_WDISP19); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_7); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_5); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_6); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_DISP64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_PLT64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_HIX22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_LOX10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_H44); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_M44); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_L44); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_REGISTER); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_UA16); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_HI22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_LO10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_ADD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_GD_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_HI22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_LO10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_ADD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDM_CALL); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_HIX22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_LOX10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LDO_ADD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_HI22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LO10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_LDX); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_IE_ADD); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_HIX22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_LE_LOX10); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPMOD64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_DTPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF32); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_TLS_TPOFF64); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_HIX22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_LOX22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_HIX22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP_LOX22); - LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_SPARC_GOTDATA_OP); +#include "llvm/Support/ELFRelocs/Sparc.def" default: break; } @@ -813,7 +96,7 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) { return "Unknown"; } -#undef LLVM_ELF_SWITCH_RELOC_TYPE_NAME +#undef ELF_RELOC } // end namespace object } // end namespace llvm diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp index 4f0f60b..8ccb253 100644 --- a/lib/Object/ELFObjectFile.cpp +++ b/lib/Object/ELFObjectFile.cpp @@ -17,61 +17,56 @@ namespace llvm { using namespace object; -ErrorOr -ObjectFile::createELFObjectFile(std::unique_ptr &Obj) { +ELFObjectFileBase::ELFObjectFileBase(unsigned int Type, MemoryBufferRef Source) + : ObjectFile(Type, Source) {} + +ErrorOr> +ObjectFile::createELFObjectFile(MemoryBufferRef Obj) { std::pair Ident = - getElfArchType(Obj->getBuffer()); + getElfArchType(Obj.getBuffer()); std::size_t MaxAlignment = - 1ULL << countTrailingZeros(uintptr_t(Obj->getBufferStart())); + 1ULL << countTrailingZeros(uintptr_t(Obj.getBufferStart())); std::error_code EC; std::unique_ptr R; if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 4) - R.reset(new ELFObjectFile>( - std::move(Obj), EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>( - std::move(Obj), EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else return object_error::parse_failed; else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 4) - R.reset(new ELFObjectFile>(std::move(Obj), - EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>(std::move(Obj), - EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else return object_error::parse_failed; else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 8) - R.reset(new ELFObjectFile>(std::move(Obj), - EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>(std::move(Obj), - EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else return object_error::parse_failed; else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) { #if !LLVM_IS_UNALIGNED_ACCESS_FAST if (MaxAlignment >= 8) - R.reset(new ELFObjectFile>( - std::move(Obj), EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else #endif if (MaxAlignment >= 2) - R.reset(new ELFObjectFile>( - std::move(Obj), EC)); + R.reset(new ELFObjectFile>(Obj, EC)); else return object_error::parse_failed; } @@ -80,7 +75,7 @@ ObjectFile::createELFObjectFile(std::unique_ptr &Obj) { if (EC) return EC; - return R.release(); + return std::move(R); } } // end namespace llvm diff --git a/lib/Object/ELFYAML.cpp b/lib/Object/ELFYAML.cpp index 6340841..7e35fb5 100644 --- a/lib/Object/ELFYAML.cpp +++ b/lib/Object/ELFYAML.cpp @@ -264,6 +264,7 @@ void ScalarBitSetTraits::bitset(IO &IO, BCase(EF_MIPS_CPIC) BCase(EF_MIPS_ABI2) BCase(EF_MIPS_32BITMODE) + BCase(EF_MIPS_NAN2008) BCase(EF_MIPS_ABI_O32) BCase(EF_MIPS_MICROMIPS) BCase(EF_MIPS_ARCH_ASE_M16) @@ -394,268 +395,53 @@ void ScalarEnumerationTraits::enumeration( #undef ECase } +void ScalarBitSetTraits::bitset(IO &IO, + ELFYAML::ELF_STO &Value) { + const auto *Object = static_cast(IO.getContext()); + assert(Object && "The IO context is not initialized"); +#define BCase(X) IO.bitSetCase(Value, #X, ELF::X); + switch (Object->Header.Machine) { + case ELF::EM_MIPS: + BCase(STO_MIPS_OPTIONAL) + BCase(STO_MIPS_PLT) + BCase(STO_MIPS_PIC) + BCase(STO_MIPS_MICROMIPS) + break; + default: + break; // Nothing to do + } +#undef BCase +#undef BCaseMask +} + void ScalarEnumerationTraits::enumeration( IO &IO, ELFYAML::ELF_REL &Value) { const auto *Object = static_cast(IO.getContext()); assert(Object && "The IO context is not initialized"); -#define ECase(X) IO.enumCase(Value, #X, ELF::X); +#define ELF_RELOC(X, Y) IO.enumCase(Value, #X, ELF::X); switch (Object->Header.Machine) { case ELF::EM_X86_64: - ECase(R_X86_64_NONE) - ECase(R_X86_64_64) - ECase(R_X86_64_PC32) - ECase(R_X86_64_GOT32) - ECase(R_X86_64_PLT32) - ECase(R_X86_64_COPY) - ECase(R_X86_64_GLOB_DAT) - ECase(R_X86_64_JUMP_SLOT) - ECase(R_X86_64_RELATIVE) - ECase(R_X86_64_GOTPCREL) - ECase(R_X86_64_32) - ECase(R_X86_64_32S) - ECase(R_X86_64_16) - ECase(R_X86_64_PC16) - ECase(R_X86_64_8) - ECase(R_X86_64_PC8) - ECase(R_X86_64_DTPMOD64) - ECase(R_X86_64_DTPOFF64) - ECase(R_X86_64_TPOFF64) - ECase(R_X86_64_TLSGD) - ECase(R_X86_64_TLSLD) - ECase(R_X86_64_DTPOFF32) - ECase(R_X86_64_GOTTPOFF) - ECase(R_X86_64_TPOFF32) - ECase(R_X86_64_PC64) - ECase(R_X86_64_GOTOFF64) - ECase(R_X86_64_GOTPC32) - ECase(R_X86_64_GOT64) - ECase(R_X86_64_GOTPCREL64) - ECase(R_X86_64_GOTPC64) - ECase(R_X86_64_GOTPLT64) - ECase(R_X86_64_PLTOFF64) - ECase(R_X86_64_SIZE32) - ECase(R_X86_64_SIZE64) - ECase(R_X86_64_GOTPC32_TLSDESC) - ECase(R_X86_64_TLSDESC_CALL) - ECase(R_X86_64_TLSDESC) - ECase(R_X86_64_IRELATIVE) +#include "llvm/Support/ELFRelocs/x86_64.def" break; case ELF::EM_MIPS: - ECase(R_MIPS_NONE) - ECase(R_MIPS_16) - ECase(R_MIPS_32) - ECase(R_MIPS_REL32) - ECase(R_MIPS_26) - ECase(R_MIPS_HI16) - ECase(R_MIPS_LO16) - ECase(R_MIPS_GPREL16) - ECase(R_MIPS_LITERAL) - ECase(R_MIPS_GOT16) - ECase(R_MIPS_PC16) - ECase(R_MIPS_CALL16) - ECase(R_MIPS_GPREL32) - ECase(R_MIPS_UNUSED1) - ECase(R_MIPS_UNUSED2) - ECase(R_MIPS_SHIFT5) - ECase(R_MIPS_SHIFT6) - ECase(R_MIPS_64) - ECase(R_MIPS_GOT_DISP) - ECase(R_MIPS_GOT_PAGE) - ECase(R_MIPS_GOT_OFST) - ECase(R_MIPS_GOT_HI16) - ECase(R_MIPS_GOT_LO16) - ECase(R_MIPS_SUB) - ECase(R_MIPS_INSERT_A) - ECase(R_MIPS_INSERT_B) - ECase(R_MIPS_DELETE) - ECase(R_MIPS_HIGHER) - ECase(R_MIPS_HIGHEST) - ECase(R_MIPS_CALL_HI16) - ECase(R_MIPS_CALL_LO16) - ECase(R_MIPS_SCN_DISP) - ECase(R_MIPS_REL16) - ECase(R_MIPS_ADD_IMMEDIATE) - ECase(R_MIPS_PJUMP) - ECase(R_MIPS_RELGOT) - ECase(R_MIPS_JALR) - ECase(R_MIPS_TLS_DTPMOD32) - ECase(R_MIPS_TLS_DTPREL32) - ECase(R_MIPS_TLS_DTPMOD64) - ECase(R_MIPS_TLS_DTPREL64) - ECase(R_MIPS_TLS_GD) - ECase(R_MIPS_TLS_LDM) - ECase(R_MIPS_TLS_DTPREL_HI16) - ECase(R_MIPS_TLS_DTPREL_LO16) - ECase(R_MIPS_TLS_GOTTPREL) - ECase(R_MIPS_TLS_TPREL32) - ECase(R_MIPS_TLS_TPREL64) - ECase(R_MIPS_TLS_TPREL_HI16) - ECase(R_MIPS_TLS_TPREL_LO16) - ECase(R_MIPS_GLOB_DAT) - ECase(R_MIPS_PC21_S2) - ECase(R_MIPS_PC26_S2) - ECase(R_MIPS_PC18_S3) - ECase(R_MIPS_PC19_S2) - ECase(R_MIPS_PCHI16) - ECase(R_MIPS_PCLO16) - ECase(R_MIPS16_GOT16) - ECase(R_MIPS16_HI16) - ECase(R_MIPS16_LO16) - ECase(R_MIPS_COPY) - ECase(R_MIPS_JUMP_SLOT) - ECase(R_MICROMIPS_26_S1) - ECase(R_MICROMIPS_HI16) - ECase(R_MICROMIPS_LO16) - ECase(R_MICROMIPS_GOT16) - ECase(R_MICROMIPS_PC16_S1) - ECase(R_MICROMIPS_CALL16) - ECase(R_MICROMIPS_GOT_DISP) - ECase(R_MICROMIPS_GOT_PAGE) - ECase(R_MICROMIPS_GOT_OFST) - ECase(R_MICROMIPS_TLS_GD) - ECase(R_MICROMIPS_TLS_LDM) - ECase(R_MICROMIPS_TLS_DTPREL_HI16) - ECase(R_MICROMIPS_TLS_DTPREL_LO16) - ECase(R_MICROMIPS_TLS_TPREL_HI16) - ECase(R_MICROMIPS_TLS_TPREL_LO16) - ECase(R_MIPS_NUM) - ECase(R_MIPS_PC32) +#include "llvm/Support/ELFRelocs/Mips.def" break; case ELF::EM_HEXAGON: - ECase(R_HEX_NONE) - ECase(R_HEX_B22_PCREL) - ECase(R_HEX_B15_PCREL) - ECase(R_HEX_B7_PCREL) - ECase(R_HEX_LO16) - ECase(R_HEX_HI16) - ECase(R_HEX_32) - ECase(R_HEX_16) - ECase(R_HEX_8) - ECase(R_HEX_GPREL16_0) - ECase(R_HEX_GPREL16_1) - ECase(R_HEX_GPREL16_2) - ECase(R_HEX_GPREL16_3) - ECase(R_HEX_HL16) - ECase(R_HEX_B13_PCREL) - ECase(R_HEX_B9_PCREL) - ECase(R_HEX_B32_PCREL_X) - ECase(R_HEX_32_6_X) - ECase(R_HEX_B22_PCREL_X) - ECase(R_HEX_B15_PCREL_X) - ECase(R_HEX_B13_PCREL_X) - ECase(R_HEX_B9_PCREL_X) - ECase(R_HEX_B7_PCREL_X) - ECase(R_HEX_16_X) - ECase(R_HEX_12_X) - ECase(R_HEX_11_X) - ECase(R_HEX_10_X) - ECase(R_HEX_9_X) - ECase(R_HEX_8_X) - ECase(R_HEX_7_X) - ECase(R_HEX_6_X) - ECase(R_HEX_32_PCREL) - ECase(R_HEX_COPY) - ECase(R_HEX_GLOB_DAT) - ECase(R_HEX_JMP_SLOT) - ECase(R_HEX_RELATIVE) - ECase(R_HEX_PLT_B22_PCREL) - ECase(R_HEX_GOTREL_LO16) - ECase(R_HEX_GOTREL_HI16) - ECase(R_HEX_GOTREL_32) - ECase(R_HEX_GOT_LO16) - ECase(R_HEX_GOT_HI16) - ECase(R_HEX_GOT_32) - ECase(R_HEX_GOT_16) - ECase(R_HEX_DTPMOD_32) - ECase(R_HEX_DTPREL_LO16) - ECase(R_HEX_DTPREL_HI16) - ECase(R_HEX_DTPREL_32) - ECase(R_HEX_DTPREL_16) - ECase(R_HEX_GD_PLT_B22_PCREL) - ECase(R_HEX_GD_GOT_LO16) - ECase(R_HEX_GD_GOT_HI16) - ECase(R_HEX_GD_GOT_32) - ECase(R_HEX_GD_GOT_16) - ECase(R_HEX_IE_LO16) - ECase(R_HEX_IE_HI16) - ECase(R_HEX_IE_32) - ECase(R_HEX_IE_GOT_LO16) - ECase(R_HEX_IE_GOT_HI16) - ECase(R_HEX_IE_GOT_32) - ECase(R_HEX_IE_GOT_16) - ECase(R_HEX_TPREL_LO16) - ECase(R_HEX_TPREL_HI16) - ECase(R_HEX_TPREL_32) - ECase(R_HEX_TPREL_16) - ECase(R_HEX_6_PCREL_X) - ECase(R_HEX_GOTREL_32_6_X) - ECase(R_HEX_GOTREL_16_X) - ECase(R_HEX_GOTREL_11_X) - ECase(R_HEX_GOT_32_6_X) - ECase(R_HEX_GOT_16_X) - ECase(R_HEX_GOT_11_X) - ECase(R_HEX_DTPREL_32_6_X) - ECase(R_HEX_DTPREL_16_X) - ECase(R_HEX_DTPREL_11_X) - ECase(R_HEX_GD_GOT_32_6_X) - ECase(R_HEX_GD_GOT_16_X) - ECase(R_HEX_GD_GOT_11_X) - ECase(R_HEX_IE_32_6_X) - ECase(R_HEX_IE_16_X) - ECase(R_HEX_IE_GOT_32_6_X) - ECase(R_HEX_IE_GOT_16_X) - ECase(R_HEX_IE_GOT_11_X) - ECase(R_HEX_TPREL_32_6_X) - ECase(R_HEX_TPREL_16_X) - ECase(R_HEX_TPREL_11_X) +#include "llvm/Support/ELFRelocs/Hexagon.def" break; case ELF::EM_386: - ECase(R_386_NONE) - ECase(R_386_32) - ECase(R_386_PC32) - ECase(R_386_GOT32) - ECase(R_386_PLT32) - ECase(R_386_COPY) - ECase(R_386_GLOB_DAT) - ECase(R_386_JUMP_SLOT) - ECase(R_386_RELATIVE) - ECase(R_386_GOTOFF) - ECase(R_386_GOTPC) - ECase(R_386_32PLT) - ECase(R_386_TLS_TPOFF) - ECase(R_386_TLS_IE) - ECase(R_386_TLS_GOTIE) - ECase(R_386_TLS_LE) - ECase(R_386_TLS_GD) - ECase(R_386_TLS_LDM) - ECase(R_386_16) - ECase(R_386_PC16) - ECase(R_386_8) - ECase(R_386_PC8) - ECase(R_386_TLS_GD_32) - ECase(R_386_TLS_GD_PUSH) - ECase(R_386_TLS_GD_CALL) - ECase(R_386_TLS_GD_POP) - ECase(R_386_TLS_LDM_32) - ECase(R_386_TLS_LDM_PUSH) - ECase(R_386_TLS_LDM_CALL) - ECase(R_386_TLS_LDM_POP) - ECase(R_386_TLS_LDO_32) - ECase(R_386_TLS_IE_32) - ECase(R_386_TLS_LE_32) - ECase(R_386_TLS_DTPMOD32) - ECase(R_386_TLS_DTPOFF32) - ECase(R_386_TLS_TPOFF32) - ECase(R_386_TLS_GOTDESC) - ECase(R_386_TLS_DESC_CALL) - ECase(R_386_TLS_DESC) - ECase(R_386_IRELATIVE) - ECase(R_386_NUM) +#include "llvm/Support/ELFRelocs/i386.def" + break; + case ELF::EM_AARCH64: +#include "llvm/Support/ELFRelocs/AArch64.def" + break; + case ELF::EM_ARM: +#include "llvm/Support/ELFRelocs/ARM.def" break; default: llvm_unreachable("Unsupported architecture"); } -#undef ECase +#undef ELF_RELOC } void MappingTraits::mapping(IO &IO, @@ -669,13 +455,30 @@ void MappingTraits::mapping(IO &IO, IO.mapOptional("Entry", FileHdr.Entry, Hex64(0)); } +namespace { +struct NormalizedOther { + NormalizedOther(IO &) + : Visibility(ELFYAML::ELF_STV(0)), Other(ELFYAML::ELF_STO(0)) {} + NormalizedOther(IO &, uint8_t Original) + : Visibility(Original & 0x3), Other(Original & ~0x3) {} + + uint8_t denormalize(IO &) { return Visibility | Other; } + + ELFYAML::ELF_STV Visibility; + ELFYAML::ELF_STO Other; +}; +} + void MappingTraits::mapping(IO &IO, ELFYAML::Symbol &Symbol) { IO.mapOptional("Name", Symbol.Name, StringRef()); IO.mapOptional("Type", Symbol.Type, ELFYAML::ELF_STT(0)); IO.mapOptional("Section", Symbol.Section, StringRef()); IO.mapOptional("Value", Symbol.Value, Hex64(0)); IO.mapOptional("Size", Symbol.Size, Hex64(0)); - IO.mapOptional("Visibility", Symbol.Visibility, ELFYAML::ELF_STV(0)); + + MappingNormalization Keys(IO, Symbol.Other); + IO.mapOptional("Visibility", Keys->Visibility, ELFYAML::ELF_STV(0)); + IO.mapOptional("Other", Keys->Other, ELFYAML::ELF_STO(0)); } void MappingTraits::mapping( diff --git a/lib/Object/Error.cpp b/lib/Object/Error.cpp index 9d25269..d2daab7 100644 --- a/lib/Object/Error.cpp +++ b/lib/Object/Error.cpp @@ -13,6 +13,7 @@ #include "llvm/Object/Error.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" using namespace llvm; using namespace object; @@ -25,7 +26,7 @@ public: }; } -const char *_object_error_category::name() const { +const char *_object_error_category::name() const LLVM_NOEXCEPT { return "llvm.object"; } @@ -41,12 +42,15 @@ std::string _object_error_category::message(int EV) const { return "Invalid data was encountered while parsing the file"; case object_error::unexpected_eof: return "The end of the file was unexpectedly encountered"; + case object_error::bitcode_section_not_found: + return "Bitcode section not found in object file"; } llvm_unreachable("An enumerator of object_error does not have a message " "defined."); } +static ManagedStatic<_object_error_category> error_category; + const std::error_category &object::object_category() { - static _object_error_category o; - return o; + return *error_category; } diff --git a/lib/Object/IRObjectFile.cpp b/lib/Object/IRObjectFile.cpp index 5323d92..423ed9e 100644 --- a/lib/Object/IRObjectFile.cpp +++ b/lib/Object/IRObjectFile.cpp @@ -14,17 +14,18 @@ #include "llvm/Object/IRObjectFile.h" #include "RecordStreamer.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/IR/LLVMContext.h" #include "llvm/IR/GVMaterializer.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" -#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCTargetAsmParser.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" @@ -32,9 +33,8 @@ using namespace llvm; using namespace object; -IRObjectFile::IRObjectFile(std::unique_ptr Object, - std::unique_ptr Mod) - : SymbolicFile(Binary::ID_IR, std::move(Object)), M(std::move(Mod)) { +IRObjectFile::IRObjectFile(MemoryBufferRef Object, std::unique_ptr Mod) + : SymbolicFile(Binary::ID_IR, Object), M(std::move(Mod)) { // If we have a DataLayout, setup a mangler. const DataLayout *DL = M->getDataLayout(); if (!DL) @@ -76,7 +76,7 @@ IRObjectFile::IRObjectFile(std::unique_ptr Object, std::unique_ptr Buffer(MemoryBuffer::getMemBuffer(InlineAsm)); SourceMgr SrcMgr; - SrcMgr.AddNewSourceBuffer(Buffer.release(), SMLoc()); + SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr Parser( createMCAsmParser(SrcMgr, MCCtx, *Streamer, *MAI)); @@ -114,12 +114,9 @@ IRObjectFile::IRObjectFile(std::unique_ptr Object, } IRObjectFile::~IRObjectFile() { - GVMaterializer *GVM = M->getMaterializer(); - if (GVM) - GVM->releaseBuffer(); } -static const GlobalValue *getGV(DataRefImpl &Symb) { +static GlobalValue *getGV(DataRefImpl &Symb) { if ((Symb.p & 3) == 3) return nullptr; @@ -184,6 +181,8 @@ void IRObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Res = (Index << 2) | 3; break; } + default: + llvm_unreachable("unreachable case"); } Symb.p = Res; @@ -207,16 +206,6 @@ std::error_code IRObjectFile::printSymbolName(raw_ostream &OS, return object_error::success; } -static bool isDeclaration(const GlobalValue &V) { - if (V.hasAvailableExternallyLinkage()) - return true; - - if (V.isMaterializable()) - return false; - - return V.isDeclaration(); -} - uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { const GlobalValue *GV = getGV(Symb); @@ -227,7 +216,7 @@ uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { } uint32_t Res = BasicSymbolRef::SF_None; - if (isDeclaration(*GV)) + if (GV->isDeclarationForLinker()) Res |= BasicSymbolRef::SF_Undefined; if (GV->hasPrivateLinkage()) Res |= BasicSymbolRef::SF_FormatSpecific; @@ -248,10 +237,9 @@ uint32_t IRObjectFile::getSymbolFlags(DataRefImpl Symb) const { return Res; } -const GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) const { - const GlobalValue *GV = getGV(Symb); - return GV; -} +GlobalValue *IRObjectFile::getSymbolGV(DataRefImpl Symb) { return getGV(Symb); } + +std::unique_ptr IRObjectFile::takeModule() { return std::move(M); } basic_symbol_iterator IRObjectFile::symbol_begin_impl() const { Module::const_iterator I = M->begin(); @@ -268,12 +256,55 @@ basic_symbol_iterator IRObjectFile::symbol_end_impl() const { return basic_symbol_iterator(BasicSymbolRef(Ret, this)); } -ErrorOr llvm::object::IRObjectFile::createIRObjectFile( - std::unique_ptr Object, LLVMContext &Context) { - ErrorOr MOrErr = getLazyBitcodeModule(Object.get(), Context); +ErrorOr IRObjectFile::findBitcodeInObject(const ObjectFile &Obj) { + for (const SectionRef &Sec : Obj.sections()) { + StringRef SecName; + if (std::error_code EC = Sec.getName(SecName)) + return EC; + if (SecName == ".llvmbc") { + StringRef SecContents; + if (std::error_code EC = Sec.getContents(SecContents)) + return EC; + return MemoryBufferRef(SecContents, Obj.getFileName()); + } + } + + return object_error::bitcode_section_not_found; +} + +ErrorOr IRObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { + sys::fs::file_magic Type = sys::fs::identify_magic(Object.getBuffer()); + switch (Type) { + case sys::fs::file_magic::bitcode: + return Object; + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::coff_object: { + ErrorOr> ObjFile = + ObjectFile::createObjectFile(Object, Type); + if (!ObjFile) + return ObjFile.getError(); + return findBitcodeInObject(*ObjFile->get()); + } + default: + return object_error::invalid_file_type; + } +} + +ErrorOr> +llvm::object::IRObjectFile::create(MemoryBufferRef Object, + LLVMContext &Context) { + ErrorOr BCOrErr = findBitcodeInMemBuffer(Object); + if (!BCOrErr) + return BCOrErr.getError(); + + std::unique_ptr Buff( + MemoryBuffer::getMemBuffer(BCOrErr.get(), false)); + + ErrorOr MOrErr = getLazyBitcodeModule(std::move(Buff), Context); if (std::error_code EC = MOrErr.getError()) return EC; std::unique_ptr M(MOrErr.get()); - return new IRObjectFile(std::move(Object), std::move(M)); + return llvm::make_unique(Object, std::move(M)); } diff --git a/lib/Object/MachOObjectFile.cpp b/lib/Object/MachOObjectFile.cpp index 51c4c33..e476976 100644 --- a/lib/Object/MachOObjectFile.cpp +++ b/lib/Object/MachOObjectFile.cpp @@ -14,10 +14,14 @@ #include "llvm/Object/MachO.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataExtractor.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" #include "llvm/Support/Host.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/MachO.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include @@ -54,6 +58,17 @@ getSegmentLoadCommandNumSections(const MachOObjectFile *O, return S.nsects; } +static bool isPageZeroSegment(const MachOObjectFile *O, + const MachOObjectFile::LoadCommandInfo &L) { + if (O->is64Bit()) { + MachO::segment_command_64 S = O->getSegment64LoadCommand(L); + return StringRef("__PAGEZERO").equals(S.segname); + } + MachO::segment_command S = O->getSegmentLoadCommand(L); + return StringRef("__PAGEZERO").equals(S.segname); +} + + static const char * getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, unsigned Sec) { @@ -129,11 +144,9 @@ static void printRelocationTargetName(const MachOObjectFile *O, // to find a section beginning instead. for (const SectionRef &Section : O->sections()) { std::error_code ec; - uint64_t Addr; - StringRef Name; - if ((ec = Section.getAddress(Addr))) - report_fatal_error(ec.message()); + StringRef Name; + uint64_t Addr = Section.getAddress(); if (Addr != Val) continue; if ((ec = Section.getName(Name))) @@ -206,11 +219,6 @@ static unsigned getPlainRelocationType(const MachOObjectFile *O, return RE.r_word1 & 0xf; } -static unsigned -getScatteredRelocationType(const MachO::any_relocation_info &RE) { - return (RE.r_word0 >> 24) & 0xf; -} - static uint32_t getSectionFlags(const MachOObjectFile *O, DataRefImpl Sec) { if (O->is64Bit()) { @@ -221,33 +229,65 @@ static uint32_t getSectionFlags(const MachOObjectFile *O, return Sect.flags; } -MachOObjectFile::MachOObjectFile(std::unique_ptr Object, - bool IsLittleEndian, bool Is64bits, - std::error_code &EC) - : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)), +MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, + bool Is64bits, std::error_code &EC) + : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), - DataInCodeLoadCmd(nullptr) { + DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr), + UuidLoadCmd(nullptr), HasPageZeroSegment(false) { uint32_t LoadCommandCount = this->getHeader().ncmds; + if (LoadCommandCount == 0) + return; + MachO::LoadCommandType SegmentLoadType = is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); for (unsigned I = 0; ; ++I) { if (Load.C.cmd == MachO::LC_SYMTAB) { - assert(!SymtabLoadCmd && "Multiple symbol tables"); + // Multiple symbol tables + if (SymtabLoadCmd) { + EC = object_error::parse_failed; + return; + } SymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { - assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); + // Multiple dynamic symbol tables + if (DysymtabLoadCmd) { + EC = object_error::parse_failed; + return; + } DysymtabLoadCmd = Load.Ptr; } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { - assert(!DataInCodeLoadCmd && "Multiple data in code tables"); + // Multiple data in code tables + if (DataInCodeLoadCmd) { + EC = object_error::parse_failed; + return; + } DataInCodeLoadCmd = Load.Ptr; + } else if (Load.C.cmd == MachO::LC_DYLD_INFO || + Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { + // Multiple dyldinfo load commands + if (DyldInfoLoadCmd) { + EC = object_error::parse_failed; + return; + } + DyldInfoLoadCmd = Load.Ptr; + } else if (Load.C.cmd == MachO::LC_UUID) { + // Multiple UUID load commands + if (UuidLoadCmd) { + EC = object_error::parse_failed; + return; + } + UuidLoadCmd = Load.Ptr; } else if (Load.C.cmd == SegmentLoadType) { uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); for (unsigned J = 0; J < NumSections; ++J) { const char *Sec = getSectionPtr(this, Load, J); Sections.push_back(Sec); } + if (isPageZeroSegment(this, Load)) + HasPageZeroSegment = true; } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || @@ -279,6 +319,12 @@ std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, return object_error::success; } +unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { + DataRefImpl DRI = Sec.getRawDataRefImpl(); + uint32_t Flags = getSectionFlags(this, DRI); + return Flags & MachO::SECTION_TYPE; +} + // getIndirectName() returns the name of the alias'ed symbol who's string table // index is in the n_value field. std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, @@ -373,11 +419,10 @@ std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, EndOffset = Value; } if (!EndOffset) { - uint64_t Size; DataRefImpl Sec; Sec.d.a = SectionIndex-1; - getSectionSize(Sec, Size); - getSectionAddress(Sec, EndOffset); + uint64_t Size = getSectionSize(Sec); + EndOffset = getSectionAddress(Sec); EndOffset += Size; } Result = EndOffset - BeginOffset; @@ -438,6 +483,9 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) Result |= SymbolRef::SF_Weak; + if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) + Result |= SymbolRef::SF_Thumb; + if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) Result |= SymbolRef::SF_Absolute; @@ -471,29 +519,16 @@ std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, return object_error::success; } -std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, - uint64_t &Res) const { - if (is64Bit()) { - MachO::section_64 Sect = getSection64(Sec); - Res = Sect.addr; - } else { - MachO::section Sect = getSection(Sec); - Res = Sect.addr; - } - return object_error::success; +uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { + if (is64Bit()) + return getSection64(Sec).addr; + return getSection(Sec).addr; } -std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, - uint64_t &Res) const { - if (is64Bit()) { - MachO::section_64 Sect = getSection64(Sec); - Res = Sect.size; - } else { - MachO::section Sect = getSection(Sec); - Res = Sect.size; - } - - return object_error::success; +uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { + if (is64Bit()) + return getSection64(Sec).size; + return getSection(Sec).size; } std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, @@ -515,8 +550,7 @@ std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, return object_error::success; } -std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, - uint64_t &Res) const { +uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { uint32_t Align; if (is64Bit()) { MachO::section_64 Sect = getSection64(Sec); @@ -526,92 +560,49 @@ std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, Align = Sect.align; } - Res = uint64_t(1) << Align; - return object_error::success; -} - -std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, - bool &Res) const { - uint32_t Flags = getSectionFlags(this, Sec); - Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; - return object_error::success; + return uint64_t(1) << Align; } -std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, - bool &Result) const { +bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { uint32_t Flags = getSectionFlags(this, Sec); - unsigned SectionType = Flags & MachO::SECTION_TYPE; - Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && - !(SectionType == MachO::S_ZEROFILL || - SectionType == MachO::S_GB_ZEROFILL); - return object_error::success; + return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; } -std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, - bool &Result) const { +bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { uint32_t Flags = getSectionFlags(this, Sec); unsigned SectionType = Flags & MachO::SECTION_TYPE; - Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && - (SectionType == MachO::S_ZEROFILL || - SectionType == MachO::S_GB_ZEROFILL); - return object_error::success; -} - -std::error_code -MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, - bool &Result) const { - // FIXME: Unimplemented. - Result = true; - return object_error::success; -} - -std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, - bool &Result) const { - // FIXME: Unimplemented. - Result = false; - return object_error::success; + return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && + !(SectionType == MachO::S_ZEROFILL || + SectionType == MachO::S_GB_ZEROFILL); } -std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, - bool &Res) const { +bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { uint32_t Flags = getSectionFlags(this, Sec); unsigned SectionType = Flags & MachO::SECTION_TYPE; - Res = SectionType == MachO::S_ZEROFILL || - SectionType == MachO::S_GB_ZEROFILL; - return object_error::success; + return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && + (SectionType == MachO::S_ZEROFILL || + SectionType == MachO::S_GB_ZEROFILL); } -std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, - bool &Result) const { - // Consider using the code from isSectionText to look for __const sections. - // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS - // to use section attributes to distinguish code from data. - +bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { // FIXME: Unimplemented. - Result = false; - return object_error::success; + return false; } -std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, - DataRefImpl Symb, - bool &Result) const { +bool MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, + DataRefImpl Symb) const { SymbolRef::Type ST; this->getSymbolType(Symb, ST); - if (ST == SymbolRef::ST_Unknown) { - Result = false; - return object_error::success; - } + if (ST == SymbolRef::ST_Unknown) + return false; - uint64_t SectBegin, SectEnd; - getSectionAddress(Sec, SectBegin); - getSectionSize(Sec, SectEnd); + uint64_t SectBegin = getSectionAddress(Sec); + uint64_t SectEnd = getSectionSize(Sec); SectEnd += SectBegin; uint64_t SymAddr; getSymbolAddress(Symb, SymAddr); - Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); - - return object_error::success; + return (SymAddr >= SectBegin) && (SymAddr < SectEnd); } relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { @@ -649,8 +640,7 @@ std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, DataRefImpl Sec; Sec.d.a = Rel.d.a; - uint64_t SecAddress; - getSectionAddress(Sec, SecAddress); + uint64_t SecAddress = getSectionAddress(Sec); Res = SecAddress + Offset; return object_error::success; } @@ -755,7 +745,6 @@ MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, res = Table[RType]; break; } - case Triple::arm64: case Triple::aarch64: { static const char *const Table[] = { "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", @@ -1009,16 +998,6 @@ std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, return object_error::success; } -std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, - LibraryRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); -} - -std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, - StringRef &Res) const { - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); -} - // // guessLibraryShortName() is passed a name of a dynamic library and returns a // guess on what the short name is. Then name is returned as a substring of the @@ -1167,31 +1146,26 @@ guess_qtx: // It is passed the index (0 - based) of the library as translated from // GET_LIBRARY_ORDINAL (1 - based). std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, - StringRef &Res) { + StringRef &Res) const { if (Index >= Libraries.size()) return object_error::parse_failed; - MachO::dylib_command D = - getStruct(this, Libraries[Index]); - if (D.dylib.name >= D.cmdsize) - return object_error::parse_failed; - // If the cache of LibrariesShortNames is not built up do that first for // all the Libraries. if (LibrariesShortNames.size() == 0) { for (unsigned i = 0; i < Libraries.size(); i++) { MachO::dylib_command D = getStruct(this, Libraries[i]); - if (D.dylib.name >= D.cmdsize) { - LibrariesShortNames.push_back(StringRef()); - continue; - } + if (D.dylib.name >= D.cmdsize) + return object_error::parse_failed; const char *P = (const char *)(Libraries[i]) + D.dylib.name; StringRef Name = StringRef(P); + if (D.dylib.name+Name.size() >= D.cmdsize) + return object_error::parse_failed; StringRef Suffix; bool isFramework; StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); - if (shortName == StringRef()) + if (shortName.empty()) LibrariesShortNames.push_back(Name); else LibrariesShortNames.push_back(shortName); @@ -1246,16 +1220,6 @@ section_iterator MachOObjectFile::section_end() const { return section_iterator(SectionRef(DRI, this)); } -library_iterator MachOObjectFile::needed_library_begin() const { - // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); -} - -library_iterator MachOObjectFile::needed_library_end() const { - // TODO: implement - report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); -} - uint8_t MachOObjectFile::getBytesInAddress() const { return is64Bit() ? 8 : 4; } @@ -1271,17 +1235,10 @@ StringRef MachOObjectFile::getFileFormatName() const { case llvm::MachO::CPU_TYPE_POWERPC: return "Mach-O 32-bit ppc"; default: - assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && - "64-bit object file when we're not 64-bit?"); return "Mach-O 32-bit unknown"; } } - // Make sure the cpu type has the correct mask. - assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) - == llvm::MachO::CPU_ARCH_ABI64 && - "32-bit object file when we're 64-bit?"); - switch (CPUType) { case llvm::MachO::CPU_TYPE_X86_64: return "Mach-O 64-bit x86-64"; @@ -1303,7 +1260,7 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { case llvm::MachO::CPU_TYPE_ARM: return Triple::arm; case llvm::MachO::CPU_TYPE_ARM64: - return Triple::arm64; + return Triple::aarch64; case llvm::MachO::CPU_TYPE_POWERPC: return Triple::ppc; case llvm::MachO::CPU_TYPE_POWERPC64: @@ -1313,7 +1270,11 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { } } -Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { +Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault) { + if (McpuDefault) + *McpuDefault = nullptr; + switch (CPUType) { case MachO::CPU_TYPE_I386: switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { @@ -1337,15 +1298,25 @@ Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { return Triple("armv4t-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V5TEJ: return Triple("armv5e-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_XSCALE: + return Triple("xscale-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V6: return Triple("armv6-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V6M: + if (McpuDefault) + *McpuDefault = "cortex-m0"; return Triple("armv6m-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7: + return Triple("armv7-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7EM: + if (McpuDefault) + *McpuDefault = "cortex-m4"; return Triple("armv7em-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7K: return Triple("armv7k-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7M: + if (McpuDefault) + *McpuDefault = "cortex-m3"; return Triple("armv7m-apple-darwin"); case MachO::CPU_SUBTYPE_ARM_V7S: return Triple("armv7s-apple-darwin"); @@ -1378,50 +1349,102 @@ Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) { } } +Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault) { + if (McpuDefault) + *McpuDefault = nullptr; + + switch (CPUType) { + case MachO::CPU_TYPE_ARM: + switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { + case MachO::CPU_SUBTYPE_ARM_V4T: + return Triple("thumbv4t-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V5TEJ: + return Triple("thumbv5e-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_XSCALE: + return Triple("xscale-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V6: + return Triple("thumbv6-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V6M: + if (McpuDefault) + *McpuDefault = "cortex-m0"; + return Triple("thumbv6m-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7: + return Triple("thumbv7-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7EM: + if (McpuDefault) + *McpuDefault = "cortex-m4"; + return Triple("thumbv7em-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7K: + return Triple("thumbv7k-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7M: + if (McpuDefault) + *McpuDefault = "cortex-m3"; + return Triple("thumbv7m-apple-darwin"); + case MachO::CPU_SUBTYPE_ARM_V7S: + return Triple("thumbv7s-apple-darwin"); + default: + return Triple(); + } + default: + return Triple(); + } +} + +Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, + const char **McpuDefault, + Triple *ThumbTriple) { + Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault); + *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType, + McpuDefault); + return T; +} + Triple MachOObjectFile::getHostArch() { return Triple(sys::getDefaultTargetTriple()); } -Triple MachOObjectFile::getArch(StringRef ArchFlag) { - if (ArchFlag == "i386") - return Triple("i386-apple-darwin"); - else if (ArchFlag == "x86_64") - return Triple("x86_64-apple-darwin"); - else if (ArchFlag == "x86_64h") - return Triple("x86_64h-apple-darwin"); - else if (ArchFlag == "armv4t" || ArchFlag == "arm") - return Triple("armv4t-apple-darwin"); - else if (ArchFlag == "armv5e") - return Triple("armv5e-apple-darwin"); - else if (ArchFlag == "armv6") - return Triple("armv6-apple-darwin"); - else if (ArchFlag == "armv6m") - return Triple("armv6m-apple-darwin"); - else if (ArchFlag == "armv7em") - return Triple("armv7em-apple-darwin"); - else if (ArchFlag == "armv7k") - return Triple("armv7k-apple-darwin"); - else if (ArchFlag == "armv7k") - return Triple("armv7m-apple-darwin"); - else if (ArchFlag == "armv7s") - return Triple("armv7s-apple-darwin"); - else if (ArchFlag == "arm64") - return Triple("arm64-apple-darwin"); - else if (ArchFlag == "ppc") - return Triple("ppc-apple-darwin"); - else if (ArchFlag == "ppc64") - return Triple("ppc64-apple-darwin"); - else - return Triple(); +bool MachOObjectFile::isValidArch(StringRef ArchFlag) { + return StringSwitch(ArchFlag) + .Case("i386", true) + .Case("x86_64", true) + .Case("x86_64h", true) + .Case("armv4t", true) + .Case("arm", true) + .Case("armv5e", true) + .Case("armv6", true) + .Case("armv6m", true) + .Case("armv7em", true) + .Case("armv7k", true) + .Case("armv7m", true) + .Case("armv7s", true) + .Case("arm64", true) + .Case("ppc", true) + .Case("ppc64", true) + .Default(false); } unsigned MachOObjectFile::getArch() const { return getArch(getCPUType(this)); } -StringRef MachOObjectFile::getLoadName() const { - // TODO: Implement - report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); +Triple MachOObjectFile::getArch(const char **McpuDefault, + Triple *ThumbTriple) const { + Triple T; + if (is64Bit()) { + MachO::mach_header_64 H_64; + H_64 = getHeader64(); + T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault); + *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype, + McpuDefault); + } else { + MachO::mach_header H; + H = getHeader(); + T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault); + *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype, + McpuDefault); + } + return T; } relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { @@ -1457,6 +1480,623 @@ dice_iterator MachOObjectFile::end_dices() const { return dice_iterator(DiceRef(DRI, this)); } +ExportEntry::ExportEntry(ArrayRef T) + : Trie(T), Malformed(false), Done(false) { } + +void ExportEntry::moveToFirst() { + pushNode(0); + pushDownUntilBottom(); +} + +void ExportEntry::moveToEnd() { + Stack.clear(); + Done = true; +} + +bool ExportEntry::operator==(const ExportEntry &Other) const { + // Common case, one at end, other iterating from begin. + if (Done || Other.Done) + return (Done == Other.Done); + // Not equal if different stack sizes. + if (Stack.size() != Other.Stack.size()) + return false; + // Not equal if different cumulative strings. + if (!CumulativeString.str().equals(Other.CumulativeString.str())) + return false; + // Equal if all nodes in both stacks match. + for (unsigned i=0; i < Stack.size(); ++i) { + if (Stack[i].Start != Other.Stack[i].Start) + return false; + } + return true; +} + +uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { + unsigned Count; + uint64_t Result = decodeULEB128(Ptr, &Count); + Ptr += Count; + if (Ptr > Trie.end()) { + Ptr = Trie.end(); + Malformed = true; + } + return Result; +} + +StringRef ExportEntry::name() const { + return CumulativeString.str(); +} + +uint64_t ExportEntry::flags() const { + return Stack.back().Flags; +} + +uint64_t ExportEntry::address() const { + return Stack.back().Address; +} + +uint64_t ExportEntry::other() const { + return Stack.back().Other; +} + +StringRef ExportEntry::otherName() const { + const char* ImportName = Stack.back().ImportName; + if (ImportName) + return StringRef(ImportName); + return StringRef(); +} + +uint32_t ExportEntry::nodeOffset() const { + return Stack.back().Start - Trie.begin(); +} + +ExportEntry::NodeState::NodeState(const uint8_t *Ptr) + : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), + ImportName(nullptr), ChildCount(0), NextChildIndex(0), + ParentStringLength(0), IsExportNode(false) { +} + +void ExportEntry::pushNode(uint64_t offset) { + const uint8_t *Ptr = Trie.begin() + offset; + NodeState State(Ptr); + uint64_t ExportInfoSize = readULEB128(State.Current); + State.IsExportNode = (ExportInfoSize != 0); + const uint8_t* Children = State.Current + ExportInfoSize; + if (State.IsExportNode) { + State.Flags = readULEB128(State.Current); + if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { + State.Address = 0; + State.Other = readULEB128(State.Current); // dylib ordinal + State.ImportName = reinterpret_cast(State.Current); + } else { + State.Address = readULEB128(State.Current); + if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) + State.Other = readULEB128(State.Current); + } + } + State.ChildCount = *Children; + State.Current = Children + 1; + State.NextChildIndex = 0; + State.ParentStringLength = CumulativeString.size(); + Stack.push_back(State); +} + +void ExportEntry::pushDownUntilBottom() { + while (Stack.back().NextChildIndex < Stack.back().ChildCount) { + NodeState &Top = Stack.back(); + CumulativeString.resize(Top.ParentStringLength); + for (;*Top.Current != 0; Top.Current++) { + char C = *Top.Current; + CumulativeString.push_back(C); + } + Top.Current += 1; + uint64_t childNodeIndex = readULEB128(Top.Current); + Top.NextChildIndex += 1; + pushNode(childNodeIndex); + } + if (!Stack.back().IsExportNode) { + Malformed = true; + moveToEnd(); + } +} + +// We have a trie data structure and need a way to walk it that is compatible +// with the C++ iterator model. The solution is a non-recursive depth first +// traversal where the iterator contains a stack of parent nodes along with a +// string that is the accumulation of all edge strings along the parent chain +// to this point. +// +// There is one "export" node for each exported symbol. But because some +// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export +// node may have child nodes too. +// +// The algorithm for moveNext() is to keep moving down the leftmost unvisited +// child until hitting a node with no children (which is an export node or +// else the trie is malformed). On the way down, each node is pushed on the +// stack ivar. If there is no more ways down, it pops up one and tries to go +// down a sibling path until a childless node is reached. +void ExportEntry::moveNext() { + if (Stack.empty() || !Stack.back().IsExportNode) { + Malformed = true; + moveToEnd(); + return; + } + + Stack.pop_back(); + while (!Stack.empty()) { + NodeState &Top = Stack.back(); + if (Top.NextChildIndex < Top.ChildCount) { + pushDownUntilBottom(); + // Now at the next export node. + return; + } else { + if (Top.IsExportNode) { + // This node has no children but is itself an export node. + CumulativeString.resize(Top.ParentStringLength); + return; + } + Stack.pop_back(); + } + } + Done = true; +} + +iterator_range +MachOObjectFile::exports(ArrayRef Trie) { + ExportEntry Start(Trie); + if (Trie.size() == 0) + Start.moveToEnd(); + else + Start.moveToFirst(); + + ExportEntry Finish(Trie); + Finish.moveToEnd(); + + return iterator_range(export_iterator(Start), + export_iterator(Finish)); +} + +iterator_range MachOObjectFile::exports() const { + return exports(getDyldInfoExportsTrie()); +} + + +MachORebaseEntry::MachORebaseEntry(ArrayRef Bytes, bool is64Bit) + : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), + RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), + PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} + +void MachORebaseEntry::moveToFirst() { + Ptr = Opcodes.begin(); + moveNext(); +} + +void MachORebaseEntry::moveToEnd() { + Ptr = Opcodes.end(); + RemainingLoopCount = 0; + Done = true; +} + +void MachORebaseEntry::moveNext() { + // If in the middle of some loop, move to next rebasing in loop. + SegmentOffset += AdvanceAmount; + if (RemainingLoopCount) { + --RemainingLoopCount; + return; + } + if (Ptr == Opcodes.end()) { + Done = true; + return; + } + bool More = true; + while (More && !Malformed) { + // Parse next opcode and set up next loop. + uint8_t Byte = *Ptr++; + uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; + uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; + switch (Opcode) { + case MachO::REBASE_OPCODE_DONE: + More = false; + Done = true; + moveToEnd(); + DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); + break; + case MachO::REBASE_OPCODE_SET_TYPE_IMM: + RebaseType = ImmValue; + DEBUG_WITH_TYPE( + "mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " + << "RebaseType=" << (int) RebaseType << "\n"); + break; + case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + SegmentIndex = ImmValue; + SegmentOffset = readULEB128(); + DEBUG_WITH_TYPE( + "mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " + << "SegmentIndex=" << SegmentIndex << ", " + << format("SegmentOffset=0x%06X", SegmentOffset) + << "\n"); + break; + case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: + SegmentOffset += readULEB128(); + DEBUG_WITH_TYPE("mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " + << format("SegmentOffset=0x%06X", + SegmentOffset) << "\n"); + break; + case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: + SegmentOffset += ImmValue * PointerSize; + DEBUG_WITH_TYPE("mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " + << format("SegmentOffset=0x%06X", + SegmentOffset) << "\n"); + break; + case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: + AdvanceAmount = PointerSize; + RemainingLoopCount = ImmValue - 1; + DEBUG_WITH_TYPE( + "mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " + << format("SegmentOffset=0x%06X", SegmentOffset) + << ", AdvanceAmount=" << AdvanceAmount + << ", RemainingLoopCount=" << RemainingLoopCount + << "\n"); + return; + case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: + AdvanceAmount = PointerSize; + RemainingLoopCount = readULEB128() - 1; + DEBUG_WITH_TYPE( + "mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " + << format("SegmentOffset=0x%06X", SegmentOffset) + << ", AdvanceAmount=" << AdvanceAmount + << ", RemainingLoopCount=" << RemainingLoopCount + << "\n"); + return; + case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: + AdvanceAmount = readULEB128() + PointerSize; + RemainingLoopCount = 0; + DEBUG_WITH_TYPE( + "mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " + << format("SegmentOffset=0x%06X", SegmentOffset) + << ", AdvanceAmount=" << AdvanceAmount + << ", RemainingLoopCount=" << RemainingLoopCount + << "\n"); + return; + case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: + RemainingLoopCount = readULEB128() - 1; + AdvanceAmount = readULEB128() + PointerSize; + DEBUG_WITH_TYPE( + "mach-o-rebase", + llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " + << format("SegmentOffset=0x%06X", SegmentOffset) + << ", AdvanceAmount=" << AdvanceAmount + << ", RemainingLoopCount=" << RemainingLoopCount + << "\n"); + return; + default: + Malformed = true; + } + } +} + +uint64_t MachORebaseEntry::readULEB128() { + unsigned Count; + uint64_t Result = decodeULEB128(Ptr, &Count); + Ptr += Count; + if (Ptr > Opcodes.end()) { + Ptr = Opcodes.end(); + Malformed = true; + } + return Result; +} + +uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } + +uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } + +StringRef MachORebaseEntry::typeName() const { + switch (RebaseType) { + case MachO::REBASE_TYPE_POINTER: + return "pointer"; + case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: + return "text abs32"; + case MachO::REBASE_TYPE_TEXT_PCREL32: + return "text rel32"; + } + return "unknown"; +} + +bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { + assert(Opcodes == Other.Opcodes && "compare iterators of different files"); + return (Ptr == Other.Ptr) && + (RemainingLoopCount == Other.RemainingLoopCount) && + (Done == Other.Done); +} + +iterator_range +MachOObjectFile::rebaseTable(ArrayRef Opcodes, bool is64) { + MachORebaseEntry Start(Opcodes, is64); + Start.moveToFirst(); + + MachORebaseEntry Finish(Opcodes, is64); + Finish.moveToEnd(); + + return iterator_range(rebase_iterator(Start), + rebase_iterator(Finish)); +} + +iterator_range MachOObjectFile::rebaseTable() const { + return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); +} + + +MachOBindEntry::MachOBindEntry(ArrayRef Bytes, bool is64Bit, + Kind BK) + : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), + Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), + BindType(0), PointerSize(is64Bit ? 8 : 4), + TableKind(BK), Malformed(false), Done(false) {} + +void MachOBindEntry::moveToFirst() { + Ptr = Opcodes.begin(); + moveNext(); +} + +void MachOBindEntry::moveToEnd() { + Ptr = Opcodes.end(); + RemainingLoopCount = 0; + Done = true; +} + +void MachOBindEntry::moveNext() { + // If in the middle of some loop, move to next binding in loop. + SegmentOffset += AdvanceAmount; + if (RemainingLoopCount) { + --RemainingLoopCount; + return; + } + if (Ptr == Opcodes.end()) { + Done = true; + return; + } + bool More = true; + while (More && !Malformed) { + // Parse next opcode and set up next loop. + uint8_t Byte = *Ptr++; + uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; + uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; + int8_t SignExtended; + const uint8_t *SymStart; + switch (Opcode) { + case MachO::BIND_OPCODE_DONE: + if (TableKind == Kind::Lazy) { + // Lazying bindings have a DONE opcode between entries. Need to ignore + // it to advance to next entry. But need not if this is last entry. + bool NotLastEntry = false; + for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { + if (*P) { + NotLastEntry = true; + } + } + if (NotLastEntry) + break; + } + More = false; + Done = true; + moveToEnd(); + DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); + break; + case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: + Ordinal = ImmValue; + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " + << "Ordinal=" << Ordinal << "\n"); + break; + case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: + Ordinal = readULEB128(); + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " + << "Ordinal=" << Ordinal << "\n"); + break; + case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: + if (ImmValue) { + SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; + Ordinal = SignExtended; + } else + Ordinal = 0; + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " + << "Ordinal=" << Ordinal << "\n"); + break; + case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: + Flags = ImmValue; + SymStart = Ptr; + while (*Ptr) { + ++Ptr; + } + SymbolName = StringRef(reinterpret_cast(SymStart), + Ptr-SymStart); + ++Ptr; + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " + << "SymbolName=" << SymbolName << "\n"); + if (TableKind == Kind::Weak) { + if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) + return; + } + break; + case MachO::BIND_OPCODE_SET_TYPE_IMM: + BindType = ImmValue; + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " + << "BindType=" << (int)BindType << "\n"); + break; + case MachO::BIND_OPCODE_SET_ADDEND_SLEB: + Addend = readSLEB128(); + if (TableKind == Kind::Lazy) + Malformed = true; + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " + << "Addend=" << Addend << "\n"); + break; + case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: + SegmentIndex = ImmValue; + SegmentOffset = readULEB128(); + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " + << "SegmentIndex=" << SegmentIndex << ", " + << format("SegmentOffset=0x%06X", SegmentOffset) + << "\n"); + break; + case MachO::BIND_OPCODE_ADD_ADDR_ULEB: + SegmentOffset += readULEB128(); + DEBUG_WITH_TYPE("mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " + << format("SegmentOffset=0x%06X", + SegmentOffset) << "\n"); + break; + case MachO::BIND_OPCODE_DO_BIND: + AdvanceAmount = PointerSize; + RemainingLoopCount = 0; + DEBUG_WITH_TYPE("mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_DO_BIND: " + << format("SegmentOffset=0x%06X", + SegmentOffset) << "\n"); + return; + case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: + AdvanceAmount = readULEB128() + PointerSize; + RemainingLoopCount = 0; + if (TableKind == Kind::Lazy) + Malformed = true; + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " + << format("SegmentOffset=0x%06X", SegmentOffset) + << ", AdvanceAmount=" << AdvanceAmount + << ", RemainingLoopCount=" << RemainingLoopCount + << "\n"); + return; + case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: + AdvanceAmount = ImmValue * PointerSize + PointerSize; + RemainingLoopCount = 0; + if (TableKind == Kind::Lazy) + Malformed = true; + DEBUG_WITH_TYPE("mach-o-bind", + llvm::dbgs() + << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " + << format("SegmentOffset=0x%06X", + SegmentOffset) << "\n"); + return; + case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: + RemainingLoopCount = readULEB128() - 1; + AdvanceAmount = readULEB128() + PointerSize; + if (TableKind == Kind::Lazy) + Malformed = true; + DEBUG_WITH_TYPE( + "mach-o-bind", + llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " + << format("SegmentOffset=0x%06X", SegmentOffset) + << ", AdvanceAmount=" << AdvanceAmount + << ", RemainingLoopCount=" << RemainingLoopCount + << "\n"); + return; + default: + Malformed = true; + } + } +} + +uint64_t MachOBindEntry::readULEB128() { + unsigned Count; + uint64_t Result = decodeULEB128(Ptr, &Count); + Ptr += Count; + if (Ptr > Opcodes.end()) { + Ptr = Opcodes.end(); + Malformed = true; + } + return Result; +} + +int64_t MachOBindEntry::readSLEB128() { + unsigned Count; + int64_t Result = decodeSLEB128(Ptr, &Count); + Ptr += Count; + if (Ptr > Opcodes.end()) { + Ptr = Opcodes.end(); + Malformed = true; + } + return Result; +} + + +uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } + +uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } + +StringRef MachOBindEntry::typeName() const { + switch (BindType) { + case MachO::BIND_TYPE_POINTER: + return "pointer"; + case MachO::BIND_TYPE_TEXT_ABSOLUTE32: + return "text abs32"; + case MachO::BIND_TYPE_TEXT_PCREL32: + return "text rel32"; + } + return "unknown"; +} + +StringRef MachOBindEntry::symbolName() const { return SymbolName; } + +int64_t MachOBindEntry::addend() const { return Addend; } + +uint32_t MachOBindEntry::flags() const { return Flags; } + +int MachOBindEntry::ordinal() const { return Ordinal; } + +bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { + assert(Opcodes == Other.Opcodes && "compare iterators of different files"); + return (Ptr == Other.Ptr) && + (RemainingLoopCount == Other.RemainingLoopCount) && + (Done == Other.Done); +} + +iterator_range +MachOObjectFile::bindTable(ArrayRef Opcodes, bool is64, + MachOBindEntry::Kind BKind) { + MachOBindEntry Start(Opcodes, is64, BKind); + Start.moveToFirst(); + + MachOBindEntry Finish(Opcodes, is64, BKind); + Finish.moveToEnd(); + + return iterator_range(bind_iterator(Start), + bind_iterator(Finish)); +} + +iterator_range MachOObjectFile::bindTable() const { + return bindTable(getDyldInfoBindOpcodes(), is64Bit(), + MachOBindEntry::Kind::Regular); +} + +iterator_range MachOObjectFile::lazyBindTable() const { + return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), + MachOBindEntry::Kind::Lazy); +} + +iterator_range MachOObjectFile::weakBindTable() const { + return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), + MachOBindEntry::Kind::Weak); +} + StringRef MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { ArrayRef Raw = getSectionRawFinalSegmentName(Sec); @@ -1467,14 +2107,14 @@ ArrayRef MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { const section_base *Base = reinterpret_cast(Sections[Sec.d.a]); - return ArrayRef(Base->sectname); + return makeArrayRef(Base->sectname); } ArrayRef MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { const section_base *Base = reinterpret_cast(Sections[Sec.d.a]); - return ArrayRef(Base->segname); + return makeArrayRef(Base->segname); } bool @@ -1509,6 +2149,11 @@ uint32_t MachOObjectFile::getScatteredRelocationValue( return RE.r_word1; } +uint32_t MachOObjectFile::getScatteredRelocationType( + const MachO::any_relocation_info &RE) const { + return (RE.r_word0 >> 24) & 0xf; +} + unsigned MachOObjectFile::getAnyRelocationAddress( const MachO::any_relocation_info &RE) const { if (isRelocationScattered(RE)) @@ -1615,9 +2260,9 @@ MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { return getStruct(this, L.Ptr); } -MachO::linker_options_command -MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { - return getStruct(this, L.Ptr); +MachO::linker_option_command +MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); } MachO::version_min_command @@ -1630,6 +2275,80 @@ MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { return getStruct(this, L.Ptr); } +MachO::dyld_info_command +MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::dylinker_command +MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::uuid_command +MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::rpath_command +MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::source_version_command +MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::entry_point_command +MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::encryption_info_command +MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::encryption_info_command_64 +MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::sub_framework_command +MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::sub_umbrella_command +MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::sub_library_command +MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::sub_client_command +MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::routines_command +MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::routines_command_64 +MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} + +MachO::thread_command +MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { + return getStruct(this, L.Ptr); +} MachO::any_relocation_info MachOObjectFile::getRelocation(DataRefImpl Rel) const { @@ -1679,11 +2398,47 @@ MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, } MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { - return getStruct(this, SymtabLoadCmd); + if (SymtabLoadCmd) + return getStruct(this, SymtabLoadCmd); + + // If there is no SymtabLoadCmd return a load command with zero'ed fields. + MachO::symtab_command Cmd; + Cmd.cmd = MachO::LC_SYMTAB; + Cmd.cmdsize = sizeof(MachO::symtab_command); + Cmd.symoff = 0; + Cmd.nsyms = 0; + Cmd.stroff = 0; + Cmd.strsize = 0; + return Cmd; } MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { - return getStruct(this, DysymtabLoadCmd); + if (DysymtabLoadCmd) + return getStruct(this, DysymtabLoadCmd); + + // If there is no DysymtabLoadCmd return a load command with zero'ed fields. + MachO::dysymtab_command Cmd; + Cmd.cmd = MachO::LC_DYSYMTAB; + Cmd.cmdsize = sizeof(MachO::dysymtab_command); + Cmd.ilocalsym = 0; + Cmd.nlocalsym = 0; + Cmd.iextdefsym = 0; + Cmd.nextdefsym = 0; + Cmd.iundefsym = 0; + Cmd.nundefsym = 0; + Cmd.tocoff = 0; + Cmd.ntoc = 0; + Cmd.modtaboff = 0; + Cmd.nmodtab = 0; + Cmd.extrefsymoff = 0; + Cmd.nextrefsyms = 0; + Cmd.indirectsymoff = 0; + Cmd.nindirectsyms = 0; + Cmd.extreloff = 0; + Cmd.nextrel = 0; + Cmd.locreloff = 0; + Cmd.nlocrel = 0; + return Cmd; } MachO::linkedit_data_command @@ -1700,6 +2455,69 @@ MachOObjectFile::getDataInCodeLoadCommand() const { return Cmd; } +ArrayRef MachOObjectFile::getDyldInfoRebaseOpcodes() const { + if (!DyldInfoLoadCmd) + return ArrayRef(); + + MachO::dyld_info_command DyldInfo + = getStruct(this, DyldInfoLoadCmd); + const uint8_t *Ptr = reinterpret_cast( + getPtr(this, DyldInfo.rebase_off)); + return ArrayRef(Ptr, DyldInfo.rebase_size); +} + +ArrayRef MachOObjectFile::getDyldInfoBindOpcodes() const { + if (!DyldInfoLoadCmd) + return ArrayRef(); + + MachO::dyld_info_command DyldInfo + = getStruct(this, DyldInfoLoadCmd); + const uint8_t *Ptr = reinterpret_cast( + getPtr(this, DyldInfo.bind_off)); + return ArrayRef(Ptr, DyldInfo.bind_size); +} + +ArrayRef MachOObjectFile::getDyldInfoWeakBindOpcodes() const { + if (!DyldInfoLoadCmd) + return ArrayRef(); + + MachO::dyld_info_command DyldInfo + = getStruct(this, DyldInfoLoadCmd); + const uint8_t *Ptr = reinterpret_cast( + getPtr(this, DyldInfo.weak_bind_off)); + return ArrayRef(Ptr, DyldInfo.weak_bind_size); +} + +ArrayRef MachOObjectFile::getDyldInfoLazyBindOpcodes() const { + if (!DyldInfoLoadCmd) + return ArrayRef(); + + MachO::dyld_info_command DyldInfo + = getStruct(this, DyldInfoLoadCmd); + const uint8_t *Ptr = reinterpret_cast( + getPtr(this, DyldInfo.lazy_bind_off)); + return ArrayRef(Ptr, DyldInfo.lazy_bind_size); +} + +ArrayRef MachOObjectFile::getDyldInfoExportsTrie() const { + if (!DyldInfoLoadCmd) + return ArrayRef(); + + MachO::dyld_info_command DyldInfo + = getStruct(this, DyldInfoLoadCmd); + const uint8_t *Ptr = reinterpret_cast( + getPtr(this, DyldInfo.export_off)); + return ArrayRef(Ptr, DyldInfo.export_size); +} + +ArrayRef MachOObjectFile::getUuid() const { + if (!UuidLoadCmd) + return ArrayRef(); + // Returning a pointer is fine as uuid doesn't need endian swapping. + const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); + return ArrayRef(reinterpret_cast(Ptr), 16); +} + StringRef MachOObjectFile::getStringTableData() const { MachO::symtab_command S = getSymtabLoadCommand(); return getData().substr(S.stroff, S.strsize); @@ -1722,24 +2540,28 @@ void MachOObjectFile::ReadULEB128s(uint64_t Index, } } -ErrorOr -ObjectFile::createMachOObjectFile(std::unique_ptr &Buffer) { - StringRef Magic = Buffer->getBuffer().slice(0, 4); +bool MachOObjectFile::isRelocatableObject() const { + return getHeader().filetype == MachO::MH_OBJECT; +} + +ErrorOr> +ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { + StringRef Magic = Buffer.getBuffer().slice(0, 4); std::error_code EC; std::unique_ptr Ret; if (Magic == "\xFE\xED\xFA\xCE") - Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC)); + Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); else if (Magic == "\xCE\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC)); + Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); else if (Magic == "\xFE\xED\xFA\xCF") - Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC)); + Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); else if (Magic == "\xCF\xFA\xED\xFE") - Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC)); + Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); else return object_error::parse_failed; if (EC) return EC; - return Ret.release(); + return std::move(Ret); } diff --git a/lib/Object/MachOUniversal.cpp b/lib/Object/MachOUniversal.cpp index 4ba5d96..a01c838 100644 --- a/lib/Object/MachOUniversal.cpp +++ b/lib/Object/MachOUniversal.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Object/MachOUniversal.h" +#include "llvm/Object/Archive.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" -#include "llvm/Object/Archive.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Host.h" #include "llvm/Support/MemoryBuffer.h" @@ -67,53 +67,46 @@ MachOUniversalBinary::ObjectForArch::ObjectForArch( } } -ErrorOr> +ErrorOr> MachOUniversalBinary::ObjectForArch::getAsObjectFile() const { if (Parent) { StringRef ParentData = Parent->getData(); StringRef ObjectData = ParentData.substr(Header.offset, Header.size); - std::string ObjectName = Parent->getFileName().str(); - std::unique_ptr ObjBuffer( - MemoryBuffer::getMemBuffer(ObjectData, ObjectName, false)); + StringRef ObjectName = Parent->getFileName(); + MemoryBufferRef ObjBuffer(ObjectData, ObjectName); return ObjectFile::createMachOObjectFile(ObjBuffer); } return object_error::parse_failed; } -std::error_code MachOUniversalBinary::ObjectForArch::getAsArchive( - std::unique_ptr &Result) const { - if (Parent) { - StringRef ParentData = Parent->getData(); - StringRef ObjectData = ParentData.substr(Header.offset, Header.size); - std::string ObjectName = Parent->getFileName().str(); - std::unique_ptr ObjBuffer( - MemoryBuffer::getMemBuffer(ObjectData, ObjectName, false)); - ErrorOr Obj = Archive::create(std::move(ObjBuffer)); - if (std::error_code EC = Obj.getError()) - return EC; - Result.reset(Obj.get()); - return object_error::success; - } - return object_error::parse_failed; +ErrorOr> +MachOUniversalBinary::ObjectForArch::getAsArchive() const { + if (!Parent) + return object_error::parse_failed; + + StringRef ParentData = Parent->getData(); + StringRef ObjectData = ParentData.substr(Header.offset, Header.size); + StringRef ObjectName = Parent->getFileName(); + MemoryBufferRef ObjBuffer(ObjectData, ObjectName); + return Archive::create(ObjBuffer); } void MachOUniversalBinary::anchor() { } -ErrorOr -MachOUniversalBinary::create(std::unique_ptr Source) { +ErrorOr> +MachOUniversalBinary::create(MemoryBufferRef Source) { std::error_code EC; std::unique_ptr Ret( - new MachOUniversalBinary(std::move(Source), EC)); + new MachOUniversalBinary(Source, EC)); if (EC) return EC; - return Ret.release(); + return std::move(Ret); } -MachOUniversalBinary::MachOUniversalBinary(std::unique_ptr Source, +MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source, std::error_code &ec) - : Binary(Binary::ID_MachOUniversalBinary, std::move(Source)), - NumberOfObjects(0) { - if (Data->getBufferSize() < sizeof(MachO::fat_header)) { + : Binary(Binary::ID_MachOUniversalBinary, Source), NumberOfObjects(0) { + if (Data.getBufferSize() < sizeof(MachO::fat_header)) { ec = object_error::invalid_file_type; return; } @@ -142,7 +135,7 @@ static bool getCTMForArch(Triple::ArchType Arch, MachO::CPUType &CTM) { } } -ErrorOr> +ErrorOr> MachOUniversalBinary::getObjectForArch(Triple::ArchType Arch) const { MachO::CPUType CTM; if (!getCTMForArch(Arch, CTM)) diff --git a/lib/Object/Object.cpp b/lib/Object/Object.cpp index 567d87f..84a5df0 100644 --- a/lib/Object/Object.cpp +++ b/lib/Object/Object.cpp @@ -19,12 +19,13 @@ using namespace llvm; using namespace object; -inline ObjectFile *unwrap(LLVMObjectFileRef OF) { - return reinterpret_cast(OF); +inline OwningBinary *unwrap(LLVMObjectFileRef OF) { + return reinterpret_cast *>(OF); } -inline LLVMObjectFileRef wrap(const ObjectFile *OF) { - return reinterpret_cast(const_cast(OF)); +inline LLVMObjectFileRef wrap(const OwningBinary *OF) { + return reinterpret_cast( + const_cast *>(OF)); } inline section_iterator *unwrap(LLVMSectionIteratorRef SI) { @@ -60,10 +61,14 @@ wrap(const relocation_iterator *SI) { // ObjectFile creation LLVMObjectFileRef LLVMCreateObjectFile(LLVMMemoryBufferRef MemBuf) { std::unique_ptr Buf(unwrap(MemBuf)); - ErrorOr ObjOrErr(ObjectFile::createObjectFile(Buf)); - Buf.release(); - ObjectFile *Obj = ObjOrErr ? ObjOrErr.get() : nullptr; - return wrap(Obj); + ErrorOr> ObjOrErr( + ObjectFile::createObjectFile(Buf->getMemBufferRef())); + std::unique_ptr Obj; + if (!ObjOrErr) + return nullptr; + + auto *Ret = new OwningBinary(std::move(ObjOrErr.get()), std::move(Buf)); + return wrap(Ret); } void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { @@ -71,8 +76,9 @@ void LLVMDisposeObjectFile(LLVMObjectFileRef ObjectFile) { } // ObjectFile Section iterators -LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef ObjectFile) { - section_iterator SI = unwrap(ObjectFile)->section_begin(); +LLVMSectionIteratorRef LLVMGetSections(LLVMObjectFileRef OF) { + OwningBinary *OB = unwrap(OF); + section_iterator SI = OB->getBinary()->section_begin(); return wrap(new section_iterator(SI)); } @@ -80,9 +86,10 @@ void LLVMDisposeSectionIterator(LLVMSectionIteratorRef SI) { delete unwrap(SI); } -LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef ObjectFile, - LLVMSectionIteratorRef SI) { - return (*unwrap(SI) == unwrap(ObjectFile)->section_end()) ? 1 : 0; +LLVMBool LLVMIsSectionIteratorAtEnd(LLVMObjectFileRef OF, + LLVMSectionIteratorRef SI) { + OwningBinary *OB = unwrap(OF); + return (*unwrap(SI) == OB->getBinary()->section_end()) ? 1 : 0; } void LLVMMoveToNextSection(LLVMSectionIteratorRef SI) { @@ -96,8 +103,9 @@ void LLVMMoveToContainingSection(LLVMSectionIteratorRef Sect, } // ObjectFile Symbol iterators -LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef ObjectFile) { - symbol_iterator SI = unwrap(ObjectFile)->symbol_begin(); +LLVMSymbolIteratorRef LLVMGetSymbols(LLVMObjectFileRef OF) { + OwningBinary *OB = unwrap(OF); + symbol_iterator SI = OB->getBinary()->symbol_begin(); return wrap(new symbol_iterator(SI)); } @@ -105,9 +113,10 @@ void LLVMDisposeSymbolIterator(LLVMSymbolIteratorRef SI) { delete unwrap(SI); } -LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef ObjectFile, - LLVMSymbolIteratorRef SI) { - return (*unwrap(SI) == unwrap(ObjectFile)->symbol_end()) ? 1 : 0; +LLVMBool LLVMIsSymbolIteratorAtEnd(LLVMObjectFileRef OF, + LLVMSymbolIteratorRef SI) { + OwningBinary *OB = unwrap(OF); + return (*unwrap(SI) == OB->getBinary()->symbol_end()) ? 1 : 0; } void LLVMMoveToNextSymbol(LLVMSymbolIteratorRef SI) { @@ -123,10 +132,7 @@ const char *LLVMGetSectionName(LLVMSectionIteratorRef SI) { } uint64_t LLVMGetSectionSize(LLVMSectionIteratorRef SI) { - uint64_t ret; - if (std::error_code ec = (*unwrap(SI))->getSize(ret)) - report_fatal_error(ec.message()); - return ret; + return (*unwrap(SI))->getSize(); } const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { @@ -137,18 +143,12 @@ const char *LLVMGetSectionContents(LLVMSectionIteratorRef SI) { } uint64_t LLVMGetSectionAddress(LLVMSectionIteratorRef SI) { - uint64_t ret; - if (std::error_code ec = (*unwrap(SI))->getAddress(ret)) - report_fatal_error(ec.message()); - return ret; + return (*unwrap(SI))->getAddress(); } LLVMBool LLVMGetSectionContainsSymbol(LLVMSectionIteratorRef SI, LLVMSymbolIteratorRef Sym) { - bool ret; - if (std::error_code ec = (*unwrap(SI))->containsSymbol(**unwrap(Sym), ret)) - report_fatal_error(ec.message()); - return ret; + return (*unwrap(SI))->containsSymbol(**unwrap(Sym)); } // Section Relocation iterators diff --git a/lib/Object/ObjectFile.cpp b/lib/Object/ObjectFile.cpp index f5488c6..fd78271 100644 --- a/lib/Object/ObjectFile.cpp +++ b/lib/Object/ObjectFile.cpp @@ -11,6 +11,8 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Object/COFF.h" +#include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -23,8 +25,8 @@ using namespace object; void ObjectFile::anchor() { } -ObjectFile::ObjectFile(unsigned int Type, std::unique_ptr Source) - : SymbolicFile(Type, std::move(Source)) {} +ObjectFile::ObjectFile(unsigned int Type, MemoryBufferRef Source) + : SymbolicFile(Type, Source) {} std::error_code ObjectFile::printSymbolName(raw_ostream &OS, DataRefImpl Symb) const { @@ -45,11 +47,11 @@ section_iterator ObjectFile::getRelocatedSection(DataRefImpl Sec) const { return section_iterator(SectionRef(Sec, this)); } -ErrorOr -ObjectFile::createObjectFile(std::unique_ptr &Object, - sys::fs::file_magic Type) { +ErrorOr> +ObjectFile::createObjectFile(MemoryBufferRef Object, sys::fs::file_magic Type) { + StringRef Data = Object.getBuffer(); if (Type == sys::fs::file_magic::unknown) - Type = sys::fs::identify_magic(Object->getBuffer()); + Type = sys::fs::identify_magic(Data); switch (Type) { case sys::fs::file_magic::unknown: @@ -58,6 +60,7 @@ ObjectFile::createObjectFile(std::unique_ptr &Object, case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: return object_error::invalid_file_type; + case sys::fs::file_magic::elf: case sys::fs::file_magic::elf_relocatable: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: @@ -77,15 +80,24 @@ ObjectFile::createObjectFile(std::unique_ptr &Object, case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: - return createCOFFObjectFile(std::move(Object)); + return createCOFFObjectFile(Object); } llvm_unreachable("Unexpected Object File Type"); } -ErrorOr ObjectFile::createObjectFile(StringRef ObjectPath) { +ErrorOr> +ObjectFile::createObjectFile(StringRef ObjectPath) { ErrorOr> FileOrErr = MemoryBuffer::getFile(ObjectPath); if (std::error_code EC = FileOrErr.getError()) return EC; - return createObjectFile(FileOrErr.get()); + std::unique_ptr Buffer = std::move(FileOrErr.get()); + + ErrorOr> ObjOrErr = + createObjectFile(Buffer->getMemBufferRef()); + if (std::error_code EC = ObjOrErr.getError()) + return EC; + std::unique_ptr Obj = std::move(ObjOrErr.get()); + + return OwningBinary(std::move(Obj), std::move(Buffer)); } diff --git a/lib/Object/RecordStreamer.h b/lib/Object/RecordStreamer.h index 10e70ef..7dacbdf 100644 --- a/lib/Object/RecordStreamer.h +++ b/lib/Object/RecordStreamer.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJECT_RECORD_STREAMER -#define LLVM_OBJECT_RECORD_STREAMER +#ifndef LLVM_LIB_OBJECT_RECORDSTREAMER_H +#define LLVM_LIB_OBJECT_RECORDSTREAMER_H #include "llvm/MC/MCStreamer.h" diff --git a/lib/Object/SymbolicFile.cpp b/lib/Object/SymbolicFile.cpp index 30cf1a0..de98a12 100644 --- a/lib/Object/SymbolicFile.cpp +++ b/lib/Object/SymbolicFile.cpp @@ -19,34 +19,31 @@ using namespace llvm; using namespace object; -SymbolicFile::SymbolicFile(unsigned int Type, - std::unique_ptr Source) - : Binary(Type, std::move(Source)) {} +SymbolicFile::SymbolicFile(unsigned int Type, MemoryBufferRef Source) + : Binary(Type, Source) {} SymbolicFile::~SymbolicFile() {} -ErrorOr -SymbolicFile::createSymbolicFile(std::unique_ptr &Object, - sys::fs::file_magic Type, - LLVMContext *Context) { +ErrorOr> SymbolicFile::createSymbolicFile( + MemoryBufferRef Object, sys::fs::file_magic Type, LLVMContext *Context) { + StringRef Data = Object.getBuffer(); if (Type == sys::fs::file_magic::unknown) - Type = sys::fs::identify_magic(Object->getBuffer()); + Type = sys::fs::identify_magic(Data); switch (Type) { case sys::fs::file_magic::bitcode: if (Context) - return IRObjectFile::createIRObjectFile(std::move(Object), *Context); + return IRObjectFile::create(Object, *Context); // Fallthrough case sys::fs::file_magic::unknown: case sys::fs::file_magic::archive: case sys::fs::file_magic::macho_universal_binary: case sys::fs::file_magic::windows_resource: return object_error::invalid_file_type; - case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::elf: case sys::fs::file_magic::elf_executable: case sys::fs::file_magic::elf_shared_object: case sys::fs::file_magic::elf_core: - case sys::fs::file_magic::macho_object: case sys::fs::file_magic::macho_executable: case sys::fs::file_magic::macho_fixed_virtual_memory_shared_lib: case sys::fs::file_magic::macho_core: @@ -56,10 +53,26 @@ SymbolicFile::createSymbolicFile(std::unique_ptr &Object, case sys::fs::file_magic::macho_bundle: case sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub: case sys::fs::file_magic::macho_dsym_companion: - case sys::fs::file_magic::coff_object: case sys::fs::file_magic::coff_import_library: case sys::fs::file_magic::pecoff_executable: return ObjectFile::createObjectFile(Object, Type); + case sys::fs::file_magic::elf_relocatable: + case sys::fs::file_magic::macho_object: + case sys::fs::file_magic::coff_object: { + ErrorOr> Obj = + ObjectFile::createObjectFile(Object, Type); + if (!Obj || !Context) + return std::move(Obj); + + ErrorOr BCData = + IRObjectFile::findBitcodeInObject(*Obj->get()); + if (!BCData) + return std::move(Obj); + + return IRObjectFile::create( + MemoryBufferRef(BCData->getBuffer(), Object.getBufferIdentifier()), + *Context); + } } llvm_unreachable("Unexpected Binary File Type"); } diff --git a/lib/Option/ArgList.cpp b/lib/Option/ArgList.cpp index 5848bb1..b1a916d 100644 --- a/lib/Option/ArgList.cpp +++ b/lib/Option/ArgList.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Option/ArgList.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/Option/Arg.h" #include "llvm/Option/Option.h" @@ -54,6 +54,15 @@ Arg *ArgList::getLastArgNoClaim(OptSpecifier Id) const { return nullptr; } +Arg *ArgList::getLastArgNoClaim(OptSpecifier Id0, OptSpecifier Id1) const { + // FIXME: Make search efficient? + for (const_reverse_iterator it = rbegin(), ie = rend(); it != ie; ++it) + if ((*it)->getOption().matches(Id0) || + (*it)->getOption().matches(Id1)) + return *it; + return nullptr; +} + Arg *ArgList::getLastArg(OptSpecifier Id) const { Arg *Res = nullptr; for (const_iterator it = begin(), ie = end(); it != ie; ++it) { diff --git a/lib/Option/OptTable.cpp b/lib/Option/OptTable.cpp index 6842f4d..dca02c17 100644 --- a/lib/Option/OptTable.cpp +++ b/lib/Option/OptTable.cpp @@ -264,6 +264,11 @@ InputArgList *OptTable::ParseArgs(const char *const *ArgBegin, MissingArgIndex = MissingArgCount = 0; unsigned Index = 0, End = ArgEnd - ArgBegin; while (Index < End) { + // Ingore nullptrs, they are response file's EOL markers + if (Args->getArgString(Index) == nullptr) { + ++Index; + continue; + } // Ignore empty arguments (other things may still take them as arguments). StringRef Str = Args->getArgString(Index); if (Str == "") { @@ -300,7 +305,18 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) { llvm_unreachable("Invalid option with help text."); case Option::MultiArgClass: - llvm_unreachable("Cannot print metavar for this kind of option."); + if (const char *MetaVarName = Opts.getOptionMetaVar(Id)) { + // For MultiArgs, metavar is full list of all argument names. + Name += ' '; + Name += MetaVarName; + } + else { + // For MultiArgs, if metavar not supplied, print N times. + for (unsigned i=0, e=O.getNumArgs(); i< e; ++i) { + Name += " "; + } + } + break; case Option::FlagClass: break; diff --git a/lib/Option/Option.cpp b/lib/Option/Option.cpp index 10662a3..cdc63c3 100644 --- a/lib/Option/Option.cpp +++ b/lib/Option/Option.cpp @@ -169,7 +169,8 @@ Arg *Option::accept(const ArgList &Args, return nullptr; Index += 2; - if (Index > Args.getNumInputArgStrings()) + if (Index > Args.getNumInputArgStrings() || + Args.getArgString(Index - 1) == nullptr) return nullptr; return new Arg(UnaliasedOption, Spelling, @@ -200,7 +201,8 @@ Arg *Option::accept(const ArgList &Args, // Otherwise it must be separate. Index += 2; - if (Index > Args.getNumInputArgStrings()) + if (Index > Args.getNumInputArgStrings() || + Args.getArgString(Index - 1) == nullptr) return nullptr; return new Arg(UnaliasedOption, Spelling, @@ -209,7 +211,8 @@ Arg *Option::accept(const ArgList &Args, case JoinedAndSeparateClass: // Always matches. Index += 2; - if (Index > Args.getNumInputArgStrings()) + if (Index > Args.getNumInputArgStrings() || + Args.getArgString(Index - 1) == nullptr) return nullptr; return new Arg(UnaliasedOption, Spelling, Index - 2, @@ -221,7 +224,8 @@ Arg *Option::accept(const ArgList &Args, if (ArgSize != strlen(Args.getArgString(Index))) return nullptr; Arg *A = new Arg(UnaliasedOption, Spelling, Index++); - while (Index < Args.getNumInputArgStrings()) + while (Index < Args.getNumInputArgStrings() && + Args.getArgString(Index) != nullptr) A->getValues().push_back(Args.getArgString(Index++)); return A; } diff --git a/lib/ProfileData/CMakeLists.txt b/lib/ProfileData/CMakeLists.txt index aefb16c..b9d472d 100644 --- a/lib/ProfileData/CMakeLists.txt +++ b/lib/ProfileData/CMakeLists.txt @@ -2,4 +2,10 @@ add_llvm_library(LLVMProfileData InstrProf.cpp InstrProfReader.cpp InstrProfWriter.cpp + CoverageMapping.cpp + CoverageMappingWriter.cpp + CoverageMappingReader.cpp + SampleProf.cpp + SampleProfReader.cpp + SampleProfWriter.cpp ) diff --git a/lib/ProfileData/CoverageMapping.cpp b/lib/ProfileData/CoverageMapping.cpp new file mode 100644 index 0000000..1752777 --- /dev/null +++ b/lib/ProfileData/CoverageMapping.cpp @@ -0,0 +1,474 @@ +//=-- CoverageMapping.cpp - Code coverage mapping support ---------*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for clang's and llvm's instrumentation based +// code coverage. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ProfileData/CoverageMappingReader.h" +#include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; +using namespace coverage; + +#define DEBUG_TYPE "coverage-mapping" + +Counter CounterExpressionBuilder::get(const CounterExpression &E) { + auto It = ExpressionIndices.find(E); + if (It != ExpressionIndices.end()) + return Counter::getExpression(It->second); + unsigned I = Expressions.size(); + Expressions.push_back(E); + ExpressionIndices[E] = I; + return Counter::getExpression(I); +} + +void CounterExpressionBuilder::extractTerms( + Counter C, int Sign, SmallVectorImpl> &Terms) { + switch (C.getKind()) { + case Counter::Zero: + break; + case Counter::CounterValueReference: + Terms.push_back(std::make_pair(C.getCounterID(), Sign)); + break; + case Counter::Expression: + const auto &E = Expressions[C.getExpressionID()]; + extractTerms(E.LHS, Sign, Terms); + extractTerms(E.RHS, E.Kind == CounterExpression::Subtract ? -Sign : Sign, + Terms); + break; + } +} + +Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) { + // Gather constant terms. + llvm::SmallVector, 32> Terms; + extractTerms(ExpressionTree, +1, Terms); + + // If there are no terms, this is just a zero. The algorithm below assumes at + // least one term. + if (Terms.size() == 0) + return Counter::getZero(); + + // Group the terms by counter ID. + std::sort(Terms.begin(), Terms.end(), + [](const std::pair &LHS, + const std::pair &RHS) { + return LHS.first < RHS.first; + }); + + // Combine terms by counter ID to eliminate counters that sum to zero. + auto Prev = Terms.begin(); + for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) { + if (I->first == Prev->first) { + Prev->second += I->second; + continue; + } + ++Prev; + *Prev = *I; + } + Terms.erase(++Prev, Terms.end()); + + Counter C; + // Create additions. We do this before subtractions to avoid constructs like + // ((0 - X) + Y), as opposed to (Y - X). + for (auto Term : Terms) { + if (Term.second <= 0) + continue; + for (int I = 0; I < Term.second; ++I) + if (C.isZero()) + C = Counter::getCounter(Term.first); + else + C = get(CounterExpression(CounterExpression::Add, C, + Counter::getCounter(Term.first))); + } + + // Create subtractions. + for (auto Term : Terms) { + if (Term.second >= 0) + continue; + for (int I = 0; I < -Term.second; ++I) + C = get(CounterExpression(CounterExpression::Subtract, C, + Counter::getCounter(Term.first))); + } + return C; +} + +Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS) { + return simplify(get(CounterExpression(CounterExpression::Add, LHS, RHS))); +} + +Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS) { + return simplify( + get(CounterExpression(CounterExpression::Subtract, LHS, RHS))); +} + +void CounterMappingContext::dump(const Counter &C, + llvm::raw_ostream &OS) const { + switch (C.getKind()) { + case Counter::Zero: + OS << '0'; + return; + case Counter::CounterValueReference: + OS << '#' << C.getCounterID(); + break; + case Counter::Expression: { + if (C.getExpressionID() >= Expressions.size()) + return; + const auto &E = Expressions[C.getExpressionID()]; + OS << '('; + dump(E.LHS, OS); + OS << (E.Kind == CounterExpression::Subtract ? " - " : " + "); + dump(E.RHS, OS); + OS << ')'; + break; + } + } + if (CounterValues.empty()) + return; + ErrorOr Value = evaluate(C); + if (!Value) + return; + OS << '[' << *Value << ']'; +} + +ErrorOr CounterMappingContext::evaluate(const Counter &C) const { + switch (C.getKind()) { + case Counter::Zero: + return 0; + case Counter::CounterValueReference: + if (C.getCounterID() >= CounterValues.size()) + return std::make_error_code(std::errc::argument_out_of_domain); + return CounterValues[C.getCounterID()]; + case Counter::Expression: { + if (C.getExpressionID() >= Expressions.size()) + return std::make_error_code(std::errc::argument_out_of_domain); + const auto &E = Expressions[C.getExpressionID()]; + ErrorOr LHS = evaluate(E.LHS); + if (!LHS) + return LHS; + ErrorOr RHS = evaluate(E.RHS); + if (!RHS) + return RHS; + return E.Kind == CounterExpression::Subtract ? *LHS - *RHS : *LHS + *RHS; + } + } + llvm_unreachable("Unhandled CounterKind"); +} + +void FunctionRecordIterator::skipOtherFiles() { + while (Current != Records.end() && !Filename.empty() && + Filename != Current->Filenames[0]) + ++Current; + if (Current == Records.end()) + *this = FunctionRecordIterator(); +} + +ErrorOr> +CoverageMapping::load(ObjectFileCoverageMappingReader &CoverageReader, + IndexedInstrProfReader &ProfileReader) { + auto Coverage = std::unique_ptr(new CoverageMapping()); + + std::vector Counts; + for (const auto &Record : CoverageReader) { + Counts.clear(); + if (std::error_code EC = ProfileReader.getFunctionCounts( + Record.FunctionName, Record.FunctionHash, Counts)) { + if (EC != instrprof_error::hash_mismatch && + EC != instrprof_error::unknown_function) + return EC; + Coverage->MismatchedFunctionCount++; + continue; + } + + assert(Counts.size() != 0 && "Function's counts are empty"); + FunctionRecord Function(Record.FunctionName, Record.Filenames, + Counts.front()); + CounterMappingContext Ctx(Record.Expressions, Counts); + for (const auto &Region : Record.MappingRegions) { + ErrorOr ExecutionCount = Ctx.evaluate(Region.Count); + if (!ExecutionCount) + break; + Function.CountedRegions.push_back(CountedRegion(Region, *ExecutionCount)); + } + if (Function.CountedRegions.size() != Record.MappingRegions.size()) { + Coverage->MismatchedFunctionCount++; + continue; + } + + Coverage->Functions.push_back(std::move(Function)); + } + + return std::move(Coverage); +} + +ErrorOr> +CoverageMapping::load(StringRef ObjectFilename, StringRef ProfileFilename) { + auto CounterMappingBuff = MemoryBuffer::getFileOrSTDIN(ObjectFilename); + if (auto EC = CounterMappingBuff.getError()) + return EC; + ObjectFileCoverageMappingReader CoverageReader(CounterMappingBuff.get()); + if (auto EC = CoverageReader.readHeader()) + return EC; + std::unique_ptr ProfileReader; + if (auto EC = IndexedInstrProfReader::create(ProfileFilename, ProfileReader)) + return EC; + return load(CoverageReader, *ProfileReader); +} + +namespace { +/// \brief Distributes functions into instantiation sets. +/// +/// An instantiation set is a collection of functions that have the same source +/// code, ie, template functions specializations. +class FunctionInstantiationSetCollector { + typedef DenseMap, + std::vector> MapT; + MapT InstantiatedFunctions; + +public: + void insert(const FunctionRecord &Function, unsigned FileID) { + auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end(); + while (I != E && I->FileID != FileID) + ++I; + assert(I != E && "function does not cover the given file"); + auto &Functions = InstantiatedFunctions[I->startLoc()]; + Functions.push_back(&Function); + } + + MapT::iterator begin() { return InstantiatedFunctions.begin(); } + + MapT::iterator end() { return InstantiatedFunctions.end(); } +}; + +class SegmentBuilder { + std::vector Segments; + SmallVector ActiveRegions; + + /// Start a segment with no count specified. + void startSegment(unsigned Line, unsigned Col) { + DEBUG(dbgs() << "Top level segment at " << Line << ":" << Col << "\n"); + Segments.emplace_back(Line, Col, /*IsRegionEntry=*/false); + } + + /// Start a segment with the given Region's count. + void startSegment(unsigned Line, unsigned Col, bool IsRegionEntry, + const CountedRegion &Region) { + if (Segments.empty()) + Segments.emplace_back(Line, Col, IsRegionEntry); + CoverageSegment S = Segments.back(); + // Avoid creating empty regions. + if (S.Line != Line || S.Col != Col) { + Segments.emplace_back(Line, Col, IsRegionEntry); + S = Segments.back(); + } + DEBUG(dbgs() << "Segment at " << Line << ":" << Col); + // Set this region's count. + if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) { + DEBUG(dbgs() << " with count " << Region.ExecutionCount); + Segments.back().setCount(Region.ExecutionCount); + } + DEBUG(dbgs() << "\n"); + } + + /// Start a segment for the given region. + void startSegment(const CountedRegion &Region) { + startSegment(Region.LineStart, Region.ColumnStart, true, Region); + } + + /// Pop the top region off of the active stack, starting a new segment with + /// the containing Region's count. + void popRegion() { + const CountedRegion *Active = ActiveRegions.back(); + unsigned Line = Active->LineEnd, Col = Active->ColumnEnd; + ActiveRegions.pop_back(); + if (ActiveRegions.empty()) + startSegment(Line, Col); + else + startSegment(Line, Col, false, *ActiveRegions.back()); + } + +public: + /// Build a list of CoverageSegments from a sorted list of Regions. + std::vector buildSegments(ArrayRef Regions) { + for (const auto &Region : Regions) { + // Pop any regions that end before this one starts. + while (!ActiveRegions.empty() && + ActiveRegions.back()->endLoc() <= Region.startLoc()) + popRegion(); + if (Segments.size() && Segments.back().Line == Region.LineStart && + Segments.back().Col == Region.ColumnStart) { + if (Region.Kind != coverage::CounterMappingRegion::SkippedRegion) + Segments.back().addCount(Region.ExecutionCount); + } else { + // Add this region to the stack. + ActiveRegions.push_back(&Region); + startSegment(Region); + } + } + // Pop any regions that are left in the stack. + while (!ActiveRegions.empty()) + popRegion(); + return Segments; + } +}; +} + +std::vector CoverageMapping::getUniqueSourceFiles() const { + std::vector Filenames; + for (const auto &Function : getCoveredFunctions()) + for (const auto &Filename : Function.Filenames) + Filenames.push_back(Filename); + std::sort(Filenames.begin(), Filenames.end()); + auto Last = std::unique(Filenames.begin(), Filenames.end()); + Filenames.erase(Last, Filenames.end()); + return Filenames; +} + +static Optional findMainViewFileID(StringRef SourceFile, + const FunctionRecord &Function) { + llvm::SmallVector IsExpandedFile(Function.Filenames.size(), false); + llvm::SmallVector FilenameEquivalence(Function.Filenames.size(), + false); + for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) + if (SourceFile == Function.Filenames[I]) + FilenameEquivalence[I] = true; + for (const auto &CR : Function.CountedRegions) + if (CR.Kind == CounterMappingRegion::ExpansionRegion && + FilenameEquivalence[CR.FileID]) + IsExpandedFile[CR.ExpandedFileID] = true; + for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) + if (FilenameEquivalence[I] && !IsExpandedFile[I]) + return I; + return None; +} + +static Optional findMainViewFileID(const FunctionRecord &Function) { + llvm::SmallVector IsExpandedFile(Function.Filenames.size(), false); + for (const auto &CR : Function.CountedRegions) + if (CR.Kind == CounterMappingRegion::ExpansionRegion) + IsExpandedFile[CR.ExpandedFileID] = true; + for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) + if (!IsExpandedFile[I]) + return I; + return None; +} + +static SmallSet gatherFileIDs(StringRef SourceFile, + const FunctionRecord &Function) { + SmallSet IDs; + for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) + if (SourceFile == Function.Filenames[I]) + IDs.insert(I); + return IDs; +} + +/// Sort a nested sequence of regions from a single file. +template static void sortNestedRegions(It First, It Last) { + std::sort(First, Last, + [](const CountedRegion &LHS, const CountedRegion &RHS) { + if (LHS.startLoc() == RHS.startLoc()) + // When LHS completely contains RHS, we sort LHS first. + return RHS.endLoc() < LHS.endLoc(); + return LHS.startLoc() < RHS.startLoc(); + }); +} + +static bool isExpansion(const CountedRegion &R, unsigned FileID) { + return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID; +} + +CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) { + CoverageData FileCoverage(Filename); + std::vector Regions; + + for (const auto &Function : Functions) { + auto MainFileID = findMainViewFileID(Filename, Function); + if (!MainFileID) + continue; + auto FileIDs = gatherFileIDs(Filename, Function); + for (const auto &CR : Function.CountedRegions) + if (FileIDs.count(CR.FileID)) { + Regions.push_back(CR); + if (isExpansion(CR, *MainFileID)) + FileCoverage.Expansions.emplace_back(CR, Function); + } + } + + sortNestedRegions(Regions.begin(), Regions.end()); + FileCoverage.Segments = SegmentBuilder().buildSegments(Regions); + + return FileCoverage; +} + +std::vector +CoverageMapping::getInstantiations(StringRef Filename) { + FunctionInstantiationSetCollector InstantiationSetCollector; + for (const auto &Function : Functions) { + auto MainFileID = findMainViewFileID(Filename, Function); + if (!MainFileID) + continue; + InstantiationSetCollector.insert(Function, *MainFileID); + } + + std::vector Result; + for (const auto &InstantiationSet : InstantiationSetCollector) { + if (InstantiationSet.second.size() < 2) + continue; + for (auto Function : InstantiationSet.second) + Result.push_back(Function); + } + return Result; +} + +CoverageData +CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) { + auto MainFileID = findMainViewFileID(Function); + if (!MainFileID) + return CoverageData(); + + CoverageData FunctionCoverage(Function.Filenames[*MainFileID]); + std::vector Regions; + for (const auto &CR : Function.CountedRegions) + if (CR.FileID == *MainFileID) { + Regions.push_back(CR); + if (isExpansion(CR, *MainFileID)) + FunctionCoverage.Expansions.emplace_back(CR, Function); + } + + sortNestedRegions(Regions.begin(), Regions.end()); + FunctionCoverage.Segments = SegmentBuilder().buildSegments(Regions); + + return FunctionCoverage; +} + +CoverageData +CoverageMapping::getCoverageForExpansion(const ExpansionRecord &Expansion) { + CoverageData ExpansionCoverage( + Expansion.Function.Filenames[Expansion.FileID]); + std::vector Regions; + for (const auto &CR : Expansion.Function.CountedRegions) + if (CR.FileID == Expansion.FileID) { + Regions.push_back(CR); + if (isExpansion(CR, Expansion.FileID)) + ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function); + } + + sortNestedRegions(Regions.begin(), Regions.end()); + ExpansionCoverage.Segments = SegmentBuilder().buildSegments(Regions); + + return ExpansionCoverage; +} diff --git a/lib/ProfileData/CoverageMappingReader.cpp b/lib/ProfileData/CoverageMappingReader.cpp new file mode 100644 index 0000000..6476d28 --- /dev/null +++ b/lib/ProfileData/CoverageMappingReader.cpp @@ -0,0 +1,553 @@ +//=-- CoverageMappingReader.cpp - Code coverage mapping reader ----*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for reading coverage mapping data for +// instrumentation based coverage. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/CoverageMappingReader.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/LEB128.h" + +using namespace llvm; +using namespace coverage; +using namespace object; + +#define DEBUG_TYPE "coverage-mapping" + +void CoverageMappingIterator::increment() { + // Check if all the records were read or if an error occurred while reading + // the next record. + if (Reader->readNextRecord(Record)) + *this = CoverageMappingIterator(); +} + +std::error_code RawCoverageReader::readULEB128(uint64_t &Result) { + if (Data.size() < 1) + return error(instrprof_error::truncated); + unsigned N = 0; + Result = decodeULEB128(reinterpret_cast(Data.data()), &N); + if (N > Data.size()) + return error(instrprof_error::malformed); + Data = Data.substr(N); + return success(); +} + +std::error_code RawCoverageReader::readIntMax(uint64_t &Result, + uint64_t MaxPlus1) { + if (auto Err = readULEB128(Result)) + return Err; + if (Result >= MaxPlus1) + return error(instrprof_error::malformed); + return success(); +} + +std::error_code RawCoverageReader::readSize(uint64_t &Result) { + if (auto Err = readULEB128(Result)) + return Err; + // Sanity check the number. + if (Result > Data.size()) + return error(instrprof_error::malformed); + return success(); +} + +std::error_code RawCoverageReader::readString(StringRef &Result) { + uint64_t Length; + if (auto Err = readSize(Length)) + return Err; + Result = Data.substr(0, Length); + Data = Data.substr(Length); + return success(); +} + +std::error_code RawCoverageFilenamesReader::read() { + uint64_t NumFilenames; + if (auto Err = readSize(NumFilenames)) + return Err; + for (size_t I = 0; I < NumFilenames; ++I) { + StringRef Filename; + if (auto Err = readString(Filename)) + return Err; + Filenames.push_back(Filename); + } + return success(); +} + +std::error_code RawCoverageMappingReader::decodeCounter(unsigned Value, + Counter &C) { + auto Tag = Value & Counter::EncodingTagMask; + switch (Tag) { + case Counter::Zero: + C = Counter::getZero(); + return success(); + case Counter::CounterValueReference: + C = Counter::getCounter(Value >> Counter::EncodingTagBits); + return success(); + default: + break; + } + Tag -= Counter::Expression; + switch (Tag) { + case CounterExpression::Subtract: + case CounterExpression::Add: { + auto ID = Value >> Counter::EncodingTagBits; + if (ID >= Expressions.size()) + return error(instrprof_error::malformed); + Expressions[ID].Kind = CounterExpression::ExprKind(Tag); + C = Counter::getExpression(ID); + break; + } + default: + return error(instrprof_error::malformed); + } + return success(); +} + +std::error_code RawCoverageMappingReader::readCounter(Counter &C) { + uint64_t EncodedCounter; + if (auto Err = + readIntMax(EncodedCounter, std::numeric_limits::max())) + return Err; + if (auto Err = decodeCounter(EncodedCounter, C)) + return Err; + return success(); +} + +static const unsigned EncodingExpansionRegionBit = 1 + << Counter::EncodingTagBits; + +/// \brief Read the sub-array of regions for the given inferred file id. +/// \param NumFileIDs the number of file ids that are defined for this +/// function. +std::error_code RawCoverageMappingReader::readMappingRegionsSubArray( + std::vector &MappingRegions, unsigned InferredFileID, + size_t NumFileIDs) { + uint64_t NumRegions; + if (auto Err = readSize(NumRegions)) + return Err; + unsigned LineStart = 0; + for (size_t I = 0; I < NumRegions; ++I) { + Counter C; + CounterMappingRegion::RegionKind Kind = CounterMappingRegion::CodeRegion; + + // Read the combined counter + region kind. + uint64_t EncodedCounterAndRegion; + if (auto Err = readIntMax(EncodedCounterAndRegion, + std::numeric_limits::max())) + return Err; + unsigned Tag = EncodedCounterAndRegion & Counter::EncodingTagMask; + uint64_t ExpandedFileID = 0; + if (Tag != Counter::Zero) { + if (auto Err = decodeCounter(EncodedCounterAndRegion, C)) + return Err; + } else { + // Is it an expansion region? + if (EncodedCounterAndRegion & EncodingExpansionRegionBit) { + Kind = CounterMappingRegion::ExpansionRegion; + ExpandedFileID = EncodedCounterAndRegion >> + Counter::EncodingCounterTagAndExpansionRegionTagBits; + if (ExpandedFileID >= NumFileIDs) + return error(instrprof_error::malformed); + } else { + switch (EncodedCounterAndRegion >> + Counter::EncodingCounterTagAndExpansionRegionTagBits) { + case CounterMappingRegion::CodeRegion: + // Don't do anything when we have a code region with a zero counter. + break; + case CounterMappingRegion::SkippedRegion: + Kind = CounterMappingRegion::SkippedRegion; + break; + default: + return error(instrprof_error::malformed); + } + } + } + + // Read the source range. + uint64_t LineStartDelta, CodeBeforeColumnStart, NumLines, ColumnEnd; + if (auto Err = + readIntMax(LineStartDelta, std::numeric_limits::max())) + return Err; + if (auto Err = readULEB128(CodeBeforeColumnStart)) + return Err; + bool HasCodeBefore = CodeBeforeColumnStart & 1; + uint64_t ColumnStart = CodeBeforeColumnStart >> + CounterMappingRegion::EncodingHasCodeBeforeBits; + if (ColumnStart > std::numeric_limits::max()) + return error(instrprof_error::malformed); + if (auto Err = readIntMax(NumLines, std::numeric_limits::max())) + return Err; + if (auto Err = readIntMax(ColumnEnd, std::numeric_limits::max())) + return Err; + LineStart += LineStartDelta; + // Adjust the column locations for the empty regions that are supposed to + // cover whole lines. Those regions should be encoded with the + // column range (1 -> std::numeric_limits::max()), but because + // the encoded std::numeric_limits::max() is several bytes long, + // we set the column range to (0 -> 0) to ensure that the column start and + // column end take up one byte each. + // The std::numeric_limits::max() is used to represent a column + // position at the end of the line without knowing the length of that line. + if (ColumnStart == 0 && ColumnEnd == 0) { + ColumnStart = 1; + ColumnEnd = std::numeric_limits::max(); + } + + DEBUG({ + dbgs() << "Counter in file " << InferredFileID << " " << LineStart << ":" + << ColumnStart << " -> " << (LineStart + NumLines) << ":" + << ColumnEnd << ", "; + if (Kind == CounterMappingRegion::ExpansionRegion) + dbgs() << "Expands to file " << ExpandedFileID; + else + CounterMappingContext(Expressions).dump(C, dbgs()); + dbgs() << "\n"; + }); + + MappingRegions.push_back(CounterMappingRegion( + C, InferredFileID, LineStart, ColumnStart, LineStart + NumLines, + ColumnEnd, HasCodeBefore, Kind)); + MappingRegions.back().ExpandedFileID = ExpandedFileID; + } + return success(); +} + +std::error_code RawCoverageMappingReader::read(CoverageMappingRecord &Record) { + + // Read the virtual file mapping. + llvm::SmallVector VirtualFileMapping; + uint64_t NumFileMappings; + if (auto Err = readSize(NumFileMappings)) + return Err; + for (size_t I = 0; I < NumFileMappings; ++I) { + uint64_t FilenameIndex; + if (auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size())) + return Err; + VirtualFileMapping.push_back(FilenameIndex); + } + + // Construct the files using unique filenames and virtual file mapping. + for (auto I : VirtualFileMapping) { + Filenames.push_back(TranslationUnitFilenames[I]); + } + + // Read the expressions. + uint64_t NumExpressions; + if (auto Err = readSize(NumExpressions)) + return Err; + // Create an array of dummy expressions that get the proper counters + // when the expressions are read, and the proper kinds when the counters + // are decoded. + Expressions.resize( + NumExpressions, + CounterExpression(CounterExpression::Subtract, Counter(), Counter())); + for (size_t I = 0; I < NumExpressions; ++I) { + if (auto Err = readCounter(Expressions[I].LHS)) + return Err; + if (auto Err = readCounter(Expressions[I].RHS)) + return Err; + } + + // Read the mapping regions sub-arrays. + for (unsigned InferredFileID = 0, S = VirtualFileMapping.size(); + InferredFileID < S; ++InferredFileID) { + if (auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID, + VirtualFileMapping.size())) + return Err; + } + + // Set the counters for the expansion regions. + // i.e. Counter of expansion region = counter of the first region + // from the expanded file. + // Perform multiple passes to correctly propagate the counters through + // all the nested expansion regions. + SmallVector FileIDExpansionRegionMapping; + FileIDExpansionRegionMapping.resize(VirtualFileMapping.size(), nullptr); + for (unsigned Pass = 1, S = VirtualFileMapping.size(); Pass < S; ++Pass) { + for (auto &R : MappingRegions) { + if (R.Kind != CounterMappingRegion::ExpansionRegion) + continue; + assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]); + FileIDExpansionRegionMapping[R.ExpandedFileID] = &R; + } + for (auto &R : MappingRegions) { + if (FileIDExpansionRegionMapping[R.FileID]) { + FileIDExpansionRegionMapping[R.FileID]->Count = R.Count; + FileIDExpansionRegionMapping[R.FileID] = nullptr; + } + } + } + + Record.FunctionName = FunctionName; + Record.Filenames = Filenames; + Record.Expressions = Expressions; + Record.MappingRegions = MappingRegions; + return success(); +} + +ObjectFileCoverageMappingReader::ObjectFileCoverageMappingReader( + StringRef FileName) + : CurrentRecord(0) { + auto File = llvm::object::ObjectFile::createObjectFile(FileName); + if (!File) + error(File.getError()); + else + Object = std::move(File.get()); +} + +namespace { +/// \brief The coverage mapping data for a single function. +/// It points to the function's name. +template struct CoverageMappingFunctionRecord { + IntPtrT FunctionNamePtr; + uint32_t FunctionNameSize; + uint32_t CoverageMappingSize; + uint64_t FunctionHash; +}; + +/// \brief The coverage mapping data for a single translation unit. +/// It points to the array of function coverage mapping records and the encoded +/// filenames array. +template struct CoverageMappingTURecord { + uint32_t FunctionRecordsSize; + uint32_t FilenamesSize; + uint32_t CoverageMappingsSize; + uint32_t Version; +}; + +/// \brief A helper structure to access the data from a section +/// in an object file. +struct SectionData { + StringRef Data; + uint64_t Address; + + std::error_code load(SectionRef &Section) { + if (auto Err = Section.getContents(Data)) + return Err; + Address = Section.getAddress(); + return instrprof_error::success; + } + + std::error_code get(uint64_t Pointer, size_t Size, StringRef &Result) { + if (Pointer < Address) + return instrprof_error::malformed; + auto Offset = Pointer - Address; + if (Offset + Size > Data.size()) + return instrprof_error::malformed; + Result = Data.substr(Pointer - Address, Size); + return instrprof_error::success; + } +}; +} + +template +std::error_code readCoverageMappingData( + SectionData &ProfileNames, StringRef Data, + std::vector &Records, + std::vector &Filenames) { + llvm::DenseSet UniqueFunctionMappingData; + + // Read the records in the coverage data section. + while (!Data.empty()) { + if (Data.size() < sizeof(CoverageMappingTURecord)) + return instrprof_error::malformed; + auto TU = reinterpret_cast *>(Data.data()); + Data = Data.substr(sizeof(CoverageMappingTURecord)); + switch (TU->Version) { + case CoverageMappingVersion1: + break; + default: + return instrprof_error::unsupported_version; + } + auto Version = CoverageMappingVersion(TU->Version); + + // Get the function records. + auto FunctionRecords = + reinterpret_cast *>(Data.data()); + if (Data.size() < + sizeof(CoverageMappingFunctionRecord) * TU->FunctionRecordsSize) + return instrprof_error::malformed; + Data = Data.substr(sizeof(CoverageMappingFunctionRecord) * + TU->FunctionRecordsSize); + + // Get the filenames. + if (Data.size() < TU->FilenamesSize) + return instrprof_error::malformed; + auto RawFilenames = Data.substr(0, TU->FilenamesSize); + Data = Data.substr(TU->FilenamesSize); + size_t FilenamesBegin = Filenames.size(); + RawCoverageFilenamesReader Reader(RawFilenames, Filenames); + if (auto Err = Reader.read()) + return Err; + + // Get the coverage mappings. + if (Data.size() < TU->CoverageMappingsSize) + return instrprof_error::malformed; + auto CoverageMappings = Data.substr(0, TU->CoverageMappingsSize); + Data = Data.substr(TU->CoverageMappingsSize); + + for (unsigned I = 0; I < TU->FunctionRecordsSize; ++I) { + auto &MappingRecord = FunctionRecords[I]; + + // Get the coverage mapping. + if (CoverageMappings.size() < MappingRecord.CoverageMappingSize) + return instrprof_error::malformed; + auto Mapping = + CoverageMappings.substr(0, MappingRecord.CoverageMappingSize); + CoverageMappings = + CoverageMappings.substr(MappingRecord.CoverageMappingSize); + + // Ignore this record if we already have a record that points to the same + // function name. + // This is useful to ignore the redundant records for the functions + // with ODR linkage. + if (!UniqueFunctionMappingData.insert(MappingRecord.FunctionNamePtr) + .second) + continue; + StringRef FunctionName; + if (auto Err = + ProfileNames.get(MappingRecord.FunctionNamePtr, + MappingRecord.FunctionNameSize, FunctionName)) + return Err; + Records.push_back(ObjectFileCoverageMappingReader::ProfileMappingRecord( + Version, FunctionName, MappingRecord.FunctionHash, Mapping, + FilenamesBegin, Filenames.size() - FilenamesBegin)); + } + } + + return instrprof_error::success; +} + +static const char *TestingFormatMagic = "llvmcovmtestdata"; + +static std::error_code decodeTestingFormat(StringRef Data, + SectionData &ProfileNames, + StringRef &CoverageMapping) { + Data = Data.substr(StringRef(TestingFormatMagic).size()); + if (Data.size() < 1) + return instrprof_error::truncated; + unsigned N = 0; + auto ProfileNamesSize = + decodeULEB128(reinterpret_cast(Data.data()), &N); + if (N > Data.size()) + return instrprof_error::malformed; + Data = Data.substr(N); + if (Data.size() < 1) + return instrprof_error::truncated; + N = 0; + ProfileNames.Address = + decodeULEB128(reinterpret_cast(Data.data()), &N); + if (N > Data.size()) + return instrprof_error::malformed; + Data = Data.substr(N); + if (Data.size() < ProfileNamesSize) + return instrprof_error::malformed; + ProfileNames.Data = Data.substr(0, ProfileNamesSize); + CoverageMapping = Data.substr(ProfileNamesSize); + return instrprof_error::success; +} + +ObjectFileCoverageMappingReader::ObjectFileCoverageMappingReader( + std::unique_ptr &ObjectBuffer, sys::fs::file_magic Type) + : CurrentRecord(0) { + if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic)) { + // This is a special format used for testing. + SectionData ProfileNames; + StringRef CoverageMapping; + if (auto Err = decodeTestingFormat(ObjectBuffer->getBuffer(), ProfileNames, + CoverageMapping)) { + error(Err); + return; + } + error(readCoverageMappingData(ProfileNames, CoverageMapping, + MappingRecords, Filenames)); + Object = OwningBinary(std::unique_ptr(), + std::move(ObjectBuffer)); + return; + } + + auto File = object::ObjectFile::createObjectFile( + ObjectBuffer->getMemBufferRef(), Type); + if (!File) + error(File.getError()); + else + Object = OwningBinary(std::move(File.get()), + std::move(ObjectBuffer)); +} + +std::error_code ObjectFileCoverageMappingReader::readHeader() { + const ObjectFile *OF = Object.getBinary(); + if (!OF) + return getError(); + auto BytesInAddress = OF->getBytesInAddress(); + if (BytesInAddress != 4 && BytesInAddress != 8) + return error(instrprof_error::malformed); + + // Look for the sections that we are interested in. + int FoundSectionCount = 0; + SectionRef ProfileNames, CoverageMapping; + for (const auto &Section : OF->sections()) { + StringRef Name; + if (auto Err = Section.getName(Name)) + return Err; + if (Name == "__llvm_prf_names") { + ProfileNames = Section; + } else if (Name == "__llvm_covmap") { + CoverageMapping = Section; + } else + continue; + ++FoundSectionCount; + } + if (FoundSectionCount != 2) + return error(instrprof_error::bad_header); + + // Get the contents of the given sections. + StringRef Data; + if (auto Err = CoverageMapping.getContents(Data)) + return Err; + SectionData ProfileNamesData; + if (auto Err = ProfileNamesData.load(ProfileNames)) + return Err; + + // Load the data from the found sections. + std::error_code Err; + if (BytesInAddress == 4) + Err = readCoverageMappingData(ProfileNamesData, Data, + MappingRecords, Filenames); + else + Err = readCoverageMappingData(ProfileNamesData, Data, + MappingRecords, Filenames); + if (Err) + return error(Err); + + return success(); +} + +std::error_code +ObjectFileCoverageMappingReader::readNextRecord(CoverageMappingRecord &Record) { + if (CurrentRecord >= MappingRecords.size()) + return error(instrprof_error::eof); + + FunctionsFilenames.clear(); + Expressions.clear(); + MappingRegions.clear(); + auto &R = MappingRecords[CurrentRecord]; + RawCoverageMappingReader Reader( + R.FunctionName, R.CoverageMapping, + makeArrayRef(Filenames.data() + R.FilenamesBegin, R.FilenamesSize), + FunctionsFilenames, Expressions, MappingRegions); + if (auto Err = Reader.read(Record)) + return Err; + Record.FunctionHash = R.FunctionHash; + ++CurrentRecord; + return success(); +} diff --git a/lib/ProfileData/CoverageMappingWriter.cpp b/lib/ProfileData/CoverageMappingWriter.cpp new file mode 100644 index 0000000..6969c2a --- /dev/null +++ b/lib/ProfileData/CoverageMappingWriter.cpp @@ -0,0 +1,187 @@ +//=-- CoverageMappingWriter.cpp - Code coverage mapping writer -------------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing coverage mapping data for +// instrumentation based coverage. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/CoverageMappingWriter.h" +#include "llvm/Support/LEB128.h" + +using namespace llvm; +using namespace coverage; + +void CoverageFilenamesSectionWriter::write(raw_ostream &OS) { + encodeULEB128(Filenames.size(), OS); + for (const auto &Filename : Filenames) { + encodeULEB128(Filename.size(), OS); + OS << Filename; + } +} + +namespace { +/// \brief Gather only the expressions that are used by the mapping +/// regions in this function. +class CounterExpressionsMinimizer { + ArrayRef Expressions; + llvm::SmallVector UsedExpressions; + std::vector AdjustedExpressionIDs; + +public: + void mark(Counter C) { + if (!C.isExpression()) + return; + unsigned ID = C.getExpressionID(); + AdjustedExpressionIDs[ID] = 1; + mark(Expressions[ID].LHS); + mark(Expressions[ID].RHS); + } + + void gatherUsed(Counter C) { + if (!C.isExpression() || !AdjustedExpressionIDs[C.getExpressionID()]) + return; + AdjustedExpressionIDs[C.getExpressionID()] = UsedExpressions.size(); + const auto &E = Expressions[C.getExpressionID()]; + UsedExpressions.push_back(E); + gatherUsed(E.LHS); + gatherUsed(E.RHS); + } + + CounterExpressionsMinimizer(ArrayRef Expressions, + ArrayRef MappingRegions) + : Expressions(Expressions) { + AdjustedExpressionIDs.resize(Expressions.size(), 0); + for (const auto &I : MappingRegions) + mark(I.Count); + for (const auto &I : MappingRegions) + gatherUsed(I.Count); + } + + ArrayRef getExpressions() const { return UsedExpressions; } + + /// \brief Adjust the given counter to correctly transition from the old + /// expression ids to the new expression ids. + Counter adjust(Counter C) const { + if (C.isExpression()) + C = Counter::getExpression(AdjustedExpressionIDs[C.getExpressionID()]); + return C; + } +}; +} + +/// \brief Encode the counter. +/// +/// The encoding uses the following format: +/// Low 2 bits - Tag: +/// Counter::Zero(0) - A Counter with kind Counter::Zero +/// Counter::CounterValueReference(1) - A counter with kind +/// Counter::CounterValueReference +/// Counter::Expression(2) + CounterExpression::Subtract(0) - +/// A counter with kind Counter::Expression and an expression +/// with kind CounterExpression::Subtract +/// Counter::Expression(2) + CounterExpression::Add(1) - +/// A counter with kind Counter::Expression and an expression +/// with kind CounterExpression::Add +/// Remaining bits - Counter/Expression ID. +static unsigned encodeCounter(ArrayRef Expressions, + Counter C) { + unsigned Tag = unsigned(C.getKind()); + if (C.isExpression()) + Tag += Expressions[C.getExpressionID()].Kind; + unsigned ID = C.getCounterID(); + assert(ID <= + (std::numeric_limits::max() >> Counter::EncodingTagBits)); + return Tag | (ID << Counter::EncodingTagBits); +} + +static void writeCounter(ArrayRef Expressions, Counter C, + raw_ostream &OS) { + encodeULEB128(encodeCounter(Expressions, C), OS); +} + +void CoverageMappingWriter::write(raw_ostream &OS) { + // Sort the regions in an ascending order by the file id and the starting + // location. + std::sort(MappingRegions.begin(), MappingRegions.end()); + + // Write out the fileid -> filename mapping. + encodeULEB128(VirtualFileMapping.size(), OS); + for (const auto &FileID : VirtualFileMapping) + encodeULEB128(FileID, OS); + + // Write out the expressions. + CounterExpressionsMinimizer Minimizer(Expressions, MappingRegions); + auto MinExpressions = Minimizer.getExpressions(); + encodeULEB128(MinExpressions.size(), OS); + for (const auto &E : MinExpressions) { + writeCounter(MinExpressions, Minimizer.adjust(E.LHS), OS); + writeCounter(MinExpressions, Minimizer.adjust(E.RHS), OS); + } + + // Write out the mapping regions. + // Split the regions into subarrays where each region in a + // subarray has a fileID which is the index of that subarray. + unsigned PrevLineStart = 0; + unsigned CurrentFileID = ~0U; + for (auto I = MappingRegions.begin(), E = MappingRegions.end(); I != E; ++I) { + if (I->FileID != CurrentFileID) { + // Ensure that all file ids have at least one mapping region. + assert(I->FileID == (CurrentFileID + 1)); + // Find the number of regions with this file id. + unsigned RegionCount = 1; + for (auto J = I + 1; J != E && I->FileID == J->FileID; ++J) + ++RegionCount; + // Start a new region sub-array. + encodeULEB128(RegionCount, OS); + + CurrentFileID = I->FileID; + PrevLineStart = 0; + } + Counter Count = Minimizer.adjust(I->Count); + switch (I->Kind) { + case CounterMappingRegion::CodeRegion: + writeCounter(MinExpressions, Count, OS); + break; + case CounterMappingRegion::ExpansionRegion: { + assert(Count.isZero()); + assert(I->ExpandedFileID <= + (std::numeric_limits::max() >> + Counter::EncodingCounterTagAndExpansionRegionTagBits)); + // Mark an expansion region with a set bit that follows the counter tag, + // and pack the expanded file id into the remaining bits. + unsigned EncodedTagExpandedFileID = + (1 << Counter::EncodingTagBits) | + (I->ExpandedFileID + << Counter::EncodingCounterTagAndExpansionRegionTagBits); + encodeULEB128(EncodedTagExpandedFileID, OS); + break; + } + case CounterMappingRegion::SkippedRegion: + assert(Count.isZero()); + encodeULEB128(unsigned(I->Kind) + << Counter::EncodingCounterTagAndExpansionRegionTagBits, + OS); + break; + } + assert(I->LineStart >= PrevLineStart); + encodeULEB128(I->LineStart - PrevLineStart, OS); + uint64_t CodeBeforeColumnStart = + uint64_t(I->HasCodeBefore) | + (uint64_t(I->ColumnStart) + << CounterMappingRegion::EncodingHasCodeBeforeBits); + encodeULEB128(CodeBeforeColumnStart, OS); + assert(I->LineEnd >= I->LineStart); + encodeULEB128(I->LineEnd - I->LineStart, OS); + encodeULEB128(I->ColumnEnd, OS); + PrevLineStart = I->LineStart; + } + // Ensure that all file ids have at least one mapping region. + assert(CurrentFileID == (VirtualFileMapping.size() - 1)); +} diff --git a/lib/ProfileData/InstrProf.cpp b/lib/ProfileData/InstrProf.cpp index 0121222..900dff9 100644 --- a/lib/ProfileData/InstrProf.cpp +++ b/lib/ProfileData/InstrProf.cpp @@ -14,6 +14,7 @@ #include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" using namespace llvm; @@ -55,7 +56,8 @@ class InstrProfErrorCategoryType : public std::error_category { }; } +static ManagedStatic ErrorCategory; + const std::error_category &llvm::instrprof_category() { - static InstrProfErrorCategoryType C; - return C; + return *ErrorCategory; } diff --git a/lib/ProfileData/InstrProfIndexed.h b/lib/ProfileData/InstrProfIndexed.h index 7761704..ebca7b2 100644 --- a/lib/ProfileData/InstrProfIndexed.h +++ b/lib/ProfileData/InstrProfIndexed.h @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_PROFILEDATA_INSTRPROF_INDEXED_H_ -#define LLVM_PROFILEDATA_INSTRPROF_INDEXED_H_ +#ifndef LLVM_LIB_PROFILEDATA_INSTRPROFINDEXED_H +#define LLVM_LIB_PROFILEDATA_INSTRPROFINDEXED_H +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MD5.h" @@ -46,10 +47,10 @@ static inline uint64_t ComputeHash(HashT Type, StringRef K) { } const uint64_t Magic = 0x8169666f72706cff; // "\xfflprofi\x81" -const uint64_t Version = 1; +const uint64_t Version = 2; const HashT HashType = HashT::MD5; } } // end namespace llvm -#endif // LLVM_PROFILEDATA_INSTRPROF_INDEXED_H_ +#endif diff --git a/lib/ProfileData/InstrProfReader.cpp b/lib/ProfileData/InstrProfReader.cpp index 0b36728..31ed130 100644 --- a/lib/ProfileData/InstrProfReader.cpp +++ b/lib/ProfileData/InstrProfReader.cpp @@ -13,40 +13,40 @@ //===----------------------------------------------------------------------===// #include "llvm/ProfileData/InstrProfReader.h" -#include "llvm/ProfileData/InstrProf.h" - #include "InstrProfIndexed.h" - +#include "llvm/ProfileData/InstrProf.h" #include using namespace llvm; -static std::error_code -setupMemoryBuffer(std::string Path, std::unique_ptr &Buffer) { +static ErrorOr> +setupMemoryBuffer(std::string Path) { ErrorOr> BufferOrErr = MemoryBuffer::getFileOrSTDIN(Path); if (std::error_code EC = BufferOrErr.getError()) return EC; - Buffer = std::move(BufferOrErr.get()); + auto Buffer = std::move(BufferOrErr.get()); // Sanity check the file. if (Buffer->getBufferSize() > std::numeric_limits::max()) return instrprof_error::too_large; - return instrprof_error::success; + return std::move(Buffer); } static std::error_code initializeReader(InstrProfReader &Reader) { return Reader.readHeader(); } -std::error_code -InstrProfReader::create(std::string Path, - std::unique_ptr &Result) { +ErrorOr> +InstrProfReader::create(std::string Path) { // Set up the buffer to read. - std::unique_ptr Buffer; - if (std::error_code EC = setupMemoryBuffer(Path, Buffer)) + auto BufferOrError = setupMemoryBuffer(Path); + if (std::error_code EC = BufferOrError.getError()) return EC; + auto Buffer = std::move(BufferOrError.get()); + std::unique_ptr Result; + // Create the reader. if (IndexedInstrProfReader::hasFormat(*Buffer)) Result.reset(new IndexedInstrProfReader(std::move(Buffer))); @@ -58,16 +58,20 @@ InstrProfReader::create(std::string Path, Result.reset(new TextInstrProfReader(std::move(Buffer))); // Initialize the reader and return the result. - return initializeReader(*Result); + if (std::error_code EC = initializeReader(*Result)) + return EC; + + return std::move(Result); } std::error_code IndexedInstrProfReader::create( std::string Path, std::unique_ptr &Result) { // Set up the buffer to read. - std::unique_ptr Buffer; - if (std::error_code EC = setupMemoryBuffer(Path, Buffer)) + auto BufferOrError = setupMemoryBuffer(Path); + if (std::error_code EC = BufferOrError.getError()) return EC; + auto Buffer = std::move(BufferOrError.get()); // Create the reader. if (!IndexedInstrProfReader::hasFormat(*Buffer)) return instrprof_error::bad_magic; @@ -83,8 +87,8 @@ void InstrProfIterator::Increment() { } std::error_code TextInstrProfReader::readNextRecord(InstrProfRecord &Record) { - // Skip empty lines. - while (!Line.is_at_end() && Line->empty()) + // Skip empty lines and comments. + while (!Line.is_at_end() && (Line->empty() || Line->startswith("#"))) ++Line; // If we hit EOF while looking for a name, we're done. if (Line.is_at_end()) @@ -190,6 +194,9 @@ RawInstrProfReader::readNextHeader(const char *CurrentPos) { // garbage at the end of the file. if (CurrentPos + sizeof(RawHeader) > End) return instrprof_error::malformed; + // The writer ensures each profile is padded to start at an aligned address. + if (reinterpret_cast(CurrentPos) % alignOf()) + return instrprof_error::malformed; // The magic should have the same byte order as in the previous header. uint64_t Magic = *reinterpret_cast(CurrentPos); if (Magic != swap(getRawMagic())) @@ -307,8 +314,8 @@ std::error_code IndexedInstrProfReader::readHeader() { return error(instrprof_error::bad_magic); // Read the version. - uint64_t Version = endian::readNext(Cur); - if (Version != IndexedInstrProf::Version) + FormatVersion = endian::readNext(Cur); + if (FormatVersion > IndexedInstrProf::Version) return error(instrprof_error::unsupported_version); // Read the maximal function count. @@ -331,18 +338,31 @@ std::error_code IndexedInstrProfReader::readHeader() { } std::error_code IndexedInstrProfReader::getFunctionCounts( - StringRef FuncName, uint64_t &FuncHash, std::vector &Counts) { - const auto &Iter = Index->find(FuncName); + StringRef FuncName, uint64_t FuncHash, std::vector &Counts) { + auto Iter = Index->find(FuncName); if (Iter == Index->end()) return error(instrprof_error::unknown_function); - // Found it. Make sure it's valid before giving back a result. - const InstrProfRecord &Record = *Iter; - if (Record.Name.empty()) - return error(instrprof_error::malformed); - FuncHash = Record.Hash; - Counts = Record.Counts; - return success(); + // Found it. Look for counters with the right hash. + ArrayRef Data = (*Iter).Data; + uint64_t NumCounts; + for (uint64_t I = 0, E = Data.size(); I != E; I += NumCounts) { + // The function hash comes first. + uint64_t FoundHash = Data[I++]; + // In v1, we have at least one count. Later, we have the number of counts. + if (I == E) + return error(instrprof_error::malformed); + NumCounts = FormatVersion == 1 ? E - I : Data[I++]; + // If we have more counts than data, this is bogus. + if (I + NumCounts > E) + return error(instrprof_error::malformed); + // Check for a match and fill the vector if there is one. + if (FoundHash == FuncHash) { + Counts = Data.slice(I, NumCounts); + return success(); + } + } + return error(instrprof_error::hash_mismatch); } std::error_code @@ -351,10 +371,30 @@ IndexedInstrProfReader::readNextRecord(InstrProfRecord &Record) { if (RecordIterator == Index->data_end()) return error(instrprof_error::eof); - // Read the next one. - Record = *RecordIterator; - ++RecordIterator; - if (Record.Name.empty()) + // Record the current function name. + Record.Name = (*RecordIterator).Name; + + ArrayRef Data = (*RecordIterator).Data; + // Valid data starts with a hash and either a count or the number of counts. + if (CurrentOffset + 1 > Data.size()) + return error(instrprof_error::malformed); + // First we have a function hash. + Record.Hash = Data[CurrentOffset++]; + // In version 1 we knew the number of counters implicitly, but in newer + // versions we store the number of counters next. + uint64_t NumCounts = + FormatVersion == 1 ? Data.size() - CurrentOffset : Data[CurrentOffset++]; + if (CurrentOffset + NumCounts > Data.size()) return error(instrprof_error::malformed); + // And finally the counts themselves. + Record.Counts = Data.slice(CurrentOffset, NumCounts); + + // If we've exhausted this function's data, increment the record. + CurrentOffset += NumCounts; + if (CurrentOffset == Data.size()) { + ++RecordIterator; + CurrentOffset = 0; + } + return success(); } diff --git a/lib/ProfileData/InstrProfWriter.cpp b/lib/ProfileData/InstrProfWriter.cpp index e55c299..d4cde2e 100644 --- a/lib/ProfileData/InstrProfWriter.cpp +++ b/lib/ProfileData/InstrProfWriter.cpp @@ -13,12 +13,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ProfileData/InstrProfWriter.h" +#include "InstrProfIndexed.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/OnDiskHashTable.h" -#include "InstrProfIndexed.h" - using namespace llvm; namespace { @@ -45,7 +44,9 @@ public: offset_type N = K.size(); LE.write(N); - offset_type M = (1 + V->Counts.size()) * sizeof(uint64_t); + offset_type M = 0; + for (const auto &Counts : *V) + M += (2 + Counts.second.size()) * sizeof(uint64_t); LE.write(M); return std::make_pair(N, M); @@ -59,9 +60,13 @@ public: offset_type) { using namespace llvm::support; endian::Writer LE(Out); - LE.write(V->Hash); - for (uint64_t I : V->Counts) - LE.write(I); + + for (const auto &Counts : *V) { + LE.write(Counts.first); + LE.write(Counts.second.size()); + for (uint64_t I : Counts.second) + LE.write(I); + } } }; } @@ -70,41 +75,43 @@ std::error_code InstrProfWriter::addFunctionCounts(StringRef FunctionName, uint64_t FunctionHash, ArrayRef Counters) { - auto Where = FunctionData.find(FunctionName); - if (Where == FunctionData.end()) { - // If this is the first time we've seen this function, just add it. - auto &Data = FunctionData[FunctionName]; - Data.Hash = FunctionHash; - Data.Counts = Counters; + auto &CounterData = FunctionData[FunctionName]; + + auto Where = CounterData.find(FunctionHash); + if (Where == CounterData.end()) { + // We've never seen a function with this name and hash, add it. + CounterData[FunctionHash] = Counters; + // We keep track of the max function count as we go for simplicity. + if (Counters[0] > MaxFunctionCount) + MaxFunctionCount = Counters[0]; return instrprof_error::success; } - auto &Data = Where->getValue(); - // We can only add to existing functions if they match, so we check the hash - // and number of counters. - if (Data.Hash != FunctionHash) - return instrprof_error::hash_mismatch; - if (Data.Counts.size() != Counters.size()) + // We're updating a function we've seen before. + auto &FoundCounters = Where->second; + // If the number of counters doesn't match we either have bad data or a hash + // collision. + if (FoundCounters.size() != Counters.size()) return instrprof_error::count_mismatch; - // These match, add up the counters. + for (size_t I = 0, E = Counters.size(); I < E; ++I) { - if (Data.Counts[I] + Counters[I] < Data.Counts[I]) + if (FoundCounters[I] + Counters[I] < FoundCounters[I]) return instrprof_error::counter_overflow; - Data.Counts[I] += Counters[I]; + FoundCounters[I] += Counters[I]; } + // We keep track of the max function count as we go for simplicity. + if (FoundCounters[0] > MaxFunctionCount) + MaxFunctionCount = FoundCounters[0]; + return instrprof_error::success; } void InstrProfWriter::write(raw_fd_ostream &OS) { OnDiskChainedHashTableGenerator Generator; - uint64_t MaxFunctionCount = 0; // Populate the hash table generator. - for (const auto &I : FunctionData) { + for (const auto &I : FunctionData) Generator.insert(I.getKey(), &I.getValue()); - if (I.getValue().Counts[0] > MaxFunctionCount) - MaxFunctionCount = I.getValue().Counts[0]; - } using namespace llvm::support; endian::Writer LE(OS); diff --git a/lib/ProfileData/LLVMBuild.txt b/lib/ProfileData/LLVMBuild.txt index 0a8cbe3..a7f471f 100644 --- a/lib/ProfileData/LLVMBuild.txt +++ b/lib/ProfileData/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = ProfileData parent = Libraries -required_libraries = Support +required_libraries = Core Support Object diff --git a/lib/ProfileData/SampleProf.cpp b/lib/ProfileData/SampleProf.cpp new file mode 100644 index 0000000..920c48a --- /dev/null +++ b/lib/ProfileData/SampleProf.cpp @@ -0,0 +1,51 @@ +//=-- SampleProf.cpp - Sample profiling format support --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains common definitions used in the reading and writing of +// sample profile data. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/SampleProf.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/ManagedStatic.h" + +using namespace llvm; + +namespace { +class SampleProfErrorCategoryType : public std::error_category { + const char *name() const LLVM_NOEXCEPT override { return "llvm.sampleprof"; } + std::string message(int IE) const override { + sampleprof_error E = static_cast(IE); + switch (E) { + case sampleprof_error::success: + return "Success"; + case sampleprof_error::bad_magic: + return "Invalid file format (bad magic)"; + case sampleprof_error::unsupported_version: + return "Unsupported format version"; + case sampleprof_error::too_large: + return "Too much profile data"; + case sampleprof_error::truncated: + return "Truncated profile data"; + case sampleprof_error::malformed: + return "Malformed profile data"; + case sampleprof_error::unrecognized_format: + return "Unrecognized profile encoding format"; + } + llvm_unreachable("A value of sampleprof_error has no message."); + } +}; +} + +static ManagedStatic ErrorCategory; + +const std::error_category &llvm::sampleprof_category() { + return *ErrorCategory; +} diff --git a/lib/ProfileData/SampleProfReader.cpp b/lib/ProfileData/SampleProfReader.cpp new file mode 100644 index 0000000..b39bfd6 --- /dev/null +++ b/lib/ProfileData/SampleProfReader.cpp @@ -0,0 +1,399 @@ +//===- SampleProfReader.cpp - Read LLVM sample profile data ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the class that reads LLVM sample profiles. It +// supports two file formats: text and binary. The textual representation +// is useful for debugging and testing purposes. The binary representation +// is more compact, resulting in smaller file sizes. However, they can +// both be used interchangeably. +// +// NOTE: If you are making changes to the file format, please remember +// to document them in the Clang documentation at +// tools/clang/docs/UsersManual.rst. +// +// Text format +// ----------- +// +// Sample profiles are written as ASCII text. The file is divided into +// sections, which correspond to each of the functions executed at runtime. +// Each section has the following format +// +// function1:total_samples:total_head_samples +// offset1[.discriminator]: number_of_samples [fn1:num fn2:num ... ] +// offset2[.discriminator]: number_of_samples [fn3:num fn4:num ... ] +// ... +// offsetN[.discriminator]: number_of_samples [fn5:num fn6:num ... ] +// +// The file may contain blank lines between sections and within a +// section. However, the spacing within a single line is fixed. Additional +// spaces will result in an error while reading the file. +// +// Function names must be mangled in order for the profile loader to +// match them in the current translation unit. The two numbers in the +// function header specify how many total samples were accumulated in the +// function (first number), and the total number of samples accumulated +// in the prologue of the function (second number). This head sample +// count provides an indicator of how frequently the function is invoked. +// +// Each sampled line may contain several items. Some are optional (marked +// below): +// +// a. Source line offset. This number represents the line number +// in the function where the sample was collected. The line number is +// always relative to the line where symbol of the function is +// defined. So, if the function has its header at line 280, the offset +// 13 is at line 293 in the file. +// +// Note that this offset should never be a negative number. This could +// happen in cases like macros. The debug machinery will register the +// line number at the point of macro expansion. So, if the macro was +// expanded in a line before the start of the function, the profile +// converter should emit a 0 as the offset (this means that the optimizers +// will not be able to associate a meaningful weight to the instructions +// in the macro). +// +// b. [OPTIONAL] Discriminator. This is used if the sampled program +// was compiled with DWARF discriminator support +// (http://wiki.dwarfstd.org/index.php?title=Path_Discriminators). +// DWARF discriminators are unsigned integer values that allow the +// compiler to distinguish between multiple execution paths on the +// same source line location. +// +// For example, consider the line of code ``if (cond) foo(); else bar();``. +// If the predicate ``cond`` is true 80% of the time, then the edge +// into function ``foo`` should be considered to be taken most of the +// time. But both calls to ``foo`` and ``bar`` are at the same source +// line, so a sample count at that line is not sufficient. The +// compiler needs to know which part of that line is taken more +// frequently. +// +// This is what discriminators provide. In this case, the calls to +// ``foo`` and ``bar`` will be at the same line, but will have +// different discriminator values. This allows the compiler to correctly +// set edge weights into ``foo`` and ``bar``. +// +// c. Number of samples. This is an integer quantity representing the +// number of samples collected by the profiler at this source +// location. +// +// d. [OPTIONAL] Potential call targets and samples. If present, this +// line contains a call instruction. This models both direct and +// number of samples. For example, +// +// 130: 7 foo:3 bar:2 baz:7 +// +// The above means that at relative line offset 130 there is a call +// instruction that calls one of ``foo()``, ``bar()`` and ``baz()``, +// with ``baz()`` being the relatively more frequently called target. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/SampleProfReader.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Regex.h" + +using namespace llvm::sampleprof; +using namespace llvm; + +/// \brief Print the samples collected for a function on stream \p OS. +/// +/// \param OS Stream to emit the output to. +void FunctionSamples::print(raw_ostream &OS) { + OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size() + << " sampled lines\n"; + for (const auto &SI : BodySamples) { + LineLocation Loc = SI.first; + const SampleRecord &Sample = SI.second; + OS << "\tline offset: " << Loc.LineOffset + << ", discriminator: " << Loc.Discriminator + << ", number of samples: " << Sample.getSamples(); + if (Sample.hasCalls()) { + OS << ", calls:"; + for (const auto &I : Sample.getCallTargets()) + OS << " " << I.first() << ":" << I.second; + } + OS << "\n"; + } + OS << "\n"; +} + +/// \brief Dump the function profile for \p FName. +/// +/// \param FName Name of the function to print. +/// \param OS Stream to emit the output to. +void SampleProfileReader::dumpFunctionProfile(StringRef FName, + raw_ostream &OS) { + OS << "Function: " << FName << ": "; + Profiles[FName].print(OS); +} + +/// \brief Dump all the function profiles found on stream \p OS. +void SampleProfileReader::dump(raw_ostream &OS) { + for (const auto &I : Profiles) + dumpFunctionProfile(I.getKey(), OS); +} + +/// \brief Load samples from a text file. +/// +/// See the documentation at the top of the file for an explanation of +/// the expected format. +/// +/// \returns true if the file was loaded successfully, false otherwise. +std::error_code SampleProfileReaderText::read() { + line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#'); + + // Read the profile of each function. Since each function may be + // mentioned more than once, and we are collecting flat profiles, + // accumulate samples as we parse them. + Regex HeadRE("^([^0-9].*):([0-9]+):([0-9]+)$"); + Regex LineSampleRE("^([0-9]+)\\.?([0-9]+)?: ([0-9]+)(.*)$"); + Regex CallSampleRE(" +([^0-9 ][^ ]*):([0-9]+)"); + while (!LineIt.is_at_eof()) { + // Read the header of each function. + // + // Note that for function identifiers we are actually expecting + // mangled names, but we may not always get them. This happens when + // the compiler decides not to emit the function (e.g., it was inlined + // and removed). In this case, the binary will not have the linkage + // name for the function, so the profiler will emit the function's + // unmangled name, which may contain characters like ':' and '>' in its + // name (member functions, templates, etc). + // + // The only requirement we place on the identifier, then, is that it + // should not begin with a number. + SmallVector Matches; + if (!HeadRE.match(*LineIt, &Matches)) { + reportParseError(LineIt.line_number(), + "Expected 'mangled_name:NUM:NUM', found " + *LineIt); + return sampleprof_error::malformed; + } + assert(Matches.size() == 4); + StringRef FName = Matches[1]; + unsigned NumSamples, NumHeadSamples; + Matches[2].getAsInteger(10, NumSamples); + Matches[3].getAsInteger(10, NumHeadSamples); + Profiles[FName] = FunctionSamples(); + FunctionSamples &FProfile = Profiles[FName]; + FProfile.addTotalSamples(NumSamples); + FProfile.addHeadSamples(NumHeadSamples); + ++LineIt; + + // Now read the body. The body of the function ends when we reach + // EOF or when we see the start of the next function. + while (!LineIt.is_at_eof() && isdigit((*LineIt)[0])) { + if (!LineSampleRE.match(*LineIt, &Matches)) { + reportParseError( + LineIt.line_number(), + "Expected 'NUM[.NUM]: NUM[ mangled_name:NUM]*', found " + *LineIt); + return sampleprof_error::malformed; + } + assert(Matches.size() == 5); + unsigned LineOffset, NumSamples, Discriminator = 0; + Matches[1].getAsInteger(10, LineOffset); + if (Matches[2] != "") + Matches[2].getAsInteger(10, Discriminator); + Matches[3].getAsInteger(10, NumSamples); + + // If there are function calls in this line, generate a call sample + // entry for each call. + std::string CallsLine(Matches[4]); + while (CallsLine != "") { + SmallVector CallSample; + if (!CallSampleRE.match(CallsLine, &CallSample)) { + reportParseError(LineIt.line_number(), + "Expected 'mangled_name:NUM', found " + CallsLine); + return sampleprof_error::malformed; + } + StringRef CalledFunction = CallSample[1]; + unsigned CalledFunctionSamples; + CallSample[2].getAsInteger(10, CalledFunctionSamples); + FProfile.addCalledTargetSamples(LineOffset, Discriminator, + CalledFunction, CalledFunctionSamples); + CallsLine = CallSampleRE.sub("", CallsLine); + } + + FProfile.addBodySamples(LineOffset, Discriminator, NumSamples); + ++LineIt; + } + } + + return sampleprof_error::success; +} + +template ErrorOr SampleProfileReaderBinary::readNumber() { + unsigned NumBytesRead = 0; + std::error_code EC; + uint64_t Val = decodeULEB128(Data, &NumBytesRead); + + if (Val > std::numeric_limits::max()) + EC = sampleprof_error::malformed; + else if (Data + NumBytesRead > End) + EC = sampleprof_error::truncated; + else + EC = sampleprof_error::success; + + if (EC) { + reportParseError(0, EC.message()); + return EC; + } + + Data += NumBytesRead; + return static_cast(Val); +} + +ErrorOr SampleProfileReaderBinary::readString() { + std::error_code EC; + StringRef Str(reinterpret_cast(Data)); + if (Data + Str.size() + 1 > End) { + EC = sampleprof_error::truncated; + reportParseError(0, EC.message()); + return EC; + } + + Data += Str.size() + 1; + return Str; +} + +std::error_code SampleProfileReaderBinary::read() { + while (!at_eof()) { + auto FName(readString()); + if (std::error_code EC = FName.getError()) + return EC; + + Profiles[*FName] = FunctionSamples(); + FunctionSamples &FProfile = Profiles[*FName]; + + auto Val = readNumber(); + if (std::error_code EC = Val.getError()) + return EC; + FProfile.addTotalSamples(*Val); + + Val = readNumber(); + if (std::error_code EC = Val.getError()) + return EC; + FProfile.addHeadSamples(*Val); + + // Read the samples in the body. + auto NumRecords = readNumber(); + if (std::error_code EC = NumRecords.getError()) + return EC; + for (unsigned I = 0; I < *NumRecords; ++I) { + auto LineOffset = readNumber(); + if (std::error_code EC = LineOffset.getError()) + return EC; + + auto Discriminator = readNumber(); + if (std::error_code EC = Discriminator.getError()) + return EC; + + auto NumSamples = readNumber(); + if (std::error_code EC = NumSamples.getError()) + return EC; + + auto NumCalls = readNumber(); + if (std::error_code EC = NumCalls.getError()) + return EC; + + for (unsigned J = 0; J < *NumCalls; ++J) { + auto CalledFunction(readString()); + if (std::error_code EC = CalledFunction.getError()) + return EC; + + auto CalledFunctionSamples = readNumber(); + if (std::error_code EC = CalledFunctionSamples.getError()) + return EC; + + FProfile.addCalledTargetSamples(*LineOffset, *Discriminator, + *CalledFunction, + *CalledFunctionSamples); + } + + FProfile.addBodySamples(*LineOffset, *Discriminator, *NumSamples); + } + } + + return sampleprof_error::success; +} + +std::error_code SampleProfileReaderBinary::readHeader() { + Data = reinterpret_cast(Buffer->getBufferStart()); + End = Data + Buffer->getBufferSize(); + + // Read and check the magic identifier. + auto Magic = readNumber(); + if (std::error_code EC = Magic.getError()) + return EC; + else if (*Magic != SPMagic()) + return sampleprof_error::bad_magic; + + // Read the version number. + auto Version = readNumber(); + if (std::error_code EC = Version.getError()) + return EC; + else if (*Version != SPVersion()) + return sampleprof_error::unsupported_version; + + return sampleprof_error::success; +} + +bool SampleProfileReaderBinary::hasFormat(const MemoryBuffer &Buffer) { + const uint8_t *Data = + reinterpret_cast(Buffer.getBufferStart()); + uint64_t Magic = decodeULEB128(Data); + return Magic == SPMagic(); +} + +/// \brief Prepare a memory buffer for the contents of \p Filename. +/// +/// \returns an error code indicating the status of the buffer. +static ErrorOr> +setupMemoryBuffer(std::string Filename) { + auto BufferOrErr = MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = BufferOrErr.getError()) + return EC; + auto Buffer = std::move(BufferOrErr.get()); + + // Sanity check the file. + if (Buffer->getBufferSize() > std::numeric_limits::max()) + return sampleprof_error::too_large; + + return std::move(Buffer); +} + +/// \brief Create a sample profile reader based on the format of the input file. +/// +/// \param Filename The file to open. +/// +/// \param Reader The reader to instantiate according to \p Filename's format. +/// +/// \param C The LLVM context to use to emit diagnostics. +/// +/// \returns an error code indicating the status of the created reader. +ErrorOr> +SampleProfileReader::create(StringRef Filename, LLVMContext &C) { + auto BufferOrError = setupMemoryBuffer(Filename); + if (std::error_code EC = BufferOrError.getError()) + return EC; + + auto Buffer = std::move(BufferOrError.get()); + std::unique_ptr Reader; + if (SampleProfileReaderBinary::hasFormat(*Buffer)) + Reader.reset(new SampleProfileReaderBinary(std::move(Buffer), C)); + else + Reader.reset(new SampleProfileReaderText(std::move(Buffer), C)); + + if (std::error_code EC = Reader->readHeader()) + return EC; + + return std::move(Reader); +} diff --git a/lib/ProfileData/SampleProfWriter.cpp b/lib/ProfileData/SampleProfWriter.cpp new file mode 100644 index 0000000..c95267a --- /dev/null +++ b/lib/ProfileData/SampleProfWriter.cpp @@ -0,0 +1,126 @@ +//===- SampleProfWriter.cpp - Write LLVM sample profile data --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the class that writes LLVM sample profiles. It +// supports two file formats: text and binary. The textual representation +// is useful for debugging and testing purposes. The binary representation +// is more compact, resulting in smaller file sizes. However, they can +// both be used interchangeably. +// +// See lib/ProfileData/SampleProfReader.cpp for documentation on each of the +// supported formats. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/SampleProfWriter.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorOr.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Regex.h" + +using namespace llvm::sampleprof; +using namespace llvm; + +/// \brief Write samples to a text file. +bool SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) { + if (S.empty()) + return true; + + OS << FName << ":" << S.getTotalSamples() << ":" << S.getHeadSamples() + << "\n"; + + for (const auto &I : S.getBodySamples()) { + LineLocation Loc = I.first; + const SampleRecord &Sample = I.second; + if (Loc.Discriminator == 0) + OS << Loc.LineOffset << ": "; + else + OS << Loc.LineOffset << "." << Loc.Discriminator << ": "; + + OS << Sample.getSamples(); + + for (const auto &J : Sample.getCallTargets()) + OS << " " << J.first() << ":" << J.second; + OS << "\n"; + } + + return true; +} + +SampleProfileWriterBinary::SampleProfileWriterBinary(StringRef F, + std::error_code &EC) + : SampleProfileWriter(F, EC, sys::fs::F_None) { + if (EC) + return; + + // Write the file header. + encodeULEB128(SPMagic(), OS); + encodeULEB128(SPVersion(), OS); +} + +/// \brief Write samples to a binary file. +/// +/// \returns true if the samples were written successfully, false otherwise. +bool SampleProfileWriterBinary::write(StringRef FName, + const FunctionSamples &S) { + if (S.empty()) + return true; + + OS << FName; + encodeULEB128(0, OS); + encodeULEB128(S.getTotalSamples(), OS); + encodeULEB128(S.getHeadSamples(), OS); + encodeULEB128(S.getBodySamples().size(), OS); + for (const auto &I : S.getBodySamples()) { + LineLocation Loc = I.first; + const SampleRecord &Sample = I.second; + encodeULEB128(Loc.LineOffset, OS); + encodeULEB128(Loc.Discriminator, OS); + encodeULEB128(Sample.getSamples(), OS); + encodeULEB128(Sample.getCallTargets().size(), OS); + for (const auto &J : Sample.getCallTargets()) { + std::string Callee = J.first(); + unsigned CalleeSamples = J.second; + OS << Callee; + encodeULEB128(0, OS); + encodeULEB128(CalleeSamples, OS); + } + } + + return true; +} + +/// \brief Create a sample profile writer based on the specified format. +/// +/// \param Filename The file to create. +/// +/// \param Writer The writer to instantiate according to the specified format. +/// +/// \param Format Encoding format for the profile file. +/// +/// \returns an error code indicating the status of the created writer. +ErrorOr> +SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) { + std::error_code EC; + std::unique_ptr Writer; + + if (Format == SPF_Binary) + Writer.reset(new SampleProfileWriterBinary(Filename, EC)); + else if (Format == SPF_Text) + Writer.reset(new SampleProfileWriterText(Filename, EC)); + else + EC = sampleprof_error::unrecognized_format; + + if (EC) + return EC; + + return std::move(Writer); +} diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp index 7989e30..393ecf4 100644 --- a/lib/Support/APFloat.cpp +++ b/lib/Support/APFloat.cpp @@ -35,8 +35,7 @@ using namespace llvm; /* Assumed in hexadecimal significand parsing, and conversion to hexadecimal strings. */ -#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] -COMPILE_TIME_ASSERT(integerPartWidth % 4 == 0); +static_assert(integerPartWidth % 4 == 0, "Part width must be divisible by 4!"); namespace llvm { @@ -212,15 +211,15 @@ skipLeadingZeroesAndAnyDot(StringRef::iterator begin, StringRef::iterator end, { StringRef::iterator p = begin; *dot = end; - while (*p == '0' && p != end) + while (p != end && *p == '0') p++; - if (*p == '.') { + if (p != end && *p == '.') { *dot = p++; assert(end - begin != 1 && "Significand has no digits"); - while (*p == '0' && p != end) + while (p != end && *p == '0') p++; } @@ -927,7 +926,10 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) assert(semantics == rhs.semantics); precision = semantics->precision; - newPartsCount = partCountForBits(precision * 2); + + // Allocate space for twice as many bits as the original significand, plus one + // extra bit for the addition to overflow into. + newPartsCount = partCountForBits(precision * 2 + 1); if (newPartsCount > 4) fullSignificand = new integerPart[newPartsCount]; @@ -949,13 +951,14 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) // *this = a23 . a22 ... a0 * 2^e1 // rhs = b23 . b22 ... b0 * 2^e2 // the result of multiplication is: - // *this = c47 c46 . c45 ... c0 * 2^(e1+e2) - // Note that there are two significant bits at the left-hand side of the - // radix point. Move the radix point toward left by one bit, and adjust - // exponent accordingly. - exponent += 1; - - if (addend) { + // *this = c48 c47 c46 . c45 ... c0 * 2^(e1+e2) + // Note that there are three significant bits at the left-hand side of the + // radix point: two for the multiplication, and an overflow bit for the + // addition (that will always be zero at this point). Move the radix point + // toward left by two bits, and adjust exponent accordingly. + exponent += 2; + + if (addend && addend->isNonZero()) { // The intermediate result of the multiplication has "2 * precision" // signicant bit; adjust the addend to be consistent with mul result. // @@ -965,13 +968,13 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) opStatus status; unsigned int extendedPrecision; - /* Normalize our MSB. */ - extendedPrecision = 2 * precision; - if (omsb != extendedPrecision) { + // Normalize our MSB to one below the top bit to allow for overflow. + extendedPrecision = 2 * precision + 1; + if (omsb != extendedPrecision - 1) { assert(extendedPrecision > omsb); APInt::tcShiftLeft(fullSignificand, newPartsCount, - extendedPrecision - omsb); - exponent -= extendedPrecision - omsb; + (extendedPrecision - 1) - omsb); + exponent -= (extendedPrecision - 1) - omsb; } /* Create new semantics. */ @@ -988,6 +991,14 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) status = extendedAddend.convert(extendedSemantics, rmTowardZero, &ignored); assert(status == opOK); (void)status; + + // Shift the significand of the addend right by one bit. This guarantees + // that the high bit of the significand is zero (same as fullSignificand), + // so the addition will overflow (if it does overflow at all) into the top bit. + lost_fraction = extendedAddend.shiftSignificandRight(1); + assert(lost_fraction == lfExactlyZero && + "Lost precision while shifting addend for fused-multiply-add."); + lost_fraction = addOrSubtractSignificand(extendedAddend, false); /* Restore our state. */ @@ -1003,7 +1014,7 @@ APFloat::multiplySignificand(const APFloat &rhs, const APFloat *addend) // having "precision" significant-bits. First, move the radix point from // poision "2*precision - 1" to "precision - 1". The exponent need to be // adjusted by "2*precision - 1" - "precision - 1" = "precision". - exponent -= precision; + exponent -= precision + 1; // In case MSB resides at the left-hand side of radix point, shift the // mantissa right by some amount to make sure the MSB reside right before @@ -1801,7 +1812,7 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand, extended-precision calculation. */ if (isFiniteNonZero() && multiplicand.isFiniteNonZero() && - addend.isFiniteNonZero()) { + addend.isFinite()) { lostFraction lost_fraction; lost_fraction = multiplySignificand(multiplicand, &addend); @@ -1812,7 +1823,7 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand, /* If two numbers add (exactly) to zero, IEEE 754 decrees it is a positive zero unless rounding to minus infinity, except that adding two like-signed zeroes gives that zero. */ - if (category == fcZero && sign != addend.sign) + if (category == fcZero && !(fs & opUnderflow) && sign != addend.sign) sign = (rounding_mode == rmTowardNegative); } else { fs = multiplySpecials(multiplicand); @@ -3377,7 +3388,9 @@ void APFloat::makeLargest(bool Negative) { // internal consistency. const unsigned NumUnusedHighBits = PartCount*integerPartWidth - semantics->precision; - significand[PartCount - 1] = ~integerPart(0) >> NumUnusedHighBits; + significand[PartCount - 1] = (NumUnusedHighBits < integerPartWidth) + ? (~integerPart(0) >> NumUnusedHighBits) + : 0; } /// Make this number the smallest magnitude denormal number in the given @@ -3904,3 +3917,20 @@ APFloat::makeZero(bool Negative) { exponent = semantics->minExponent-1; APInt::tcSet(significandParts(), 0, partCount()); } + +APFloat llvm::scalbn(APFloat X, int Exp) { + if (X.isInfinity() || X.isZero() || X.isNaN()) + return std::move(X); + + auto MaxExp = X.getSemantics().maxExponent; + auto MinExp = X.getSemantics().minExponent; + if (Exp > (MaxExp - X.exponent)) + // Overflow saturates to infinity. + return APFloat::getInf(X.getSemantics(), X.isNegative()); + if (Exp < (MinExp - X.exponent)) + // Underflow saturates to zero. + return APFloat::getZero(X.getSemantics(), X.isNegative()); + + X.exponent += Exp; + return std::move(X); +} diff --git a/lib/Support/APInt.cpp b/lib/Support/APInt.cpp index fa929eb..0ddc2ab 100644 --- a/lib/Support/APInt.cpp +++ b/lib/Support/APInt.cpp @@ -454,8 +454,10 @@ APInt APInt::XorSlowCase(const APInt& RHS) const { for (unsigned i = 0; i < numWords; ++i) val[i] = pVal[i] ^ RHS.pVal[i]; + APInt Result(val, getBitWidth()); // 0^0==1 so clear the high bits in case they got set. - return APInt(val, getBitWidth()).clearUnusedBits(); + Result.clearUnusedBits(); + return Result; } APInt APInt::operator*(const APInt& RHS) const { @@ -473,7 +475,8 @@ APInt APInt::operator+(const APInt& RHS) const { return APInt(BitWidth, VAL + RHS.VAL); APInt Result(BitWidth, 0); add(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - return Result.clearUnusedBits(); + Result.clearUnusedBits(); + return Result; } APInt APInt::operator-(const APInt& RHS) const { @@ -482,7 +485,8 @@ APInt APInt::operator-(const APInt& RHS) const { return APInt(BitWidth, VAL - RHS.VAL); APInt Result(BitWidth, 0); sub(Result.pVal, this->pVal, RHS.pVal, getNumWords()); - return Result.clearUnusedBits(); + Result.clearUnusedBits(); + return Result; } bool APInt::EqualSlowCase(const APInt& RHS) const { @@ -1114,7 +1118,9 @@ APInt APInt::ashr(unsigned shiftAmt) const { uint64_t fillValue = (isNegative() ? -1ULL : 0); for (unsigned i = breakWord+1; i < getNumWords(); ++i) val[i] = fillValue; - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } /// Logical right-shift this APInt by shiftAmt. @@ -1151,7 +1157,9 @@ APInt APInt::lshr(unsigned shiftAmt) const { // If we are shifting less than a word, compute the shift with a simple carry if (shiftAmt < APINT_BITS_PER_WORD) { lshrNear(val, pVal, getNumWords(), shiftAmt); - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Compute some values needed by the remaining shift algorithms @@ -1164,7 +1172,9 @@ APInt APInt::lshr(unsigned shiftAmt) const { val[i] = pVal[i+offset]; for (unsigned i = getNumWords()-offset; i < getNumWords(); i++) val[i] = 0; - return APInt(val,BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Shift the low order words @@ -1178,7 +1188,9 @@ APInt APInt::lshr(unsigned shiftAmt) const { // Remaining words are 0 for (unsigned i = breakWord+1; i < getNumWords(); ++i) val[i] = 0; - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } /// Left-shift this APInt by shiftAmt. @@ -1211,7 +1223,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const { val[i] = pVal[i] << shiftAmt | carry; carry = pVal[i] >> (APINT_BITS_PER_WORD - shiftAmt); } - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Compute some values needed by the remaining shift algorithms @@ -1224,7 +1238,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const { val[i] = 0; for (unsigned i = offset; i < getNumWords(); i++) val[i] = pVal[i-offset]; - return APInt(val,BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } // Copy whole words from this to Result. @@ -1235,7 +1251,9 @@ APInt APInt::shlSlowCase(unsigned shiftAmt) const { val[offset] = pVal[0] << wordShift; for (i = 0; i < offset; ++i) val[i] = 0; - return APInt(val, BitWidth).clearUnusedBits(); + APInt Result(val, BitWidth); + Result.clearUnusedBits(); + return Result; } APInt APInt::rotl(const APInt &rotateAmt) const { @@ -1303,7 +1321,7 @@ APInt APInt::sqrt() const { // Okay, all the short cuts are exhausted. We must compute it. The following // is a classical Babylonian method for computing the square root. This code - // was adapted to APINt from a wikipedia article on such computations. + // was adapted to APInt from a wikipedia article on such computations. // See http://www.wikipedia.org/ and go to the page named // Calculate_an_integer_square_root. unsigned nbits = BitWidth, i = 4; @@ -1938,6 +1956,18 @@ APInt APInt::srem(const APInt &RHS) const { void APInt::udivrem(const APInt &LHS, const APInt &RHS, APInt &Quotient, APInt &Remainder) { + assert(LHS.BitWidth == RHS.BitWidth && "Bit widths must be the same"); + + // First, deal with the easy case + if (LHS.isSingleWord()) { + assert(RHS.VAL != 0 && "Divide by zero?"); + uint64_t QuotVal = LHS.VAL / RHS.VAL; + uint64_t RemVal = LHS.VAL % RHS.VAL; + Quotient = APInt(LHS.BitWidth, QuotVal); + Remainder = APInt(LHS.BitWidth, RemVal); + return; + } + // Get some size facts about the dividend and divisor unsigned lhsBits = LHS.getActiveBits(); unsigned lhsWords = !lhsBits ? 0 : (APInt::whichWord(lhsBits - 1) + 1); @@ -2046,19 +2076,29 @@ APInt APInt::umul_ov(const APInt &RHS, bool &Overflow) const { return Res; } -APInt APInt::sshl_ov(unsigned ShAmt, bool &Overflow) const { - Overflow = ShAmt >= getBitWidth(); +APInt APInt::sshl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); if (Overflow) - ShAmt = getBitWidth()-1; + return APInt(BitWidth, 0); if (isNonNegative()) // Don't allow sign change. - Overflow = ShAmt >= countLeadingZeros(); + Overflow = ShAmt.uge(countLeadingZeros()); else - Overflow = ShAmt >= countLeadingOnes(); + Overflow = ShAmt.uge(countLeadingOnes()); return *this << ShAmt; } +APInt APInt::ushl_ov(const APInt &ShAmt, bool &Overflow) const { + Overflow = ShAmt.uge(getBitWidth()); + if (Overflow) + return APInt(BitWidth, 0); + + Overflow = ShAmt.ugt(countLeadingZeros()); + + return *this << ShAmt; +} + @@ -2270,8 +2310,7 @@ void APInt::print(raw_ostream &OS, bool isSigned) const { // Assumed by lowHalf, highHalf, partMSB and partLSB. A fairly safe // and unrestricting assumption. -#define COMPILE_TIME_ASSERT(cond) extern int CTAssert[(cond) ? 1 : -1] -COMPILE_TIME_ASSERT(integerPartWidth % 2 == 0); +static_assert(integerPartWidth % 2 == 0, "Part width must be divisible by 2!"); /* Some handy functions local to this file. */ namespace { diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 80b6ab84..fa62591 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -1,3 +1,32 @@ +set(system_libs) +if( NOT MSVC ) + if( MINGW ) + set(system_libs ${system_libs} imagehlp psapi shell32) + elseif( CMAKE_HOST_UNIX ) + if( HAVE_LIBRT ) + set(system_libs ${system_libs} rt) + endif() + if( HAVE_LIBDL ) + set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) + endif() + if(LLVM_ENABLE_TERMINFO) + if(HAVE_TERMINFO) + set(system_libs ${system_libs} ${TERMINFO_LIBS}) + endif() + endif() + if( LLVM_ENABLE_THREADS AND HAVE_LIBATOMIC ) + set(system_libs ${system_libs} atomic) + endif() + if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) + set(system_libs ${system_libs} pthread) + endif() + if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) + set(system_libs ${system_libs} z) + endif() + set(system_libs ${system_libs} m) + endif( MINGW ) +endif( NOT MSVC ) + add_llvm_library(LLVMSupport APFloat.cpp APInt.cpp @@ -36,9 +65,11 @@ add_llvm_library(LLVMSupport Locale.cpp LockFileManager.cpp ManagedStatic.cpp + MathExtras.cpp MemoryBuffer.cpp MemoryObject.cpp MD5.cpp + Options.cpp PluginLoader.cpp PrettyStackTrace.cpp RandomNumberGenerator.cpp @@ -49,12 +80,11 @@ add_llvm_library(LLVMSupport SourceMgr.cpp SpecialCaseList.cpp Statistic.cpp - StreamableMemoryObject.cpp + StreamingMemoryObject.cpp StringExtras.cpp StringMap.cpp StringPool.cpp StringRef.cpp - StringRefMemoryObject.cpp SystemUtils.cpp Timer.cpp ToolOutputFile.cpp @@ -76,7 +106,6 @@ add_llvm_library(LLVMSupport DynamicLibrary.cpp Errno.cpp Host.cpp - IncludeFile.cpp Memory.cpp Mutex.cpp Path.cpp @@ -116,38 +145,8 @@ add_llvm_library(LLVMSupport Windows/ThreadLocal.inc Windows/TimeValue.inc Windows/Watchdog.inc - ) -set(system_libs) -if( NOT MSVC ) - if( MINGW ) - set(system_libs ${system_libs} imagehlp psapi shell32) - elseif( CMAKE_HOST_UNIX ) - if( HAVE_LIBRT ) - set(system_libs ${system_libs} rt) - endif() - if( HAVE_LIBDL ) - set(system_libs ${system_libs} ${CMAKE_DL_LIBS}) - endif() - if(LLVM_ENABLE_TERMINFO) - if(HAVE_TERMINFO) - set(system_libs ${system_libs} ${TERMINFO_LIBS}) - endif() - endif() - if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) - set(system_libs ${system_libs} pthread) - endif() - if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) - set(system_libs ${system_libs} z) - endif() - endif( MINGW ) -endif( NOT MSVC ) - -if(POLICY CMP0022 AND BUILD_SHARED_LIBS) - # FIXME: Should this be really PUBLIC? - target_link_libraries(LLVMSupport PUBLIC ${system_libs}) -else() - target_link_libraries(LLVMSupport ${cmake_2_8_12_INTERFACE} ${system_libs}) -endif() + LINK_LIBS ${system_libs} + ) set_property(TARGET LLVMSupport PROPERTY LLVM_SYSTEM_LIBS "${system_libs}") diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 586ecea..40570ca 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -17,6 +17,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/CommandLine.h" +#include "llvm-c/Support.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -43,7 +44,8 @@ using namespace cl; //===----------------------------------------------------------------------===// // Template instantiations and anchors. // -namespace llvm { namespace cl { +namespace llvm { +namespace cl { TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); TEMPLATE_INSTANTIATION(class basic_parser); @@ -59,7 +61,8 @@ TEMPLATE_INSTANTIATION(class opt); TEMPLATE_INSTANTIATION(class opt); TEMPLATE_INSTANTIATION(class opt); TEMPLATE_INSTANTIATION(class opt); -} } // end namespace llvm::cl +} +} // end namespace llvm::cl // Pin the vtables to this file. void GenericOptionValue::anchor() {} @@ -86,19 +89,16 @@ static char ProgramName[80] = ""; static const char *ProgramOverview = nullptr; // This collects additional help to be printed. -static ManagedStatic > MoreHelp; +static ManagedStatic> MoreHelp; -extrahelp::extrahelp(const char *Help) - : morehelp(Help) { +extrahelp::extrahelp(const char *Help) : morehelp(Help) { MoreHelp->push_back(Help); } static bool OptionListChanged = false; // MarkOptionsChanged - Internal helper function. -void cl::MarkOptionsChanged() { - OptionListChanged = true; -} +void cl::MarkOptionsChanged() { OptionListChanged = true; } /// RegisteredOptionList - This is the list of the command line options that /// have statically constructed themselves. @@ -113,14 +113,20 @@ void Option::addArgument() { } void Option::removeArgument() { - assert(NextRegistered && "argument never registered"); - assert(RegisteredOptionList == this && "argument is not the last registered"); - RegisteredOptionList = NextRegistered; + if (RegisteredOptionList == this) { + RegisteredOptionList = NextRegistered; + MarkOptionsChanged(); + return; + } + Option *O = RegisteredOptionList; + for (; O->NextRegistered != this; O = O->NextRegistered) + ; + O->NextRegistered = NextRegistered; MarkOptionsChanged(); } // This collects the different option categories that have been registered. -typedef SmallPtrSet OptionCatSet; +typedef SmallPtrSet OptionCatSet; static ManagedStatic RegisteredOptionCategories; // Initialise the general option category. @@ -131,7 +137,8 @@ void OptionCategory::registerCategory() { RegisteredOptionCategories->end(), [this](const OptionCategory *Category) { return getName() == Category->getName(); - }) == 0 && "Duplicate option categories"); + }) == 0 && + "Duplicate option categories"); RegisteredOptionCategories->insert(this); } @@ -142,12 +149,12 @@ void OptionCategory::registerCategory() { /// GetOptionInfo - Scan the list of registered options, turning them into data /// structures that are easier to handle. -static void GetOptionInfo(SmallVectorImpl &PositionalOpts, - SmallVectorImpl &SinkOpts, - StringMap &OptionsMap) { +static void GetOptionInfo(SmallVectorImpl
: - -#CFG: Atoms: -#CFG: - StartAddress: 0x0000000000000000 -#CFG: Size: 4 -#CFG: Type: Text - -## 0: 48 8b 46 08 mov 0x8(%rsi),%rax -#CFG: - Inst: MOV64rm -#CFG: Size: 4 -#CFG: Ops: [ RRAX, RRSI, I1, R, I8, R ] - - -#CFG: - StartAddress: 0x0000000000000004 -#CFG: Size: 1 -#CFG: Type: Data - -## 4: 06 (bad) -#CFG: Content: '06' - -#CFG: - StartAddress: 0x0000000000000005 -#CFG: Size: 1 -#CFG: Type: Text - -## 5: 90 nop -#CFG: - Inst: NOOP -#CFG: Size: 1 -#CFG: Ops: [ ] - -Symbols: - Global: - - Name: main - Type: STT_FUNC - Section: .text - Value: 0x0 - Size: 6 diff --git a/test/Object/X86/objdump-cfg-textatomsize.yaml b/test/Object/X86/objdump-cfg-textatomsize.yaml deleted file mode 100644 index 87cb4e1..0000000 --- a/test/Object/X86/objdump-cfg-textatomsize.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# RUN: yaml2obj -format=elf %s | llvm-objdump -d -yaml-cfg=%t - && FileCheck --check-prefix=CFG < %t %s -# REQUIRES: shell -# -# Generated from: -# main: -# .LBL0_1: -# jmp .LBL0_1 -# - -!ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - Content: "EBFE" - -## 0000000000000000
: - -#CFG: Atoms: -#CFG: - StartAddress: 0x0000000000000000 -#CFG: Size: 2 - -## 0: eb fe jmp $-2 -#CFG: - Inst: JMP_1 -#CFG: Size: 2 -#CFG: Ops: [ I-2 ] - -Symbols: - Global: - - Name: main - Type: STT_FUNC - Section: .text - Value: 0x0 - Size: 2 diff --git a/test/Object/X86/objdump-cfg.yaml b/test/Object/X86/objdump-cfg.yaml deleted file mode 100644 index c5bff03..0000000 --- a/test/Object/X86/objdump-cfg.yaml +++ /dev/null @@ -1,86 +0,0 @@ -# RUN: yaml2obj -format=elf %s | llvm-objdump -d -yaml-cfg=%t - && FileCheck --check-prefix=CFG < %t %s -# REQUIRES: shell -# -# Generated from: -# main: -# movl $48, %eax -# cmpl $3, %edi -# jl .LBB0_2 -# movq 8(%rsi), %rax -# movsbl (%rax), %eax -# .LBB0_2: -# ret -# - -!ELF -FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_REL - Machine: EM_X86_64 -Sections: - - Name: .text - Type: SHT_PROGBITS - Flags: [ SHF_ALLOC, SHF_EXECINSTR ] - Content: "B83000000083FF037C07488B46080FBE00C3" - -## 0000000000000000
: - -#CFG: Atoms: -#CFG: - StartAddress: 0x0000000000000000 -#CFG: Size: 10 - -## 0: b8 30 00 00 00 mov $0x30,%eax -#CFG: - Inst: MOV32ri -#CFG: Size: 5 -#CFG: Ops: [ REAX, I48 ] - -## 5: 83 ff 03 cmp $0x3,%edi -#CFG: - Inst: CMP32ri8 -#CFG: Size: 3 -#CFG: Ops: [ REDI, I3 ] - -## 8: 7c 07 jl 11 -#CFG: - Inst: JL_1 -#CFG: Size: 2 -#CFG: Ops: [ I7 ] - -#CFG: - StartAddress: 0x000000000000000A -#CFG: Size: 7 - -## a: 48 8b 46 08 mov 0x8(%rsi),%rax -#CFG: - Inst: MOV64rm -#CFG: Size: 4 -#CFG: Ops: [ RRAX, RRSI, I1, R, I8, R ] - -## e: 0f be 00 movsbl (%rax),%eax -#CFG: - Inst: MOVSX32rm8 -#CFG: Size: 3 -#CFG: Ops: [ REAX, RRAX, I1, R, I0, R ] -#CFG: - StartAddress: 0x0000000000000011 -#CFG: Size: 1 - -## 11: c3 retq -#CFG: - Inst: RET -#CFG: Size: 1 -#CFG: Ops: [ ] - -Symbols: - Global: - - Name: main - Type: STT_FUNC - Section: .text - Value: 0x0 - Size: 18 - -#CFG: Functions: -#CFG: BasicBlocks: -#CFG: - Address: 0x0000000000000000 -#CFG: Preds: [ ] -#CFG: Succs: [ 0x0000000000000011, 0x000000000000000A ] -#CFG: - Address: 0x0000000000000011 -#CFG: Preds: [ 0x0000000000000000, 0x000000000000000A ] -#CFG: Succs: [ ] -#CFG: - Address: 0x000000000000000A -#CFG: Preds: [ 0x0000000000000000 ] -#CFG: Succs: [ 0x0000000000000011 ] diff --git a/test/Object/X86/objdump-disassembly-inline-relocations.test b/test/Object/X86/objdump-disassembly-inline-relocations.test index 7861576..3871bcb 100644 --- a/test/Object/X86/objdump-disassembly-inline-relocations.test +++ b/test/Object/X86/objdump-disassembly-inline-relocations.test @@ -76,11 +76,11 @@ ELF-i386: main: ELF-i386: 0: 83 ec 0c subl $12, %esp ELF-i386: 3: c7 44 24 08 00 00 00 00 movl $0, 8(%esp) ELF-i386: b: c7 04 24 00 00 00 00 movl $0, (%esp) -ELF-i386: e: R_386_32 Unknown +ELF-i386: e: R_386_32 .rodata.str1.1 ELF-i386: 12: e8 fc ff ff ff calll -4 -ELF-i386: 13: R_386_PC32 Unknown +ELF-i386: 13: R_386_PC32 puts ELF-i386: 17: e8 fc ff ff ff calll -4 -ELF-i386: 18: R_386_PC32 Unknown +ELF-i386: 18: R_386_PC32 SomeOtherFunction ELF-i386: 1c: 8b 44 24 08 movl 8(%esp), %eax ELF-i386: 20: 83 c4 0c addl $12, %esp ELF-i386: 23: c3 ret diff --git a/test/Object/X86/objdump-disassembly-symbolic.test b/test/Object/X86/objdump-disassembly-symbolic.test deleted file mode 100644 index 95a5fc8..0000000 --- a/test/Object/X86/objdump-disassembly-symbolic.test +++ /dev/null @@ -1,68 +0,0 @@ -RUN: llvm-objdump -d -symbolize %p/../Inputs/trivial-object-test.elf-x86-64 \ -RUN: | FileCheck %s -check-prefix ELF-x86-64 -RUN: llvm-objdump -d -symbolize %p/../Inputs/trivial-object-test.macho-x86-64 \ -RUN: | FileCheck %s -check-prefix MACHO-x86-64 - -# Generate this using: -# ld trivial-object-test.macho-x86-64 -undefined dynamic_lookup -RUN: llvm-objdump -d -symbolize %p/../Inputs/trivial-executable-test.macho-x86-64 \ -RUN: | FileCheck %s -check-prefix MACHO-STUBS-x86-64 - -ELF-x86-64: file format ELF64-x86-64 -ELF-x86-64: Disassembly of section .text: -ELF-x86-64: main: -ELF-x86-64: 0: 48 83 ec 08 subq $8, %rsp -ELF-x86-64: 4: c7 44 24 04 00 00 00 00 movl $0, 4(%rsp) -ELF-x86-64: c: bf 00 00 00 00 movl $.rodata.str1.1, %edi -ELF-x86-64: 11: e8 00 00 00 00 callq puts-4 -ELF-x86-64: 16: 30 c0 xorb %al, %al -ELF-x86-64: 18: e8 00 00 00 00 callq SomeOtherFunction-4 -ELF-x86-64: 1d: 8b 44 24 04 movl 4(%rsp), %eax -ELF-x86-64: 21: 48 83 c4 08 addq $8, %rsp -ELF-x86-64: 25: c3 ret - -MACHO-x86-64: file format Mach-O 64-bit x86-64 -MACHO-x86-64: Disassembly of section __TEXT,__text: -MACHO-x86-64: _main: -MACHO-x86-64: 0: 48 83 ec 08 subq $8, %rsp -MACHO-x86-64: 4: c7 44 24 04 00 00 00 00 movl $0, 4(%rsp) -MACHO-x86-64: c: 48 8d 3d 00 00 00 00 leaq L_.str(%rip), %rdi ## literal pool for: Hello World! -MACHO-x86-64: 13: e8 00 00 00 00 callq _puts -MACHO-x86-64: 18: 30 c0 xorb %al, %al -MACHO-x86-64: 1a: e8 00 00 00 00 callq _SomeOtherFunction -MACHO-x86-64: 1f: 8b 44 24 04 movl 4(%rsp), %eax -MACHO-x86-64: 23: 48 83 c4 08 addq $8, %rsp -MACHO-x86-64: 27: c3 ret - -MACHO-STUBS-x86-64: file format Mach-O 64-bit x86-64 -MACHO-STUBS-x86-64: Disassembly of section __TEXT,__text: -MACHO-STUBS-x86-64: _main: -MACHO-STUBS-x86-64: 1f90: 48 83 ec 08 subq $8, %rsp -MACHO-STUBS-x86-64: 1f94: c7 44 24 04 00 00 00 00 movl $0, 4(%rsp) -MACHO-STUBS-x86-64: 1f9c: 48 8d 3d 45 00 00 00 leaq 69(%rip), %rdi ## literal pool for: Hello World! -MACHO-STUBS-x86-64: 1fa3: e8 16 00 00 00 callq puts -MACHO-STUBS-x86-64: 1fa8: 30 c0 xorb %al, %al -MACHO-STUBS-x86-64: 1faa: e8 09 00 00 00 callq SomeOtherFunction -MACHO-STUBS-x86-64: 1faf: 8b 44 24 04 movl 4(%rsp), %eax -MACHO-STUBS-x86-64: 1fb3: 48 83 c4 08 addq $8, %rsp -MACHO-STUBS-x86-64: 1fb7: c3 ret - - -RUN: llvm-objdump -d -symbolize %p/../Inputs/relocation-relocatable.elf-i386 \ -RUN: | FileCheck %s -check-prefix ELF-i386-REL - -ELF-i386-REL: Disassembly of section .text: -ELF-i386-REL-NEXT: f: -ELF-i386-REL-NEXT: 0: e9 fc ff ff ff jmp h -ELF-i386-REL: g: -ELF-i386-REL-NEXT: 5: e9 fc ff ff ff jmp f - - -RUN: llvm-objdump -d -symbolize %p/../Inputs/relocation-dynamic.elf-i386 \ -RUN: | FileCheck %s -check-prefix ELF-i386-DYN - -ELF-i386-DYN: Disassembly of section .text: -ELF-i386-DYN-NEXT: f: -ELF-i386-DYN-NEXT: 1a4: e9 fc ff ff ff jmp h -ELF-i386-DYN: g: -ELF-i386-DYN-NEXT: 1a9: e9 fc ff ff ff jmp f diff --git a/test/Object/X86/objdump-label.test b/test/Object/X86/objdump-label.test new file mode 100644 index 0000000..f8b9334 --- /dev/null +++ b/test/Object/X86/objdump-label.test @@ -0,0 +1,10 @@ +RUN: llvm-objdump -d %p/../Inputs/trivial-label-test.elf-x86-64 \ +RUN: | FileCheck %s -check-prefix ELF-x86-64 + +ELF-x86-64: file format ELF64-x86-64 +ELF-x86-64: Disassembly of section .text: +ELF-x86-64: foo: +ELF-x86-64: 0: 90 nop +ELF-x86-64: bum: +ELF-x86-64: 1: 90 nop + diff --git a/test/Object/archive-error-tmp.txt b/test/Object/archive-error-tmp.txt index 0618986..ed3b145 100644 --- a/test/Object/archive-error-tmp.txt +++ b/test/Object/archive-error-tmp.txt @@ -1,5 +1,3 @@ -REQUIRES: shell - Test that no temporary file is left behind on error. RUN: rm -rf %t diff --git a/test/Object/archive-symtab.test b/test/Object/archive-symtab.test index 0899828..01f17bc 100644 --- a/test/Object/archive-symtab.test +++ b/test/Object/archive-symtab.test @@ -61,6 +61,7 @@ RUN: llvm-ranlib %t.a RUN: llvm-nm -M %t.a | FileCheck %s RUN: llvm-nm -M %p/Inputs/macho-archive-x86_64.a | FileCheck %s --check-prefix=BSD-MachO +RUN: llvm-nm -M %p/Inputs/macho-archive-unsorted-x86_64.a | FileCheck %s --check-prefix=BSD-MachO BSD-MachO: Archive map BSD-MachO: _bar in bar.o diff --git a/test/Object/archive-toc.test b/test/Object/archive-toc.test index 4195c40..79a6e0e 100644 --- a/test/Object/archive-toc.test +++ b/test/Object/archive-toc.test @@ -26,3 +26,11 @@ CHECK: rw-r--r-- 1002/102 8 2004-11-19 03:24:02.000000000 evenlen CHECK-NEXT: rw-r--r-- 1002/102 7 2004-11-19 03:24:02.000000000 oddlen CHECK-NEXT: rwxr-xr-x 1002/102 1465 2004-11-19 03:24:02.000000000 very_long_bytecode_file_name.bc CHECK-NEXT: rw-r--r-- 1002/102 2280 2004-11-19 03:24:02.000000000 IsNAN.o + +Test reading a thin archive created by gnu ar +RUN: env TZ=GMT llvm-ar tv %p/Inputs/thin.a | FileCheck %s --check-prefix=THIN -strict-whitespace + +THIN: rw-r--r-- 1000/1000 8 2014-12-16 00:56:27.000000000 evenlen +THIN-NEXT: rw-r--r-- 1000/1000 7 2014-12-16 00:56:27.000000000 oddlen +THIN-NEXT: rwxr-xr-x 1000/1000 1465 2014-12-16 00:56:27.000000000 very_long_bytecode_file_name.bc +THIN-NEXT: rw-r--r-- 1000/1000 2280 2014-12-16 00:56:27.000000000 IsNAN.o diff --git a/test/Object/coff-archive-short.test b/test/Object/coff-archive-short.test index 2aee956..9f7165b 100644 --- a/test/Object/coff-archive-short.test +++ b/test/Object/coff-archive-short.test @@ -5,7 +5,7 @@ # than 15 characters, thus, unlike coff_archive.lib, it has no string # table as the third member. # -RUN: llvm-nm --numeric-sort -M %p/Inputs/coff_archive_short.lib | FileCheck -check-prefix=CHECKIDX %s +RUN: llvm-nm -a --numeric-sort -M %p/Inputs/coff_archive_short.lib | FileCheck -check-prefix=CHECKIDX %s CHECKIDX: Archive map CHECKIDX: _shortfn1 in short1.obj diff --git a/test/Object/coff-archive.test b/test/Object/coff-archive.test index 3b0aa0c..239a96b 100644 --- a/test/Object/coff-archive.test +++ b/test/Object/coff-archive.test @@ -1,7 +1,7 @@ # # Check if the index is appearing properly in the output file # -RUN: llvm-nm --numeric-sort -M %p/Inputs/coff_archive.lib | FileCheck -check-prefix=CHECKIDX %s +RUN: llvm-nm -a --numeric-sort -M %p/Inputs/coff_archive.lib | FileCheck -check-prefix=CHECKIDX %s CHECKIDX: Archive map CHECKIDX: ??0invalid_argument@std@@QAE@PBD@Z in Debug\mymath.obj diff --git a/test/Object/mri-addlib.test b/test/Object/mri-addlib.test new file mode 100644 index 0000000..745bcf6 --- /dev/null +++ b/test/Object/mri-addlib.test @@ -0,0 +1,14 @@ +; RUN: echo create %t.a > %t.mri +; RUN: echo addlib %p/Inputs/GNU.a >> %t.mri +; RUN: echo addlib %p/Inputs/archive-test.a-gnu-minimal >> %t.mri +; RUN: echo save >> %t.mri +; RUN: echo end >> %t.mri + +; RUN: llvm-ar -M < %t.mri +; RUN: llvm-ar t %t.a | FileCheck %s + +; CHECK: evenlen +; CHECK-NEXT: oddlen +; CHECK-NEXT: very_long_bytecode_file_name.bc +; CHECK-NEXT: IsNAN.o +; CHECK-NEXT: test diff --git a/test/Object/mri-addmod.test b/test/Object/mri-addmod.test new file mode 100644 index 0000000..f104848 --- /dev/null +++ b/test/Object/mri-addmod.test @@ -0,0 +1,33 @@ +; RUN: echo create %t.a > %t.mri +; RUN: echo "addmod \"%p/Inputs/trivial-object-test.elf-x86-64\" " >> %t.mri +; RUN: echo save >> %t.mri +; RUN: echo end >> %t.mri + +; RUN: llvm-ar -M < %t.mri +; RUN: llvm-nm -M %t.a | FileCheck %s + +; CHECK: Archive map +; CHECK-NEXT: main in trivial-object-test.elf-x86-64 + +; CHECK: trivial-object-test.elf-x86-64: +; CHECK-NEXT: U SomeOtherFunction +; CHECK-NEXT: 0000000000000000 T main +; CHECK-NEXT: U puts + +; Now test that CREATE overwrites an existing file. +; RUN: echo create %t.a > %t2.mri +; RUN: echo addmod %p/Inputs/trivial-object-test2.elf-x86-64 >> %t2.mri +; RUN: echo save >> %t2.mri +; RUN: echo end >> %t2.mri + +; RUN: llvm-ar -M < %t2.mri +; RUN: llvm-nm -M %t.a | FileCheck --check-prefix=NEW %s + +; NEW: Archive map +; NEW-NEXT: foo in trivial-object-test2.elf-x86-64 +; NEW-NEXT: main in trivial-object-test2.elf-x86-64 + +; NEW: trivial-object-test2.elf-x86-64: +; NEW-NEXT: 0000000000000000 t bar +; NEW-NEXT: 0000000000000006 T foo +; NEW-NEXT: 0000000000000016 T main diff --git a/test/Object/mri-crlf.test b/test/Object/mri-crlf.test new file mode 100644 index 0000000..3411b55 --- /dev/null +++ b/test/Object/mri-crlf.test @@ -0,0 +1 @@ +; RUN: llvm-ar -M < %S/Inputs/mri-crlf.mri diff --git a/test/Object/mri1.test b/test/Object/mri1.test new file mode 100644 index 0000000..3d27db7 --- /dev/null +++ b/test/Object/mri1.test @@ -0,0 +1,6 @@ +; RUN: echo create %t.a > %t.mri +; RUN: echo save >> %t.mri +; RUN: echo end >> %t.mri + +; RUN: llvm-ar -M < %t.mri +; RUN: llvm-ar t %t.a diff --git a/test/Object/mri2.test b/test/Object/mri2.test new file mode 100644 index 0000000..0c24179 --- /dev/null +++ b/test/Object/mri2.test @@ -0,0 +1,7 @@ +; RUN: echo create %t.a > %t.mri +; RUN: echo create %t.a >> %t.mri +; RUN: echo save >> %t.mri +; RUN: echo end >> %t.mri + +; RUN: not llvm-ar -M < %t.mri 2>&1 | FileCheck %s +; CHECK: Editing multiple archives not supported diff --git a/test/Object/mri3.test b/test/Object/mri3.test new file mode 100644 index 0000000..bdc5399 --- /dev/null +++ b/test/Object/mri3.test @@ -0,0 +1,6 @@ +; RUN: echo save > %t.mri +; RUN: echo create %t.a >> %t.mri +; RUN: echo end >> %t.mri + +; RUN: not llvm-ar -M < %t.mri 2>&1 | FileCheck %s +; CHECK: File already saved. diff --git a/test/Object/mri4.test b/test/Object/mri4.test new file mode 100644 index 0000000..a24c14d --- /dev/null +++ b/test/Object/mri4.test @@ -0,0 +1,4 @@ +; RUN: echo abc > %t.mri + +; RUN: not llvm-ar -M < %t.mri 2>&1 | FileCheck %s +; CHECK: Unknown command: abc. diff --git a/test/Object/mri5.test b/test/Object/mri5.test new file mode 100644 index 0000000..9811424 --- /dev/null +++ b/test/Object/mri5.test @@ -0,0 +1,2 @@ +; RUN: not llvm-ar -M t < %s 2>&1 | FileCheck %s +; CHECK: Cannot mix -M and other options. diff --git a/test/Object/nm-archive.test b/test/Object/nm-archive.test index 7dbc22a..a9ae9cb 100644 --- a/test/Object/nm-archive.test +++ b/test/Object/nm-archive.test @@ -1,4 +1,4 @@ -RUN: llvm-nm %p/Inputs/archive-test.a-coff-i386 \ +RUN: llvm-nm -a %p/Inputs/archive-test.a-coff-i386 \ RUN: | FileCheck %s -check-prefix COFF COFF: trivial-object-test.coff-i386: @@ -9,6 +9,15 @@ COFF-NEXT: U _SomeOtherFunction COFF-NEXT: 00000000 T _main COFF-NEXT: U _puts +RUN: llvm-nm -a -o %p/Inputs/archive-test.a-coff-i386 \ +RUN: | FileCheck %s -check-prefix COFF-o + +COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d .data +COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 t .text +COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 d L_.str +COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: U _SomeOtherFunction +COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: 00000000 T _main +COFF-o: {{.*}}/archive-test.a-coff-i386:trivial-object-test.coff-i386: U _puts RUN: llvm-as %p/Inputs/trivial.ll -o=%t1 RUN: rm -f %t2 diff --git a/test/Object/nm-trivial-object.test b/test/Object/nm-trivial-object.test index 49c7683..0135f2d 100644 --- a/test/Object/nm-trivial-object.test +++ b/test/Object/nm-trivial-object.test @@ -1,9 +1,13 @@ -RUN: yaml2obj %p/Inputs/COFF/i386.yaml | llvm-nm - \ +RUN: yaml2obj %p/Inputs/COFF/i386.yaml | llvm-nm -a -S - \ RUN: | FileCheck %s -check-prefix COFF -RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm - \ +RUN: yaml2obj %p/Inputs/COFF/x86-64.yaml | llvm-nm -a -S - \ RUN: | FileCheck %s -check-prefix COFF RUN: llvm-nm %p/Inputs/trivial-object-test.elf-i386 \ RUN: | FileCheck %s -check-prefix ELF +RUN: llvm-nm -o %p/Inputs/trivial-object-test.elf-i386 \ +RUN: | FileCheck %s -check-prefix ELF-o +RUN: llvm-nm -u %p/Inputs/trivial-object-test.elf-i386 \ +RUN: | FileCheck %s -check-prefix ELF-u RUN: llvm-nm %p/Inputs/trivial-object-test.elf-x86-64 \ RUN: | FileCheck %s -check-prefix ELF64 RUN: llvm-nm %p/Inputs/weak.elf-x86-64 \ @@ -26,9 +30,13 @@ RUN: llvm-nm %p/Inputs/macho-text-data-bss.macho-x86_64 -s __DATA __data \ RUN: | FileCheck %s -check-prefix macho-s RUN: llvm-nm -x %p/Inputs/macho-text-data-bss.macho-x86_64 \ RUN: | FileCheck %s -check-prefix macho-x +RUN: llvm-nm -o %p/Inputs/macho-text-data-bss.macho-x86_64 \ +RUN: | FileCheck %s -check-prefix macho-o RUN: llvm-nm -p -a %p/Inputs/macho-hello-g.macho-x86_64 \ RUN: | FileCheck %s -check-prefix macho-pa -RUN: llvm-nm %p/Inputs/common.coff-i386 \ +RUN: llvm-nm -u %p/Inputs/macho-hello-g.macho-x86_64 \ +RUN: | FileCheck %s -check-prefix macho-u +RUN: llvm-nm -S -a %p/Inputs/common.coff-i386 \ RUN: | FileCheck %s -check-prefix COFF-COMMON RUN: llvm-nm %p/Inputs/relocatable-with-section-address.elf-x86-64 \ RUN: | FileCheck %s -check-prefix ELF-SEC-ADDR64 @@ -41,20 +49,20 @@ RUN: llvm-nm | FileCheck %s -check-prefix A-OUT REQUIRES: shell -COFF: 00000000 d .data -COFF: 00000000 t .text -COFF: 00000000 d L{{_?}}.str +COFF: 00000000 {{.*}} d .data +COFF: 00000000 {{.*}} t .text +COFF: 00000000 0000000d d L{{_?}}.str COFF: U {{_?}}SomeOtherFunction -COFF: 00000000 T {{_?}}main +COFF: 00000000 {{.*}} T {{_?}}main COFF: U {{_?}}puts -COFF-COMMON: 00000000 b .bss -COFF-COMMON-NEXT: 00000000 d .data -COFF-COMMON-NEXT: 00000000 d .drectve -COFF-COMMON-NEXT: 00000000 n .file -COFF-COMMON-NEXT: 00000000 r .rdata$zzz -COFF-COMMON-NEXT: 00000000 t .text -COFF-COMMON-NEXT: C _a +COFF-COMMON: 00000000 00000000 b .bss +COFF-COMMON-NEXT: 00000000 00000000 d .data +COFF-COMMON-NEXT: 00000000 00000014 d .drectve +COFF-COMMON-NEXT: 00000000 00000000 n .file +COFF-COMMON-NEXT: 00000000 00000014 r .rdata$zzz +COFF-COMMON-NEXT: 00000000 00000000 t .text +COFF-COMMON-NEXT: 00000004 C _a ELF-NOT: U @@ -62,6 +70,13 @@ ELF: U SomeOtherFunction ELF: 00000000 T main ELF: U puts +ELF-o: {{.*}}/trivial-object-test.elf-i386: U SomeOtherFunction +ELF-o: {{.*}}/trivial-object-test.elf-i386: 00000000 T main +ELF-o: {{.*}}/trivial-object-test.elf-i386: U puts + +ELF-u: U SomeOtherFunction +ELF-u: U puts + ELF64: U SomeOtherFunction ELF64: 0000000000000000 T main ELF64: U puts @@ -117,6 +132,13 @@ macho-x: 000000000000000c 0f 02 0000 00000004 _d macho-x: 0000000000000000 0f 01 0000 00000001 _t macho-x: 0000000000000048 0f 05 0000 00000007 _t.eh + +macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000030 s EH_frame0 +macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000070 b _b +macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 000000000000000c D _d +macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000000 T _t +macho-o: {{.*}}/macho-text-data-bss.macho-x86_64: 0000000000000048 S _t.eh + macho-pa: 0000000000000000 - 00 0000 SO /Volumes/SandBox/ macho-pa: 0000000000000000 - 00 0000 SO hello.c macho-pa: 0000000053c8408d - 03 0001 OSO /Volumes/SandBox/hello.o @@ -130,6 +152,9 @@ macho-pa: 0000000100000f30 T _main macho-pa: U _printf macho-pa: U dyld_stub_binder +macho-u: _printf +macho-u: dyld_stub_binder + Test that nm uses addresses even with ELF .o files. ELF-SEC-ADDR64: 0000000000000058 D a ELF-SEC-ADDR64-NEXT: 000000000000005c D b diff --git a/test/Object/nm-universal-binary.test b/test/Object/nm-universal-binary.test index 889377b..0cced18 100644 --- a/test/Object/nm-universal-binary.test +++ b/test/Object/nm-universal-binary.test @@ -2,10 +2,16 @@ RUN: llvm-nm -arch all %p/Inputs/macho-universal.x86_64.i386 \ RUN: | FileCheck %s -check-prefix CHECK-OBJ RUN: llvm-nm -arch x86_64 %p/Inputs/macho-universal.x86_64.i386 \ RUN: | FileCheck %s -check-prefix CHECK-OBJ-x86_64 +RUN: not llvm-nm -arch armv7m %p/Inputs/macho-universal.x86_64.i386 2>&1 \ +RUN: | FileCheck %s -check-prefix CHECK-OBJ-armv7m +RUN: not llvm-nm -arch foobar %p/Inputs/macho-universal.x86_64.i386 2>&1 \ +RUN: | FileCheck %s -check-prefix CHECK-OBJ-foobar RUN: llvm-nm -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \ RUN: | FileCheck %s -check-prefix CHECK-AR RUN: llvm-nm -arch i386 %p/Inputs/macho-universal-archive.x86_64.i386 \ RUN: | FileCheck %s -check-prefix CHECK-AR-i386 +RUN: llvm-nm -o -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \ +RUN: | FileCheck %s -check-prefix CHECK-AR-o CHECK-OBJ: macho-universal.x86_64.i386 (for architecture x86_64): CHECK-OBJ: 0000000100000f60 T _main @@ -16,6 +22,12 @@ CHECK-OBJ-x86_64: 0000000100000000 T __mh_execute_header CHECK-OBJ-x86_64: 0000000100000f60 T _main CHECK-OBJ-x86_64: U dyld_stub_binder +CHECK-OBJ-armv7m-NOT: Unknown architecture named +CHECK-OBJ-armv7m: does not contain architecture + +CHECK-OBJ-foobar: Unknown architecture named +CHECK-OBJ-foobar: does not contain architecture + CHECK-AR: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64): CHECK-AR: 0000000000000068 s EH_frame0 CHECK-AR: 000000000000003b s L_.str @@ -29,3 +41,11 @@ CHECK-AR: 00000000 T _foo CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o): CHECK-AR-i386: 00000008 D _bar CHECK-AR-i386: 00000000 T _foo + +CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000068 s EH_frame0 +CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 000000000000003b s L_.str +CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000000 T _main +CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: 0000000000000080 S _main.eh +CHECK-AR-o: (for architecture x86_64):{{.*}}/macho-universal-archive.x86_64.i386:hello.o: U _printf +CHECK-AR-o: (for architecture i386):{{.*}}/macho-universal-archive.x86_64.i386:foo.o: 00000008 D _bar +CHECK-AR-o: (for architecture i386):{{.*}}/macho-universal-archive.x86_64.i386:foo.o: 00000000 T _foo diff --git a/test/Object/obj2yaml-coff-long-section-name.test b/test/Object/obj2yaml-coff-long-section-name.test new file mode 100644 index 0000000..5457aef --- /dev/null +++ b/test/Object/obj2yaml-coff-long-section-name.test @@ -0,0 +1,3 @@ +RUN: yaml2obj %p/Inputs/COFF/long-section-name.yaml | obj2yaml | FileCheck %s --check-prefix COFF-I386 + +COFF-I386: Name: .long_section_name diff --git a/test/Object/obj2yaml-coff-section-aux-symbol.test b/test/Object/obj2yaml-coff-section-aux-symbol.test new file mode 100644 index 0000000..55ce5f0 --- /dev/null +++ b/test/Object/obj2yaml-coff-section-aux-symbol.test @@ -0,0 +1,96 @@ +RUN: yaml2obj %p/Inputs/COFF/section-aux-symbol.yaml | obj2yaml | FileCheck %s --check-prefix COFF-I386 + +COFF-I386: sections: +COFF-I386-NEXT: - Name: .CRT +COFF-I386: symbols: +COFF-I386: - Name: '.CRT$XCAA' +COFF-I386-NEXT: Value: 4 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 1 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XIAA' +COFF-I386-NEXT: Value: 16 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 1 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XLD' +COFF-I386-NEXT: Value: 36 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 1 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XLC' +COFF-I386-NEXT: Value: 32 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 1 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XDZ' +COFF-I386-NEXT: Value: 48 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XDA' +COFF-I386-NEXT: Value: 44 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XLZ' +COFF-I386-NEXT: Value: 40 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XLA' +COFF-I386-NEXT: Value: 28 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XIC' +COFF-I386-NEXT: Value: 20 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 1 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XCZ' +COFF-I386-NEXT: Value: 8 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XCA' +COFF-I386-NEXT: Value: 0 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XIZ' +COFF-I386-NEXT: Value: 24 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 +COFF-I386: - Name: '.CRT$XIA' +COFF-I386-NEXT: Value: 12 +COFF-I386: StorageClass: IMAGE_SYM_CLASS_STATIC +COFF-I386-NEXT: SectionDefinition: +COFF-I386-NEXT: Length: 4 +COFF-I386-NEXT: NumberOfRelocations: 0 +COFF-I386-NEXT: NumberOfLinenumbers: 0 diff --git a/test/Object/objdump-export-list.test b/test/Object/objdump-export-list.test new file mode 100644 index 0000000..74344c1 --- /dev/null +++ b/test/Object/objdump-export-list.test @@ -0,0 +1,4 @@ +RUN: llvm-objdump -exports-trie %p/Inputs/macho-no-exports.dylib | FileCheck %s + +; Test that we don't crash with an empty export list. +CHECK: macho-no-exports.dylib: file format Mach-O 64-bit x86-64 diff --git a/test/Object/objdump-macho-quirks.test b/test/Object/objdump-macho-quirks.test new file mode 100644 index 0000000..eeee153 --- /dev/null +++ b/test/Object/objdump-macho-quirks.test @@ -0,0 +1,9 @@ +RUN: llvm-objdump -private-headers %p/Inputs/macho-zero-ncmds \ +RUN: | FileCheck %s -check-prefix A + +// Check that we don't get an infinite loop if ncmds = 0 +A: file format Mach-O 64-bit unknown +A: Mach header +A: magic cputype cpusubtype caps filetype ncmds sizeofcmds flags +A: MH_MAGIC_64 0x00 OBJECT 0 0 0x00000000 + diff --git a/test/Object/objdump-private-headers.test b/test/Object/objdump-private-headers.test index c562044..d311bec 100644 --- a/test/Object/objdump-private-headers.test +++ b/test/Object/objdump-private-headers.test @@ -2,6 +2,8 @@ RUN: llvm-objdump -p %p/Inputs/program-headers.elf-i386 \ RUN: | FileCheck %s -check-prefix ELF-i386 RUN: llvm-objdump -p %p/Inputs/program-headers.elf-x86-64 \ RUN: | FileCheck %s -check-prefix ELF-x86-64 +RUN: llvm-objdump -p %p/Inputs/macho-rpath-x86_64 \ +RUN: | FileCheck %s -check-prefix MACHO-x86_64 ELF-i386: Program Header: ELF-i386: LOAD off 0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12 @@ -16,3 +18,8 @@ ELF-x86-64: EH_FRAME off 0x00000000000000f4 vaddr 0x00000000004000f4 paddr 0x ELF-x86-64: filesz 0x0000000000000014 memsz 0x0000000000000014 flags r-- ELF-x86-64: STACK off 0x0000000000000000 vaddr 0x0000000000000000 paddr 0x0000000000000000 align 2**3 ELF-x86-64: filesz 0x0000000000000000 memsz 0x0000000000000000 flags rw- + +MACHO-x86_64: Load command 12 +MACHO-x86_64: cmd LC_RPATH +MACHO-x86_64: cmdsize 32 +MACHO-x86_64: path @executable_path/. (offset 12) diff --git a/test/Object/objdump-reloc-shared.test b/test/Object/objdump-reloc-shared.test new file mode 100644 index 0000000..d899ffb --- /dev/null +++ b/test/Object/objdump-reloc-shared.test @@ -0,0 +1,5 @@ +RUN: llvm-objdump -r %p/Inputs/elf-reloc-no-sym.x86_64 \ +RUN: | FileCheck %s + +; CHECK: elf-reloc-no-sym.x86_64: file format ELF64-x86-64 +; CHECK-NOT: {{.}} diff --git a/test/Object/objdump-relocations.test b/test/Object/objdump-relocations.test index 28cac10..1e41f78 100644 --- a/test/Object/objdump-relocations.test +++ b/test/Object/objdump-relocations.test @@ -27,9 +27,9 @@ COFF-x86-64: IMAGE_REL_AMD64_REL32 puts COFF-x86-64: IMAGE_REL_AMD64_REL32 SomeOtherFunction ELF-i386: .text -ELF-i386: R_386_32 -ELF-i386: R_386_PC32 -ELF-i386: R_386_PC32 +ELF-i386: R_386_32 .rodata.str1.1 +ELF-i386: R_386_PC32 puts +ELF-i386: R_386_PC32 SomeOtherFunction ELF-x86-64: .text ELF-x86-64: R_X86_64_32S .rodata.str1.1 diff --git a/test/Object/yaml2obj-elf-file-headers-with-e_flags.yaml b/test/Object/yaml2obj-elf-file-headers-with-e_flags.yaml index 7d09807..dddc7d9 100644 --- a/test/Object/yaml2obj-elf-file-headers-with-e_flags.yaml +++ b/test/Object/yaml2obj-elf-file-headers-with-e_flags.yaml @@ -5,13 +5,15 @@ FileHeader: Data: ELFDATA2LSB Type: ET_REL Machine: EM_MIPS - Flags: [ EF_MIPS_NOREORDER, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2 ] + Flags: [ EF_MIPS_NOREORDER, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32R2, + EF_MIPS_NAN2008 ] # CHECK: Format: ELF32-mips # CHECK: Arch: mipsel # CHECK: Machine: EM_MIPS -# CHECK: Flags [ (0x70001001) +# CHECK: Flags [ (0x70001401) # CHECK-NEXT: EF_MIPS_ABI_O32 (0x1000) # CHECK-NEXT: EF_MIPS_ARCH_32R2 (0x70000000) +# CHECK-NEXT: EF_MIPS_NAN2008 (0x400) # CHECK-NEXT: EF_MIPS_NOREORDER (0x1) # CHECK-NEXT: ] diff --git a/test/Object/yaml2obj-elf-symbol-visibility.yaml b/test/Object/yaml2obj-elf-symbol-visibility.yaml index 113354a..6c4037c 100644 --- a/test/Object/yaml2obj-elf-symbol-visibility.yaml +++ b/test/Object/yaml2obj-elf-symbol-visibility.yaml @@ -44,7 +44,7 @@ # OBJ-NEXT: Size: 4 # OBJ-NEXT: Binding: Global (0x1) # OBJ-NEXT: Type: Object (0x1) -# OBJ-NEXT: Other: 3 +# OBJ-NEXT: Other: 163 # OBJ-NEXT: Section: .data (0x1) # OBJ-NEXT: } @@ -77,6 +77,7 @@ # YAML-NEXT: Value: 0x0000000000000010 # YAML-NEXT: Size: 0x0000000000000004 # YAML-NEXT: Visibility: STV_PROTECTED +# YAML-NEXT: Other: [ STO_MIPS_PIC, STO_MIPS_MICROMIPS ] --- FileHeader: @@ -121,6 +122,7 @@ Symbols: - Name: protected Type: STT_OBJECT Visibility: STV_PROTECTED + Other: [ STO_MIPS_MICROMIPS, STO_MIPS_PIC ] Section: .data Value: 0x10 Size: 0x04 diff --git a/test/Other/Inputs/block-info-only.bc b/test/Other/Inputs/block-info-only.bc new file mode 100755 index 0000000..e30ca5f Binary files /dev/null and b/test/Other/Inputs/block-info-only.bc differ diff --git a/test/Other/Inputs/has-block-info.bc b/test/Other/Inputs/has-block-info.bc new file mode 100644 index 0000000..1815db6 Binary files /dev/null and b/test/Other/Inputs/has-block-info.bc differ diff --git a/test/Other/Inputs/no-block-info.bc b/test/Other/Inputs/no-block-info.bc new file mode 100755 index 0000000..e79c276 Binary files /dev/null and b/test/Other/Inputs/no-block-info.bc differ diff --git a/test/Other/bcanalyzer-block-info.txt b/test/Other/bcanalyzer-block-info.txt new file mode 100644 index 0000000..e660312 --- /dev/null +++ b/test/Other/bcanalyzer-block-info.txt @@ -0,0 +1,32 @@ +RUN: llvm-bcanalyzer -dump %S/Inputs/has-block-info.bc | FileCheck -check-prefix=CHECK -check-prefix=DATA %s +RUN: llvm-bcanalyzer -dump %S/Inputs/no-block-info.bc | FileCheck -check-prefix=UNKNOWN -check-prefix=DATA %s +RUN: llvm-bcanalyzer -dump %S/Inputs/no-block-info.bc -block-info %S/Inputs/block-info-only.bc | FileCheck -check-prefix=CHECK -check-prefix=DATA %s + + CHECK: + CHECK: + CHECK: + CHECK: + CHECK: +UNKNOWN: + CHECK: + CHECK: + CHECK: + CHECK: + CHECK: +UNKNOWN: diff --git a/test/Other/link-opts.ll b/test/Other/link-opts.ll deleted file mode 100644 index 8e58ac8..0000000 --- a/test/Other/link-opts.ll +++ /dev/null @@ -1,13 +0,0 @@ -;RUN: opt -S -std-link-opts < %s | FileCheck %s -; Simple test to check that -std-link-opts keeps only the main function. - -; CHECK-NOT: define -; CHECK: define void @main -; CHECK-NOT: define -define void @main() { - ret void -} - -define void @foo() { - ret void -} diff --git a/test/Other/lit-unicode.txt b/test/Other/lit-unicode.txt new file mode 100644 index 0000000..ca92c99 --- /dev/null +++ b/test/Other/lit-unicode.txt @@ -0,0 +1,3 @@ +REQUIRES: shell +RUN: echo "よã†ã“ã" | FileCheck %s +CHECK: {{^}}よã†ã“ã{{$}} diff --git a/test/Other/new-pass-manager.ll b/test/Other/new-pass-manager.ll index cec01b5..6454ffc 100644 --- a/test/Other/new-pass-manager.ll +++ b/test/Other/new-pass-manager.ll @@ -5,27 +5,85 @@ ; files, but for now this is just going to step the new process through its ; paces. +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes=no-op-module %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-PASS +; CHECK-MODULE-PASS: Starting pass manager +; CHECK-MODULE-PASS-NEXT: Running pass: NoOpModulePass +; CHECK-MODULE-PASS-NEXT: Finished pass manager + +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes=no-op-cgscc %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-CGSCC-PASS +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='cgscc(no-op-cgscc)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-CGSCC-PASS +; CHECK-CGSCC-PASS: Starting pass manager +; CHECK-CGSCC-PASS-NEXT: Running pass: ModuleToPostOrderCGSCCPassAdaptor +; CHECK-CGSCC-PASS-NEXT: Running analysis: CGSCCAnalysisManagerModuleProxy +; CHECK-CGSCC-PASS-NEXT: Running analysis: Lazy CallGraph Analysis +; CHECK-CGSCC-PASS-NEXT: Starting pass manager +; CHECK-CGSCC-PASS-NEXT: Running pass: NoOpCGSCCPass +; CHECK-CGSCC-PASS-NEXT: Finished pass manager +; CHECK-CGSCC-PASS-NEXT: Finished pass manager + +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes=no-op-function %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='function(no-op-function)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PASS +; CHECK-FUNCTION-PASS: Starting pass manager +; CHECK-FUNCTION-PASS-NEXT: Running pass: ModuleToFunctionPassAdaptor +; CHECK-FUNCTION-PASS-NEXT: Running analysis: FunctionAnalysisManagerModuleProxy +; CHECK-FUNCTION-PASS-NEXT: Starting pass manager +; CHECK-FUNCTION-PASS-NEXT: Running pass: NoOpFunctionPass +; CHECK-FUNCTION-PASS-NEXT: Finished pass manager +; CHECK-FUNCTION-PASS-NEXT: Finished pass manager + ; RUN: opt -disable-output -debug-pass-manager -passes=print %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-PRINT -; CHECK-MODULE-PRINT: Starting module pass manager -; CHECK-MODULE-PRINT: Running module pass: VerifierPass -; CHECK-MODULE-PRINT: Running module pass: PrintModulePass +; CHECK-MODULE-PRINT: Starting pass manager +; CHECK-MODULE-PRINT: Running pass: VerifierPass +; CHECK-MODULE-PRINT: Running pass: PrintModulePass ; CHECK-MODULE-PRINT: ModuleID ; CHECK-MODULE-PRINT: define void @foo() -; CHECK-MODULE-PRINT: Running module pass: VerifierPass -; CHECK-MODULE-PRINT: Finished module pass manager +; CHECK-MODULE-PRINT: Running pass: VerifierPass +; CHECK-MODULE-PRINT: Finished pass manager + +; RUN: opt -disable-output -debug-pass-manager -disable-verify -passes='print,verify' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-MODULE-VERIFY +; CHECK-MODULE-VERIFY: Starting pass manager +; CHECK-MODULE-VERIFY: Running pass: PrintModulePass +; CHECK-MODULE-VERIFY: ModuleID +; CHECK-MODULE-VERIFY: define void @foo() +; CHECK-MODULE-VERIFY: Running pass: VerifierPass +; CHECK-MODULE-VERIFY: Finished pass manager ; RUN: opt -disable-output -debug-pass-manager -passes='function(print)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-PRINT -; CHECK-FUNCTION-PRINT: Starting module pass manager -; CHECK-FUNCTION-PRINT: Running module pass: VerifierPass -; CHECK-FUNCTION-PRINT: Starting function pass manager -; CHECK-FUNCTION-PRINT: Running function pass: PrintFunctionPass +; CHECK-FUNCTION-PRINT: Starting pass manager +; CHECK-FUNCTION-PRINT: Running pass: VerifierPass +; CHECK-FUNCTION-PRINT: Running pass: ModuleToFunctionPassAdaptor +; CHECK-FUNCTION-PRINT: Running analysis: FunctionAnalysisManagerModuleProxy +; CHECK-FUNCTION-PRINT: Starting pass manager +; CHECK-FUNCTION-PRINT: Running pass: PrintFunctionPass ; CHECK-FUNCTION-PRINT-NOT: ModuleID ; CHECK-FUNCTION-PRINT: define void @foo() -; CHECK-FUNCTION-PRINT: Finished function pass manager -; CHECK-FUNCTION-PRINT: Running module pass: VerifierPass -; CHECK-FUNCTION-PRINT: Finished module pass manager +; CHECK-FUNCTION-PRINT: Finished pass manager +; CHECK-FUNCTION-PRINT: Running pass: VerifierPass +; CHECK-FUNCTION-PRINT: Finished pass manager + +; RUN: opt -disable-output -debug-pass-manager -disable-verify -passes='function(print,verify)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-FUNCTION-VERIFY +; CHECK-FUNCTION-VERIFY: Starting pass manager +; CHECK-FUNCTION-VERIFY: Starting pass manager +; CHECK-FUNCTION-VERIFY: Running pass: PrintFunctionPass +; CHECK-FUNCTION-VERIFY-NOT: ModuleID +; CHECK-FUNCTION-VERIFY: define void @foo() +; CHECK-FUNCTION-VERIFY: Running pass: VerifierPass +; CHECK-FUNCTION-VERIFY: Finished pass manager +; CHECK-FUNCTION-VERIFY: Finished pass manager ; RUN: opt -S -o - -passes='no-op-module,no-op-module' %s \ ; RUN: | FileCheck %s --check-prefix=CHECK-NOOP @@ -40,29 +98,173 @@ ; RUN: opt -disable-output -debug-pass-manager -verify-each -passes='no-op-module,function(no-op-function)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-VERIFY-EACH -; CHECK-VERIFY-EACH: Starting module pass manager -; CHECK-VERIFY-EACH: Running module pass: VerifierPass -; CHECK-VERIFY-EACH: Running module pass: NoOpModulePass -; CHECK-VERIFY-EACH: Running module pass: VerifierPass -; CHECK-VERIFY-EACH: Starting function pass manager -; CHECK-VERIFY-EACH: Running function pass: NoOpFunctionPass -; CHECK-VERIFY-EACH: Running function pass: VerifierPass -; CHECK-VERIFY-EACH: Finished function pass manager -; CHECK-VERIFY-EACH: Running module pass: VerifierPass -; CHECK-VERIFY-EACH: Finished module pass manager +; CHECK-VERIFY-EACH: Starting pass manager +; CHECK-VERIFY-EACH: Running pass: VerifierPass +; CHECK-VERIFY-EACH: Running pass: NoOpModulePass +; CHECK-VERIFY-EACH: Running pass: VerifierPass +; CHECK-VERIFY-EACH: Starting pass manager +; CHECK-VERIFY-EACH: Running pass: NoOpFunctionPass +; CHECK-VERIFY-EACH: Running pass: VerifierPass +; CHECK-VERIFY-EACH: Finished pass manager +; CHECK-VERIFY-EACH: Running pass: VerifierPass +; CHECK-VERIFY-EACH: Finished pass manager ; RUN: opt -disable-output -debug-pass-manager -disable-verify -passes='no-op-module,function(no-op-function)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-NO-VERIFY -; CHECK-NO-VERIFY: Starting module pass manager +; CHECK-NO-VERIFY: Starting pass manager ; CHECK-NO-VERIFY-NOT: VerifierPass -; CHECK-NO-VERIFY: Running module pass: NoOpModulePass +; CHECK-NO-VERIFY: Running pass: NoOpModulePass ; CHECK-NO-VERIFY-NOT: VerifierPass -; CHECK-NO-VERIFY: Starting function pass manager -; CHECK-NO-VERIFY: Running function pass: NoOpFunctionPass +; CHECK-NO-VERIFY: Starting pass manager +; CHECK-NO-VERIFY: Running pass: NoOpFunctionPass ; CHECK-NO-VERIFY-NOT: VerifierPass -; CHECK-NO-VERIFY: Finished function pass manager +; CHECK-NO-VERIFY: Finished pass manager ; CHECK-NO-VERIFY-NOT: VerifierPass -; CHECK-NO-VERIFY: Finished module pass manager +; CHECK-NO-VERIFY: Finished pass manager + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='require,cgscc(require,function(require))' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-ANALYSES +; CHECK-ANALYSES: Starting pass manager +; CHECK-ANALYSES: Running pass: RequireAnalysisPass +; CHECK-ANALYSES: Running analysis: NoOpModuleAnalysis +; CHECK-ANALYSES: Starting pass manager +; CHECK-ANALYSES: Running pass: RequireAnalysisPass +; CHECK-ANALYSES: Running analysis: NoOpCGSCCAnalysis +; CHECK-ANALYSES: Starting pass manager +; CHECK-ANALYSES: Running pass: RequireAnalysisPass +; CHECK-ANALYSES: Running analysis: NoOpFunctionAnalysis + +; Make sure no-op passes that preserve all analyses don't even try to do any +; analysis invalidation. +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='require,cgscc(require,function(require))' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-NO-OP-INVALIDATION +; CHECK-NO-OP-INVALIDATION: Starting pass manager +; CHECK-NO-OP-INVALIDATION-NOT: Invalidating all non-preserved analyses + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='require,require,require' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Starting pass manager +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Running pass: RequireAnalysisPass +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS: Running analysis: NoOpModuleAnalysis +; CHECK-DO-CACHE-MODULE-ANALYSIS-RESULTS-NOT: Running analysis: NoOpModuleAnalysis + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='require,invalidate,require' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Starting pass manager +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running pass: RequireAnalysisPass +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running analysis: NoOpModuleAnalysis +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Invalidating analysis: NoOpModuleAnalysis +; CHECK-DO-INVALIDATE-MODULE-ANALYSIS-RESULTS: Running analysis: NoOpModuleAnalysis + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='cgscc(require,require,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Starting pass manager +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Running pass: RequireAnalysisPass +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS: Running analysis: NoOpCGSCCAnalysis +; CHECK-DO-CACHE-CGSCC-ANALYSIS-RESULTS-NOT: Running analysis: NoOpCGSCCAnalysis + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='cgscc(require,invalidate,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Starting pass manager +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running pass: RequireAnalysisPass +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running analysis: NoOpCGSCCAnalysis +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Invalidating analysis: NoOpCGSCCAnalysis +; CHECK-DO-INVALIDATE-CGSCC-ANALYSIS-RESULTS: Running analysis: NoOpCGSCCAnalysis + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='function(require,require,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Starting pass manager +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Running pass: RequireAnalysisPass +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS: Running analysis: NoOpFunctionAnalysis +; CHECK-DO-CACHE-FUNCTION-ANALYSIS-RESULTS-NOT: Running analysis: NoOpFunctionAnalysis + +; RUN: opt -disable-output -debug-pass-manager \ +; RUN: -passes='function(require,invalidate,require)' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Starting pass manager +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running pass: RequireAnalysisPass +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running analysis: NoOpFunctionAnalysis +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Invalidating analysis: NoOpFunctionAnalysis +; CHECK-DO-INVALIDATE-FUNCTION-ANALYSIS-RESULTS: Running analysis: NoOpFunctionAnalysis + +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='require,module(require,function(require,invalidate,require),require),require' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-INVALIDATE-ALL +; CHECK-INVALIDATE-ALL: Starting pass manager +; CHECK-INVALIDATE-ALL: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL: Starting pass manager +; CHECK-INVALIDATE-ALL: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-NOT: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL: Starting pass manager +; CHECK-INVALIDATE-ALL: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL: Running analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL: Running pass: InvalidateAllAnalysesPass +; CHECK-INVALIDATE-ALL: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL: Invalidating analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL: Running analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL: Finished pass manager +; CHECK-INVALIDATE-ALL: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-NOT: Running analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL: Invalidating analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL: Finished pass manager +; CHECK-INVALIDATE-ALL: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-NOT: Invalidating analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-NOT: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL: Finished pass manager + +; RUN: opt -disable-output -disable-verify -debug-pass-manager \ +; RUN: -passes='require,module(require,cgscc(require,function(require,invalidate,require),require),require),require' %s 2>&1 \ +; RUN: | FileCheck %s --check-prefix=CHECK-INVALIDATE-ALL-CG +; CHECK-INVALIDATE-ALL-CG: Starting pass manager +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL-CG: Starting pass manager +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG-NOT: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL-CG: Starting pass manager +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG: Running analysis: NoOpCGSCCAnalysis +; CHECK-INVALIDATE-ALL-CG: Starting pass manager +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG: Running analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL-CG: Running pass: InvalidateAllAnalysesPass +; CHECK-INVALIDATE-ALL-CG: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-CG: Invalidating analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG: Running analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL-CG: Finished pass manager +; CHECK-INVALIDATE-ALL-CG: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-CG-NOT: Running analysis: NoOpFunctionAnalysis +; CHECK-INVALIDATE-ALL-CG: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-CG: Invalidating analysis: NoOpCGSCCAnalysis +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG: Running analysis: NoOpCGSCCAnalysis +; CHECK-INVALIDATE-ALL-CG: Finished pass manager +; CHECK-INVALIDATE-ALL-CG: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-CG-NOT: Invalidating analysis: NoOpCGSCCAnalysis +; CHECK-INVALIDATE-ALL-CG: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-CG: Invalidating analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL-CG: Finished pass manager +; CHECK-INVALIDATE-ALL-CG: Invalidating all non-preserved analyses +; CHECK-INVALIDATE-ALL-CG-NOT: Invalidating analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL-CG: Running pass: RequireAnalysisPass +; CHECK-INVALIDATE-ALL-CG-NOT: Running analysis: NoOpModuleAnalysis +; CHECK-INVALIDATE-ALL-CG: Finished pass manager define void @foo() { ret void diff --git a/test/Other/pass-pipeline-parsing.ll b/test/Other/pass-pipeline-parsing.ll index 4ec4162..da0e760 100644 --- a/test/Other/pass-pipeline-parsing.ll +++ b/test/Other/pass-pipeline-parsing.ll @@ -1,59 +1,55 @@ ; RUN: opt -disable-output -debug-pass-manager \ ; RUN: -passes=no-op-module,no-op-module %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-TWO-NOOP-MP -; CHECK-TWO-NOOP-MP: Starting module pass manager -; CHECK-TWO-NOOP-MP: Running module pass: NoOpModulePass -; CHECK-TWO-NOOP-MP: Running module pass: NoOpModulePass -; CHECK-TWO-NOOP-MP: Finished module pass manager +; CHECK-TWO-NOOP-MP: Starting pass manager +; CHECK-TWO-NOOP-MP: Running pass: NoOpModulePass +; CHECK-TWO-NOOP-MP: Running pass: NoOpModulePass +; CHECK-TWO-NOOP-MP: Finished pass manager ; RUN: opt -disable-output -debug-pass-manager \ ; RUN: -passes='module(no-op-module,no-op-module)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-NESTED-TWO-NOOP-MP -; CHECK-NESTED-TWO-NOOP-MP: Starting module pass manager -; CHECK-NESTED-TWO-NOOP-MP: Running module pass: ModulePassManager -; CHECK-NESTED-TWO-NOOP-MP: Starting module pass manager -; CHECK-NESTED-TWO-NOOP-MP: Running module pass: NoOpModulePass -; CHECK-NESTED-TWO-NOOP-MP: Running module pass: NoOpModulePass -; CHECK-NESTED-TWO-NOOP-MP: Finished module pass manager -; CHECK-NESTED-TWO-NOOP-MP: Finished module pass manager +; CHECK-NESTED-TWO-NOOP-MP: Starting pass manager +; CHECK-NESTED-TWO-NOOP-MP: Starting pass manager +; CHECK-NESTED-TWO-NOOP-MP: Running pass: NoOpModulePass +; CHECK-NESTED-TWO-NOOP-MP: Running pass: NoOpModulePass +; CHECK-NESTED-TWO-NOOP-MP: Finished pass manager +; CHECK-NESTED-TWO-NOOP-MP: Finished pass manager ; RUN: opt -disable-output -debug-pass-manager \ ; RUN: -passes=no-op-function,no-op-function %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-TWO-NOOP-FP -; CHECK-TWO-NOOP-FP: Starting module pass manager -; CHECK-TWO-NOOP-FP: Running module pass: ModuleToFunctionPassAdaptor -; CHECK-TWO-NOOP-FP: Starting function pass manager -; CHECK-TWO-NOOP-FP: Running function pass: NoOpFunctionPass -; CHECK-TWO-NOOP-FP: Running function pass: NoOpFunctionPass -; CHECK-TWO-NOOP-FP: Finished function pass manager -; CHECK-TWO-NOOP-FP: Finished module pass manager +; CHECK-TWO-NOOP-FP: Starting pass manager +; CHECK-TWO-NOOP-FP: Running pass: ModuleToFunctionPassAdaptor +; CHECK-TWO-NOOP-FP: Starting pass manager +; CHECK-TWO-NOOP-FP: Running pass: NoOpFunctionPass +; CHECK-TWO-NOOP-FP: Running pass: NoOpFunctionPass +; CHECK-TWO-NOOP-FP: Finished pass manager +; CHECK-TWO-NOOP-FP: Finished pass manager ; RUN: opt -disable-output -debug-pass-manager \ ; RUN: -passes='function(no-op-function,no-op-function)' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-NESTED-TWO-NOOP-FP -; CHECK-NESTED-TWO-NOOP-FP: Starting module pass manager -; CHECK-NESTED-TWO-NOOP-FP: Running module pass: ModuleToFunctionPassAdaptor -; CHECK-NESTED-TWO-NOOP-FP: Starting function pass manager -; CHECK-NESTED-TWO-NOOP-FP: Running function pass: FunctionPassManager -; CHECK-NESTED-TWO-NOOP-FP: Starting function pass manager -; CHECK-NESTED-TWO-NOOP-FP: Running function pass: NoOpFunctionPass -; CHECK-NESTED-TWO-NOOP-FP: Running function pass: NoOpFunctionPass -; CHECK-NESTED-TWO-NOOP-FP: Finished function pass manager -; CHECK-NESTED-TWO-NOOP-FP: Finished function pass manager -; CHECK-NESTED-TWO-NOOP-FP: Finished module pass manager +; CHECK-NESTED-TWO-NOOP-FP: Starting pass manager +; CHECK-NESTED-TWO-NOOP-FP: Running pass: ModuleToFunctionPassAdaptor +; CHECK-NESTED-TWO-NOOP-FP: Starting pass manager +; CHECK-NESTED-TWO-NOOP-FP: Running pass: NoOpFunctionPass +; CHECK-NESTED-TWO-NOOP-FP: Running pass: NoOpFunctionPass +; CHECK-NESTED-TWO-NOOP-FP: Finished pass manager +; CHECK-NESTED-TWO-NOOP-FP: Finished pass manager ; RUN: opt -disable-output -debug-pass-manager \ ; RUN: -passes='no-op-module,function(no-op-function,no-op-function),no-op-module' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-MIXED-FP-AND-MP -; CHECK-MIXED-FP-AND-MP: Starting module pass manager -; CHECK-MIXED-FP-AND-MP: Running module pass: NoOpModulePass -; CHECK-MIXED-FP-AND-MP: Running module pass: ModuleToFunctionPassAdaptor -; CHECK-MIXED-FP-AND-MP: Starting function pass manager -; CHECK-MIXED-FP-AND-MP: Running function pass: NoOpFunctionPass -; CHECK-MIXED-FP-AND-MP: Running function pass: NoOpFunctionPass -; CHECK-MIXED-FP-AND-MP: Finished function pass manager -; CHECK-MIXED-FP-AND-MP: Running module pass: NoOpModulePass -; CHECK-MIXED-FP-AND-MP: Finished module pass manager +; CHECK-MIXED-FP-AND-MP: Starting pass manager +; CHECK-MIXED-FP-AND-MP: Running pass: NoOpModulePass +; CHECK-MIXED-FP-AND-MP: Running pass: ModuleToFunctionPassAdaptor +; CHECK-MIXED-FP-AND-MP: Starting pass manager +; CHECK-MIXED-FP-AND-MP: Running pass: NoOpFunctionPass +; CHECK-MIXED-FP-AND-MP: Running pass: NoOpFunctionPass +; CHECK-MIXED-FP-AND-MP: Finished pass manager +; CHECK-MIXED-FP-AND-MP: Running pass: NoOpModulePass +; CHECK-MIXED-FP-AND-MP: Finished pass manager ; RUN: not opt -disable-output -debug-pass-manager \ ; RUN: -passes='no-op-module)' %s 2>&1 \ @@ -105,41 +101,41 @@ ; RUN: | FileCheck %s --check-prefix=CHECK-UNBALANCED10 ; CHECK-UNBALANCED10: unable to parse pass pipeline description -; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; RUN: opt -disable-output -debug-pass-manager \ ; RUN: -passes=no-op-cgscc,no-op-cgscc %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-TWO-NOOP-CG -; CHECK-TWO-NOOP-CG: Starting module pass manager -; CHECK-TWO-NOOP-CG: Running module pass: ModuleToPostOrderCGSCCPassAdaptor -; CHECK-TWO-NOOP-CG: Starting CGSCC pass manager -; CHECK-TWO-NOOP-CG: Running CGSCC pass: NoOpCGSCCPass -; CHECK-TWO-NOOP-CG: Running CGSCC pass: NoOpCGSCCPass -; CHECK-TWO-NOOP-CG: Finished CGSCC pass manager -; CHECK-TWO-NOOP-CG: Finished module pass manager - -; RUN: opt -disable-output -debug-pass-manager -debug-cgscc-pass-manager \ +; CHECK-TWO-NOOP-CG: Starting pass manager +; CHECK-TWO-NOOP-CG: Running pass: ModuleToPostOrderCGSCCPassAdaptor +; CHECK-TWO-NOOP-CG: Starting pass manager +; CHECK-TWO-NOOP-CG: Running pass: NoOpCGSCCPass +; CHECK-TWO-NOOP-CG: Running pass: NoOpCGSCCPass +; CHECK-TWO-NOOP-CG: Finished pass manager +; CHECK-TWO-NOOP-CG: Finished pass manager + +; RUN: opt -disable-output -debug-pass-manager \ ; RUN: -passes='module(function(no-op-function),cgscc(no-op-cgscc,function(no-op-function),no-op-cgscc),function(no-op-function))' %s 2>&1 \ ; RUN: | FileCheck %s --check-prefix=CHECK-NESTED-MP-CG-FP -; CHECK-NESTED-MP-CG-FP: Starting module pass manager -; CHECK-NESTED-MP-CG-FP: Starting module pass manager -; CHECK-NESTED-MP-CG-FP: Running module pass: ModuleToFunctionPassAdaptor -; CHECK-NESTED-MP-CG-FP: Starting function pass manager -; CHECK-NESTED-MP-CG-FP: Running function pass: NoOpFunctionPass -; CHECK-NESTED-MP-CG-FP: Finished function pass manager -; CHECK-NESTED-MP-CG-FP: Running module pass: ModuleToPostOrderCGSCCPassAdaptor -; CHECK-NESTED-MP-CG-FP: Starting CGSCC pass manager -; CHECK-NESTED-MP-CG-FP: Running CGSCC pass: NoOpCGSCCPass -; CHECK-NESTED-MP-CG-FP: Running CGSCC pass: CGSCCToFunctionPassAdaptor -; CHECK-NESTED-MP-CG-FP: Starting function pass manager -; CHECK-NESTED-MP-CG-FP: Running function pass: NoOpFunctionPass -; CHECK-NESTED-MP-CG-FP: Finished function pass manager -; CHECK-NESTED-MP-CG-FP: Running CGSCC pass: NoOpCGSCCPass -; CHECK-NESTED-MP-CG-FP: Finished CGSCC pass manager -; CHECK-NESTED-MP-CG-FP: Running module pass: ModuleToFunctionPassAdaptor -; CHECK-NESTED-MP-CG-FP: Starting function pass manager -; CHECK-NESTED-MP-CG-FP: Running function pass: NoOpFunctionPass -; CHECK-NESTED-MP-CG-FP: Finished function pass manager -; CHECK-NESTED-MP-CG-FP: Finished module pass manager -; CHECK-NESTED-MP-CG-FP: Finished module pass manager +; CHECK-NESTED-MP-CG-FP: Starting pass manager +; CHECK-NESTED-MP-CG-FP: Starting pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: ModuleToFunctionPassAdaptor +; CHECK-NESTED-MP-CG-FP: Starting pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: NoOpFunctionPass +; CHECK-NESTED-MP-CG-FP: Finished pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: ModuleToPostOrderCGSCCPassAdaptor +; CHECK-NESTED-MP-CG-FP: Starting pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: NoOpCGSCCPass +; CHECK-NESTED-MP-CG-FP: Running pass: CGSCCToFunctionPassAdaptor +; CHECK-NESTED-MP-CG-FP: Starting pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: NoOpFunctionPass +; CHECK-NESTED-MP-CG-FP: Finished pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: NoOpCGSCCPass +; CHECK-NESTED-MP-CG-FP: Finished pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: ModuleToFunctionPassAdaptor +; CHECK-NESTED-MP-CG-FP: Starting pass manager +; CHECK-NESTED-MP-CG-FP: Running pass: NoOpFunctionPass +; CHECK-NESTED-MP-CG-FP: Finished pass manager +; CHECK-NESTED-MP-CG-FP: Finished pass manager +; CHECK-NESTED-MP-CG-FP: Finished pass manager define void @f() { ret void diff --git a/test/SymbolRewriter/rewrite.ll b/test/SymbolRewriter/rewrite.ll new file mode 100644 index 0000000..716fff9 --- /dev/null +++ b/test/SymbolRewriter/rewrite.ll @@ -0,0 +1,59 @@ +; RUN: opt -mtriple i686-win32 -rewrite-symbols -rewrite-map-file %p/rewrite.map \ +; RUN: %s -o - | llvm-dis | FileCheck %s + +declare void @source_function() +@source_variable = external global i32 +declare void @source_function_pattern_function() +declare void @source_function_pattern_multiple_function_matches() +@source_variable_pattern_variable = external global i32 +@source_variable_pattern_multiple_variable_matches = external global i32 +declare void @"\01naked_source_function"() +declare void @"\01__imp_missing_global_leader_prefix"() + +declare i32 @first_callee() +declare i32 @second_callee() +define i32 @caller() { + %rhs = call i32 @first_callee() + %lhs = call i32 @second_callee() + %res = add i32 %rhs, %lhs + ret i32 %res +} + +%struct.S = type { i8 } +@_ZN1SC1Ev = alias void (%struct.S*)* @_ZN1SC2Ev +define void @_ZN1SC2Ev(%struct.S* %this) unnamed_addr align 2 { +entry: + %this.addr = alloca %struct.S*, align 4 + store %struct.S* %this, %struct.S** %this.addr, align 4 + ret void +} + +; CHECK: @target_variable = external global i32 +; CHECK-NOT: @source_variable = external global i32 +; CHECK: @target_pattern_variable = external global i32 +; CHECK-NOT: @source_pattern_variable = external global i32 +; CHECK: @target_pattern_multiple_variable_matches = external global i32 +; CHECK-NOT: @source_pattern_multiple_variable_matches = external global i32 +; CHECK: declare void @target_function() +; CHECK-NOT: declare void @source_function() +; CHECK: declare void @target_pattern_function() +; CHECK-NOT: declare void @source_function_pattern_function() +; CHECK: declare void @target_pattern_multiple_function_matches() +; CHECK-NOT: declare void @source_function_pattern_multiple_function_matches() +; CHECK: declare void @naked_target_function() +; CHECK-NOT: declare void @"\01naked_source_function"() +; CHECK-NOT: declare void @"\01__imp__imported_function"() +; CHECK: declare void @"\01__imp_missing_global_leader_prefix"() +; CHECK-NOT: declare void @"\01__imp_DO_NOT_REWRITE"() + +; CHECK: declare i32 @renamed_callee() +; CHECK-NOT: declare i32 @first_callee() +; CHECK: declare i32 @second_callee() +; CHECK: define i32 @caller() { +; CHECK: %rhs = call i32 @renamed_callee() +; CHECK-NOT: %rhs = call i32 @first_callee() +; CHECK: %lhs = call i32 @second_callee() +; CHECK: %res = add i32 %rhs, %lhs +; CHECK: ret i32 %res +; CHECK: } + diff --git a/test/SymbolRewriter/rewrite.map b/test/SymbolRewriter/rewrite.map new file mode 100644 index 0000000..ef6dfc8 --- /dev/null +++ b/test/SymbolRewriter/rewrite.map @@ -0,0 +1,46 @@ +function: { + source: source_function, + target: target_function, +} + +global variable: { + source: source_variable, + target: target_variable, +} + +function: { + source: source_function_(.*), + transform: target_\1, +} + +global variable: { + source: source_variable_(.*), + transform: target_\1, +} + +function: { + source: naked_source_function, + target: naked_target_function, + naked: true, +} + +function: { + source: imported_function, + target: exported_function, +} + +function: { + source: missing_global_leader_prefix, + target: DO_NOT_REWRITE, +} + +function: { + source: first_callee, + target: renamed_callee, +} + +global alias: { + source: _ZN1SC1Ev, + target: _ZN1SD1Ev, +} + diff --git a/test/TableGen/BitOffsetDecoder.td b/test/TableGen/BitOffsetDecoder.td new file mode 100644 index 0000000..ec0ceee --- /dev/null +++ b/test/TableGen/BitOffsetDecoder.td @@ -0,0 +1,74 @@ +// RUN: llvm-tblgen -gen-disassembler -I %p/../../include %s | FileCheck %s + +include "llvm/Target/Target.td" + +def archInstrInfo : InstrInfo { } + +def arch : Target { + let InstructionSet = archInstrInfo; +} + +def Myi32 : Operand { + let DecoderMethod = "DecodeMyi32"; +} + + +let OutOperandList = (outs), Size = 2 in { + +def foo : Instruction { + let InOperandList = (ins i32imm:$factor); + field bits<16> Inst; + bits<32> factor; + let Inst{7-0} = 0xAA; + let Inst{14-8} = factor{6-0}; // no offset + let AsmString = "foo $factor"; + field bits<16> SoftFail = 0; + } + +def bar : Instruction { + let InOperandList = (ins i32imm:$factor); + field bits<16> Inst; + bits<32> factor; + let Inst{7-0} = 0xBB; + let Inst{15-8} = factor{10-3}; // offset by 3 + let AsmString = "bar $factor"; + field bits<16> SoftFail = 0; + } + +def biz : Instruction { + let InOperandList = (ins i32imm:$factor); + field bits<16> Inst; + bits<32> factor; + let Inst{7-0} = 0xCC; + let Inst{11-8,15-12} = factor{10-3}; // offset by 3, multipart + let AsmString = "biz $factor"; + field bits<16> SoftFail = 0; + } + +def baz : Instruction { + let InOperandList = (ins Myi32:$factor); + field bits<16> Inst; + bits<32> factor; + let Inst{7-0} = 0xDD; + let Inst{15-8} = factor{11-4}; // offset by 4 + custom decode + let AsmString = "baz $factor"; + field bits<16> SoftFail = 0; + } + +def bum : Instruction { + let InOperandList = (ins i32imm:$factor); + field bits<16> Inst; + bits<32> factor; + let Inst{7-0} = 0xEE; + let Inst{15-8} = !srl(factor,5); + let AsmString = "bum $factor"; + field bits<16> SoftFail = 0; + } +} + + +// CHECK: tmp = fieldFromInstruction(insn, 8, 7); +// CHECK: tmp = fieldFromInstruction(insn, 8, 8) << 3; +// CHECK: tmp |= fieldFromInstruction(insn, 8, 4) << 7; +// CHECK: tmp |= fieldFromInstruction(insn, 12, 4) << 3; +// CHECK: tmp = fieldFromInstruction(insn, 8, 8) << 4; diff --git a/test/TableGen/BitsInit.td b/test/TableGen/BitsInit.td new file mode 100644 index 0000000..6aac3e4 --- /dev/null +++ b/test/TableGen/BitsInit.td @@ -0,0 +1,85 @@ + +// RUN: not llvm-tblgen %s 2>&1 > %t +// RUN: FileCheck %s < %t + +def a { + bits<2> opc = { 0, 1 }; + bits<2> opc2 = { 1, 0 }; + bits<1> opc3 = { 1 }; + bits<2> a = { opc, opc2 }; // error! + bits<2> b = { opc{0}, opc2{0} }; + bits<2> c = { opc{1}, opc2{1} }; + bits<2> c = { opc3{0}, opc3 }; +} + +// CHECK: def a { +// CHECK: bits<2> opc = { 0, 1 }; +// CHECK: bits<2> opc2 = { 1, 0 }; +// CHECK: bits<1> opc3 = { 1 }; +// CHECK: bits<2> a; +// CHECK: bits<2> b = { 1, 0 }; +// CHECK: bits<2> c = { 1, 1 }; +// CHECK: } + +def { + bits<2> B1 = 0b011; // bitfield is too small, reject + bits<3> B2 = 0b011; // ok + + bits<2> C1 = 0b111; // bitfield is too small, reject + bits<3> C2 = 0b111; // ok + + bits<2> D1 = { 0, 0 }; // ok + bits<2> D2 = { 0b00 }; // ok + bits<3> D3 = { 0, 0 }; // type mismatch. RHS doesn't have enough bits + bits<3> D4 = { 0b00 }; // type mismatch. RHS doesn't have enough bits + bits<1> D5 = { 0 }; // ok + bits<1> D6 = { 1 }; // ok + bits<1> D7 = { 3 }; // type mismatch. LHS doesn't have enough bits + bits<2> D8 = { 0 }; // type mismatch. RHS doesn't have enough bits + + bits<8> E; + let E{7-0} = {0,0,1,?,?,?,?,?}; + let E{3-0} = 0b0010; + + bits<8> F1 = { 0, 1, 0b1001, 0, 0b0 }; // ok + bits<7> F2 = { 0, 1, 0b1001, 0, 0b0 }; // LHS doesn't have enough bits + bits<9> F3 = { 0, 1, 0b1001, 0, 0b0 }; // RHS doesn't have enough bits + + bits<8> G1 = { 0, { 1, 0b1001, 0 }, 0b0 }; // ok + bits<8> G2 = { 0, { 1, 0b1001 }, 0, 0b0 }; // ok + bits<8> G3 = { 0, 1, { 0b1001 }, 0, 0b0 }; // ok + + bits<16> H; + let H{15-0} = { { 0b11001100 }, 0b00110011 }; + bits<16> I = { G1, G2 }; + + // Make sure we can initialise ints with bits<> values. + int J = H; + int K = { 0, 1 }; +} + +// CHECK: def {{.*}} { +// CHECK: bits<2> B1; +// CHECK: bits<3> B2 = { 0, 1, 1 }; +// CHECK: bits<2> C1; +// CHECK: bits<3> C2 = { 1, 1, 1 }; +// CHECK: bits<2> D1 = { 0, 0 }; +// CHECK: bits<2> D2 = { 0, 0 }; +// CHECK: bits<3> D3; +// CHECK: bits<3> D4; +// CHECK: bits<1> D5 = { 0 }; +// CHECK: bits<1> D6 = { 1 }; +// CHECK: bits<1> D7 = { ? }; +// CHECK: bits<2> D8; +// CHECK: bits<8> E = { 0, 0, 1, ?, 0, 0, 1, 0 }; +// CHECK: bits<8> F1 = { 0, 1, 1, 0, 0, 1, 0, 0 }; +// CHECK: bits<7> F2; +// CHECK: bits<9> F3; +// CHECK: bits<8> G1 = { 0, 1, 1, 0, 0, 1, 0, 0 }; +// CHECK: bits<8> G2 = { 0, 1, 1, 0, 0, 1, 0, 0 }; +// CHECK: bits<8> G3 = { 0, 1, 1, 0, 0, 1, 0, 0 }; +// CHECK: bits<16> H = { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1 }; +// CHECK: bits<16> I = { 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0 }; +// CHECK: int J = 52275; +// CHECK: int K = 1; +// CHECK: } diff --git a/test/TableGen/ClassInstanceValue.td b/test/TableGen/ClassInstanceValue.td new file mode 100644 index 0000000..b6c4c93 --- /dev/null +++ b/test/TableGen/ClassInstanceValue.td @@ -0,0 +1,19 @@ +// RUN: llvm-tblgen %s | FileCheck %s +// XFAIL: vg_leak + +class Struct { + int I = !shl(i, 1); + int J = !shl(I, 1); +} + +class Class { + int Class_J = s.J; +} + +multiclass MultiClass { + def Def : Class>; +// CHECK: Class_J = 8 +// CHECK-NOT: Class_J = !shl(I, 1) +} + +defm Defm : MultiClass<2>; diff --git a/test/TableGen/ForeachList.td b/test/TableGen/ForeachList.td index 99b7e14..9bc76e0 100644 --- a/test/TableGen/ForeachList.td +++ b/test/TableGen/ForeachList.td @@ -1,5 +1,4 @@ // RUN: llvm-tblgen %s | FileCheck %s -// XFAIL: vg_leak class Register { string Name = name; diff --git a/test/TableGen/ForeachLoop.td b/test/TableGen/ForeachLoop.td index 25208fa..ce8d44c 100644 --- a/test/TableGen/ForeachLoop.td +++ b/test/TableGen/ForeachLoop.td @@ -1,5 +1,4 @@ // RUN: llvm-tblgen %s | FileCheck %s -// XFAIL: vg_leak class Register { string Name = name; diff --git a/test/TableGen/NestedForeach.td b/test/TableGen/NestedForeach.td index e8c16f7..5b63175 100644 --- a/test/TableGen/NestedForeach.td +++ b/test/TableGen/NestedForeach.td @@ -1,5 +1,4 @@ // RUN: llvm-tblgen %s | FileCheck %s -// XFAIL: vg_leak class Droid { string Series = series; diff --git a/test/TableGen/SiblingForeach.td b/test/TableGen/SiblingForeach.td index a11f6f8..e4c4704 100644 --- a/test/TableGen/SiblingForeach.td +++ b/test/TableGen/SiblingForeach.td @@ -1,5 +1,4 @@ // RUN: llvm-tblgen %s | FileCheck %s -// XFAIL: vg_leak class Set { int I = i; diff --git a/test/TableGen/if.td b/test/TableGen/if.td index 1d8d623..05a2d99 100644 --- a/test/TableGen/if.td +++ b/test/TableGen/if.td @@ -3,7 +3,7 @@ // Support for an `!if' operator as part of a `let' statement. // CHECK: class C -// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, !if({ C:y{3} }, 1, !if({ C:y{2} }, { C:x{0} }, !if({ C:y{1} }, { C:x{1} }, !if({ C:y{0} }, { C:x{2} }, ?)))){0}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){1}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){0}, !if({ C:x{2} }, 2, 6){2}, !if({ C:x{2} }, 2, 6){1}, !if({ C:x{2} }, 2, 6){0}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){1}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){0}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){3}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){2}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){1}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){0} }; +// CHECK-NEXT: bits<16> n = { ?, ?, ?, ?, !if({ C:y{3} }, 1, !if({ C:y{2} }, { C:x{0} }, !if({ C:y{1} }, { C:x{1} }, !if({ C:y{0} }, { C:x{2} }, ?)))){0}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){1}, !if({ C:x{2} }, { C:y{3}, C:y{2} }, !if({ C:x{1} }, { C:y{2}, C:y{1} }, !if({ C:x{0} }, { C:y{1}, C:y{0} }, ?))){0}, !if({ C:x{2} }, { 0, 1, 0 }, { 1, 1, 0 }){2}, !if({ C:x{2} }, { 0, 1, 0 }, { 1, 1, 0 }){1}, !if({ C:x{2} }, { 0, 1, 0 }, { 1, 1, 0 }){0}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){1}, !if({ C:x{1} }, { C:y{3}, C:y{2} }, { 0, 1 }){0}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){3}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){2}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){1}, !if({ C:x{0} }, { C:y{3}, C:y{2}, C:y{1}, C:y{0} }, { C:z, C:y{2}, C:y{1}, C:y{0} }){0} }; class C x, bits<4> y, bit z> { bits<16> n; diff --git a/test/TableGen/ifbit.td b/test/TableGen/ifbit.td index 88f575e..18797ca 100644 --- a/test/TableGen/ifbit.td +++ b/test/TableGen/ifbit.td @@ -5,6 +5,8 @@ class A { int a = !if(b, 5, 6); + bit c = !if(b, 0, 1); + bits<1> d = !if(b, 0, 1); } def X : A<0>; diff --git a/test/TableGen/intrinsic-varargs.td b/test/TableGen/intrinsic-varargs.td index 3e48f8d..935a625 100644 --- a/test/TableGen/intrinsic-varargs.td +++ b/test/TableGen/intrinsic-varargs.td @@ -26,5 +26,5 @@ class Intrinsic param_types = []> { def isVoid : ValueType<0, 56>; // Produces no value def llvm_vararg_ty : LLVMType; // this means vararg here -// CHECK: /* 0 */ 0, 27, 0, +// CHECK: /* 0 */ 0, 28, 0, def int_foo : Intrinsic<"llvm.foo", [llvm_vararg_ty]>; diff --git a/test/TableGen/list-element-bitref.td b/test/TableGen/list-element-bitref.td index 4622f28..0f59b53 100644 --- a/test/TableGen/list-element-bitref.td +++ b/test/TableGen/list-element-bitref.td @@ -1,7 +1,7 @@ // RUN: llvm-tblgen %s | FileCheck %s // XFAIL: vg_leak -class C> L> { +class C> L> { bits<2> V0 = L[0]{1-0}; bits<2> V1 = L[1]{3-2}; string V2 = !if(L[0]{0}, "Odd", "Even"); diff --git a/test/TableGen/math.td b/test/TableGen/math.td index 71c6057..d966346 100644 --- a/test/TableGen/math.td +++ b/test/TableGen/math.td @@ -15,6 +15,12 @@ class Int { int Value = value; } +// CHECK: def v0 +// CHECK: Value = 0 + +// CHECK: def v1 +// CHECK: Value = 1 + def v1024 : Int<1024>; // CHECK: def v1024 // CHECK: Value = 1024 @@ -27,3 +33,5 @@ def v2048 : Int; // CHECK: def v2048 // CHECK: Value = 2048 +def v0 : Int; +def v1 : Int; diff --git a/test/Transforms/AddDiscriminators/basic.ll b/test/Transforms/AddDiscriminators/basic.ll index b12cbee..7c8b3d3 100644 --- a/test/Transforms/AddDiscriminators/basic.ll +++ b/test/Transforms/AddDiscriminators/basic.ll @@ -40,20 +40,20 @@ attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointe !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [basic.c] [DW_LANG_C99] -!1 = metadata !{metadata !"basic.c", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [basic.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5 "} -!10 = metadata !{i32 3, i32 0, metadata !11, null} -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [basic.c] -!12 = metadata !{i32 4, i32 0, metadata !4, null} - -; CHECK: !12 = metadata !{i32 3, i32 0, metadata !13, null} -; CHECK: !13 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1, i32 0} ; [ DW_TAG_lexical_block ] [./basic.c] -; CHECK: !14 = metadata !{i32 4, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5 \000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [basic.c] [DW_LANG_C99] +!1 = !{!"basic.c", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [basic.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5 "} +!10 = !MDLocation(line: 3, scope: !11) +!11 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [basic.c] +!12 = !MDLocation(line: 4, scope: !4) + +; CHECK: !12 = !MDLocation(line: 3, scope: !13) +; CHECK: !13 = !{!"0xb\001", !1, !11} ; [ DW_TAG_lexical_block ] [./basic.c] +; CHECK: !14 = !MDLocation(line: 4, scope: !4) diff --git a/test/Transforms/AddDiscriminators/first-only.ll b/test/Transforms/AddDiscriminators/first-only.ll index f3b0357..153cfc8 100644 --- a/test/Transforms/AddDiscriminators/first-only.ll +++ b/test/Transforms/AddDiscriminators/first-only.ll @@ -50,33 +50,33 @@ attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointe !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [first-only.c] [DW_LANG_C99] -!1 = metadata !{metadata !"first-only.c", metadata !"."} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [first-only.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} -!10 = metadata !{i32 3, i32 0, metadata !11, null} - -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [first-only.c] -; CHECK: !11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0} - -!12 = metadata !{i32 3, i32 0, metadata !13, null} - -!13 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1} ; [ DW_TAG_lexical_block ] [first-only.c] -; CHECK: !13 = metadata !{i32 786443, metadata !1, metadata !14, i32 3, i32 0, i32 1, i32 0} ; [ DW_TAG_lexical_block ] [./first-only.c] - -!14 = metadata !{i32 4, i32 0, metadata !13, null} -; CHECK: !14 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1} - -!15 = metadata !{i32 5, i32 0, metadata !13, null} -; CHECK: !15 = metadata !{i32 4, i32 0, metadata !14, null} - -!16 = metadata !{i32 6, i32 0, metadata !4, null} -; CHECK: !16 = metadata !{i32 5, i32 0, metadata !14, null} -; CHECK: !17 = metadata !{i32 6, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5 (trunk 199750) (llvm/trunk 199751)\000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [first-only.c] [DW_LANG_C99] +!1 = !{!"first-only.c", !"."} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [first-only.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} +!10 = !MDLocation(line: 3, scope: !11) + +!11 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [first-only.c] +; CHECK: !11 = !{!"0xb\003\000\000", !1, !4} + +!12 = !MDLocation(line: 3, scope: !13) + +!13 = !{!"0xb\003\000\001", !1, !11} ; [ DW_TAG_lexical_block ] [first-only.c] +; CHECK: !13 = !{!"0xb\001", !1, !14} ; [ DW_TAG_lexical_block ] [./first-only.c] + +!14 = !MDLocation(line: 4, scope: !13) +; CHECK: !14 = !{!"0xb\003\000\001", !1, !11} + +!15 = !MDLocation(line: 5, scope: !13) +; CHECK: !15 = !MDLocation(line: 4, scope: !14) + +!16 = !MDLocation(line: 6, scope: !4) +; CHECK: !16 = !MDLocation(line: 5, scope: !14) +; CHECK: !17 = !MDLocation(line: 6, scope: !4) diff --git a/test/Transforms/AddDiscriminators/multiple.ll b/test/Transforms/AddDiscriminators/multiple.ll index 0241a0c..5e552a8 100644 --- a/test/Transforms/AddDiscriminators/multiple.ll +++ b/test/Transforms/AddDiscriminators/multiple.ll @@ -51,21 +51,21 @@ attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointe !llvm.module.flags = !{!7, !8} !llvm.ident = !{!9} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [multiple.c] [DW_LANG_C99] -!1 = metadata !{metadata !"multiple.c", metadata !"."} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [multiple.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !2, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!8 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!9 = metadata !{metadata !"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} -!10 = metadata !{i32 3, i32 0, metadata !11, null} -!11 = metadata !{i32 786443, metadata !1, metadata !4, i32 3, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [multiple.c] -!12 = metadata !{i32 4, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5 (trunk 199750) (llvm/trunk 199751)\000\00\000\00\000", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [multiple.c] [DW_LANG_C99] +!1 = !{!"multiple.c", !"."} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, void (i32)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [multiple.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !2, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{i32 2, !"Dwarf Version", i32 4} +!8 = !{i32 1, !"Debug Info Version", i32 2} +!9 = !{!"clang version 3.5 (trunk 199750) (llvm/trunk 199751)"} +!10 = !MDLocation(line: 3, scope: !11) +!11 = !{!"0xb\003\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [multiple.c] +!12 = !MDLocation(line: 4, scope: !4) -; CHECK: !12 = metadata !{i32 3, i32 0, metadata !13, null} -; CHECK: !13 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 1, i32 0} ; [ DW_TAG_lexical_block ] [./multiple.c] -; CHECK: !14 = metadata !{i32 3, i32 0, metadata !15, null} -; CHECK: !15 = metadata !{i32 786443, metadata !1, metadata !11, i32 3, i32 0, i32 2, i32 1} ; [ DW_TAG_lexical_block ] [./multiple.c] +; CHECK: !12 = !MDLocation(line: 3, scope: !13) +; CHECK: !13 = !{!"0xb\001", !1, !11} ; [ DW_TAG_lexical_block ] [./multiple.c] +; CHECK: !14 = !MDLocation(line: 3, scope: !15) +; CHECK: !15 = !{!"0xb\002", !1, !11} ; [ DW_TAG_lexical_block ] [./multiple.c] diff --git a/test/Transforms/AddDiscriminators/no-discriminators.ll b/test/Transforms/AddDiscriminators/no-discriminators.ll index f7b45e2..dd7faf0 100644 --- a/test/Transforms/AddDiscriminators/no-discriminators.ll +++ b/test/Transforms/AddDiscriminators/no-discriminators.ll @@ -17,7 +17,7 @@ entry: %retval = alloca i32, align 4 %i.addr = alloca i64, align 8 store i64 %i, i64* %i.addr, align 8 - call void @llvm.dbg.declare(metadata !{i64* %i.addr}, metadata !13), !dbg !14 + call void @llvm.dbg.declare(metadata i64* %i.addr, metadata !13, metadata !{}), !dbg !14 %0 = load i64* %i.addr, align 8, !dbg !15 ; CHECK: %0 = load i64* %i.addr, align 8, !dbg !15 %cmp = icmp slt i64 %0, 5, !dbg !15 @@ -39,7 +39,7 @@ return: ; preds = %if.else, %if.then } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.declare(metadata, metadata) #1 +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } attributes #1 = { nounwind readnone } @@ -48,24 +48,24 @@ attributes #1 = { nounwind readnone } !llvm.module.flags = !{!10, !11} !llvm.ident = !{!12} -!0 = metadata !{i32 786449, metadata !1, i32 12, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !2, metadata !2, metadata !"", i32 1} ; [ DW_TAG_compile_unit ] [./no-discriminators] [DW_LANG_C99] -!1 = metadata !{metadata !"no-discriminators", metadata !"."} -!2 = metadata !{} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"foo", metadata !"foo", metadata !"", i32 1, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 (i64)* @foo, null, null, metadata !2, i32 1} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [./no-discriminators] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{metadata !8, metadata !9} -!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!9 = metadata !{i32 786468, null, null, metadata !"long int", i32 0, i64 64, i64 64, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [long int] [line 0, size 64, align 64, offset 0, enc DW_ATE_signed] -!10 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -; CHECK: !10 = metadata !{i32 2, metadata !"Dwarf Version", i32 2} -!11 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} -!12 = metadata !{metadata !"clang version 3.5.0 "} -!13 = metadata !{i32 786689, metadata !4, metadata !"i", metadata !5, i32 16777217, metadata !9, i32 0, i32 0} ; [ DW_TAG_arg_variable ] [i] [line 1] -!14 = metadata !{i32 1, i32 0, metadata !4, null} -!15 = metadata !{i32 2, i32 0, metadata !16, null} -; CHECK: !15 = metadata !{i32 2, i32 0, metadata !16, null} -!16 = metadata !{i32 786443, metadata !1, metadata !4, i32 2, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./no-discriminators] -; CHECK: !16 = metadata !{i32 786443, metadata !1, metadata !4, i32 2, i32 0, i32 0, i32 0} ; [ DW_TAG_lexical_block ] [./no-discriminators] -!17 = metadata !{i32 3, i32 0, metadata !4, null} +!0 = !{!"0x11\0012\00clang version 3.5.0 \000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [./no-discriminators] [DW_LANG_C99] +!1 = !{!"no-discriminators", !"."} +!2 = !{} +!3 = !{!4} +!4 = !{!"0x2e\00foo\00foo\00\001\000\001\000\006\00256\000\001", !1, !5, !6, null, i32 (i64)* @foo, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [def] [foo] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [./no-discriminators] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!8, !9} +!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!9 = !{!"0x24\00long int\000\0064\0064\000\000\005", null, null} ; [ DW_TAG_base_type ] [long int] [line 0, size 64, align 64, offset 0, enc DW_ATE_signed] +!10 = !{i32 2, !"Dwarf Version", i32 2} +; CHECK: !10 = !{i32 2, !"Dwarf Version", i32 2} +!11 = !{i32 1, !"Debug Info Version", i32 2} +!12 = !{!"clang version 3.5.0 "} +!13 = !{!"0x101\00i\0016777217\000", !4, !5, !9} ; [ DW_TAG_arg_variable ] [i] [line 1] +!14 = !MDLocation(line: 1, scope: !4) +!15 = !MDLocation(line: 2, scope: !16) +; CHECK: !15 = !MDLocation(line: 2, scope: !16) +!16 = !{!"0xb\002\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [./no-discriminators] +; CHECK: !16 = !{!"0xb\002\000\000", !1, !4} ; [ DW_TAG_lexical_block ] [./no-discriminators] +!17 = !MDLocation(line: 3, scope: !4) diff --git a/test/Transforms/AlignmentFromAssumptions/simple.ll b/test/Transforms/AlignmentFromAssumptions/simple.ll new file mode 100644 index 0000000..884c8ba --- /dev/null +++ b/test/Transforms/AlignmentFromAssumptions/simple.ll @@ -0,0 +1,215 @@ +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" +; RUN: opt < %s -alignment-from-assumptions -S | FileCheck %s + +define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 24 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 2 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2 +; CHECK: load i32* {{[^,]+}}, align 16 +; CHECK: ret i32 +} + +define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 28 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 -1 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2a +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @goo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @hoo +; CHECK: load i32* %arrayidx, align 32 +; CHECK: ret i32 %add.lcssa +} + +define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @joo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo2 +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @moo(i32* nocapture %a) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = bitcast i32* %a to i8* + tail call void @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo +; CHECK: @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %ptrint1 = ptrtoint i32* %b to i64 + %maskedptr3 = and i64 %ptrint1, 127 + %maskcond4 = icmp eq i64 %maskedptr3, 0 + tail call void @llvm.assume(i1 %maskcond4) + %0 = bitcast i32* %a to i8* + %1 = bitcast i32* %b to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo2 +; CHECK: @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +declare void @llvm.assume(i1) nounwind + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + diff --git a/test/Transforms/AlignmentFromAssumptions/simple32.ll b/test/Transforms/AlignmentFromAssumptions/simple32.ll new file mode 100644 index 0000000..166e7ef --- /dev/null +++ b/test/Transforms/AlignmentFromAssumptions/simple32.ll @@ -0,0 +1,215 @@ +target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-n32-S64" +; RUN: opt < %s -alignment-from-assumptions -S | FileCheck %s + +define i32 @foo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @foo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 24 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 2 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2 +; CHECK: load i32* {{[^,]+}}, align 16 +; CHECK: ret i32 +} + +define i32 @foo2a(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %offsetptr = add i64 %ptrint, 28 + %maskedptr = and i64 %offsetptr, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %arrayidx = getelementptr inbounds i32* %a, i64 -1 + %0 = load i32* %arrayidx, align 4 + ret i32 %0 + +; CHECK-LABEL: @foo2a +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @goo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = load i32* %a, align 4 + ret i32 %0 + +; CHECK-LABEL: @goo +; CHECK: load i32* {{[^,]+}}, align 32 +; CHECK: ret i32 +} + +define i32 @hoo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @hoo +; CHECK: load i32* %arrayidx, align 32 +; CHECK: ret i32 %add.lcssa +} + +define i32 @joo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 8 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @joo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @koo2(i32* nocapture %a) nounwind uwtable readonly { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + br label %for.body + +for.body: ; preds = %entry, %for.body + %indvars.iv = phi i64 [ -4, %entry ], [ %indvars.iv.next, %for.body ] + %r.06 = phi i32 [ 0, %entry ], [ %add, %for.body ] + %arrayidx = getelementptr inbounds i32* %a, i64 %indvars.iv + %0 = load i32* %arrayidx, align 4 + %add = add nsw i32 %0, %r.06 + %indvars.iv.next = add i64 %indvars.iv, 4 + %1 = trunc i64 %indvars.iv.next to i32 + %cmp = icmp slt i32 %1, 2048 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %add.lcssa = phi i32 [ %add, %for.body ] + ret i32 %add.lcssa + +; CHECK-LABEL: @koo2 +; CHECK: load i32* %arrayidx, align 16 +; CHECK: ret i32 %add.lcssa +} + +define i32 @moo(i32* nocapture %a) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %0 = bitcast i32* %a to i8* + tail call void @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo +; CHECK: @llvm.memset.p0i8.i64(i8* %0, i8 0, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +define i32 @moo2(i32* nocapture %a, i32* nocapture %b) nounwind uwtable { +entry: + %ptrint = ptrtoint i32* %a to i64 + %maskedptr = and i64 %ptrint, 31 + %maskcond = icmp eq i64 %maskedptr, 0 + tail call void @llvm.assume(i1 %maskcond) + %ptrint1 = ptrtoint i32* %b to i64 + %maskedptr3 = and i64 %ptrint1, 127 + %maskcond4 = icmp eq i64 %maskedptr3, 0 + tail call void @llvm.assume(i1 %maskcond4) + %0 = bitcast i32* %a to i8* + %1 = bitcast i32* %b to i8* + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 4, i1 false) + ret i32 undef + +; CHECK-LABEL: @moo2 +; CHECK: @llvm.memcpy.p0i8.p0i8.i64(i8* %0, i8* %1, i64 64, i32 32, i1 false) +; CHECK: ret i32 undef +} + +declare void @llvm.assume(i1) nounwind + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) nounwind +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + diff --git a/test/Transforms/AlignmentFromAssumptions/start-unk.ll b/test/Transforms/AlignmentFromAssumptions/start-unk.ll new file mode 100644 index 0000000..b7fe249 --- /dev/null +++ b/test/Transforms/AlignmentFromAssumptions/start-unk.ll @@ -0,0 +1,154 @@ +; RUN: opt -alignment-from-assumptions -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%type1 = type { %type2 } +%type2 = type { [4 x i8] } + +; Function Attrs: nounwind +declare void @llvm.assume(i1) #0 + +; Function Attrs: nounwind readnone +declare i32 @llvm.bswap.i32(i32) #1 + +; Function Attrs: nounwind uwtable +define void @test1() unnamed_addr #2 align 2 { + +; CHECK-LABEL: @test1 + +entry: + br i1 undef, label %if.then, label %if.end + +if.then: ; preds = %entry + unreachable + +if.end: ; preds = %entry + br i1 undef, label %return, label %if.end8 + +if.end8: ; preds = %if.end + br i1 undef, label %if.then13, label %if.end14 + +if.then13: ; preds = %if.end8 + unreachable + +if.end14: ; preds = %if.end8 + br i1 undef, label %cond.false.i129, label %cond.end.i136 + +cond.false.i129: ; preds = %if.end14 + unreachable + +cond.end.i136: ; preds = %if.end14 + br i1 undef, label %land.lhs.true.i, label %if.end.i145 + +land.lhs.true.i: ; preds = %cond.end.i136 + br i1 undef, label %if.end.i145, label %if.then.i137 + +if.then.i137: ; preds = %land.lhs.true.i + br i1 undef, label %cond.false8.i, label %cond.end9.i + +cond.false8.i: ; preds = %if.then.i137 + unreachable + +cond.end9.i: ; preds = %if.then.i137 + br i1 undef, label %if.then23, label %if.end24 + +if.end.i145: ; preds = %land.lhs.true.i, %cond.end.i136 + unreachable + +if.then23: ; preds = %cond.end9.i + unreachable + +if.end24: ; preds = %cond.end9.i + br i1 undef, label %for.end, label %for.body.lr.ph + +for.body.lr.ph: ; preds = %if.end24 + unreachable + +for.end: ; preds = %if.end24 + br i1 undef, label %if.end123, label %if.then121 + +if.then121: ; preds = %for.end + unreachable + +if.end123: ; preds = %for.end + br i1 undef, label %if.end150, label %if.then126 + +if.then126: ; preds = %if.end123 + %ptrint.i.i185 = ptrtoint %type1* undef to i64 + %maskedptr.i.i186 = and i64 %ptrint.i.i185, 1 + %maskcond.i.i187 = icmp eq i64 %maskedptr.i.i186, 0 + tail call void @llvm.assume(i1 %maskcond.i.i187) #0 + %ret.0..sroa_cast.i.i188 = bitcast %type1* undef to i32* + %ret.0.copyload.i.i189 = load i32* %ret.0..sroa_cast.i.i188, align 2 + +; CHECK: load {{.*}} align 2 + + %0 = tail call i32 @llvm.bswap.i32(i32 %ret.0.copyload.i.i189) #0 + %conv131 = zext i32 %0 to i64 + %add.ptr132 = getelementptr inbounds i8* undef, i64 %conv131 + %1 = bitcast i8* %add.ptr132 to %type1* + br i1 undef, label %if.end150, label %if.end.i173 + +if.end.i173: ; preds = %if.then126 + br i1 undef, label %test1.exit, label %cond.false.i.i.i.i174 + +cond.false.i.i.i.i174: ; preds = %if.end.i173 + unreachable + +test1.exit: ; preds = %if.end.i173 + br i1 undef, label %test1a.exit, label %if.end.i124 + +if.end.i124: ; preds = %test1.exit + unreachable + +test1a.exit: ; preds = %test1.exit + br i1 undef, label %if.end150, label %for.body137.lr.ph + +for.body137.lr.ph: ; preds = %test1a.exit + br label %for.body137 + +for.body137: ; preds = %test1b.exit, %for.body137.lr.ph + %ShndxTable.0309 = phi %type1* [ %1, %for.body137.lr.ph ], [ %incdec.ptr, %test1b.exit ] + %ret.0..sroa_cast.i.i106 = bitcast %type1* %ShndxTable.0309 to i32* + br i1 undef, label %for.body137.if.end146_crit_edge, label %if.then140 + +for.body137.if.end146_crit_edge: ; preds = %for.body137 + %incdec.ptr = getelementptr inbounds %type1* %ShndxTable.0309, i64 1 + br i1 undef, label %cond.false.i70, label %cond.end.i + +if.then140: ; preds = %for.body137 + %ret.0.copyload.i.i102 = load i32* %ret.0..sroa_cast.i.i106, align 2 + +; CHECK: load {{.*}} align 2 + + unreachable + +cond.false.i70: ; preds = %for.body137.if.end146_crit_edge + unreachable + +cond.end.i: ; preds = %for.body137.if.end146_crit_edge + br i1 undef, label %test1b.exit, label %cond.false.i.i + +cond.false.i.i: ; preds = %cond.end.i + unreachable + +test1b.exit: ; preds = %cond.end.i + br i1 undef, label %if.end150, label %for.body137 + +if.end150: ; preds = %test1b.exit, %test1a.exit, %if.then126, %if.end123 + br i1 undef, label %for.end176, label %for.body155.lr.ph + +for.body155.lr.ph: ; preds = %if.end150 + unreachable + +for.end176: ; preds = %if.end150 + unreachable + +return: ; preds = %if.end + ret void +} + +attributes #0 = { nounwind } +attributes #1 = { nounwind readnone } +attributes #2 = { nounwind uwtable } + diff --git a/test/Transforms/ArgumentPromotion/dbg.ll b/test/Transforms/ArgumentPromotion/dbg.ll index 70503af..65cf367 100644 --- a/test/Transforms/ArgumentPromotion/dbg.ll +++ b/test/Transforms/ArgumentPromotion/dbg.ll @@ -1,22 +1,26 @@ ; RUN: opt < %s -argpromotion -S | FileCheck %s -; CHECK: call void @test(), !dbg [[DBG_LOC:![0-9]]] -; CHECK: [[TEST_FN:.*]] = {{.*}} void ()* @test -; CHECK: [[DBG_LOC]] = metadata !{i32 8, i32 0, metadata [[TEST_FN]], null} +; CHECK: call void @test(i32 % +; CHECK: void (i32)* @test, {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [test] -define internal void @test(i32* %X) { +declare void @sink(i32) + +define internal void @test(i32** %X) { + %1 = load i32** %X, align 8 + %2 = load i32* %1, align 8 + call void @sink(i32 %2) ret void } -define void @caller() { - call void @test(i32* null), !dbg !1 +define void @caller(i32** %Y) { + call void @test(i32** %Y) ret void } !llvm.module.flags = !{!0} !llvm.dbg.cu = !{!3} -!0 = metadata !{i32 2, metadata !"Debug Info Version", i32 1} -!1 = metadata !{i32 8, i32 0, metadata !2, null} -!2 = metadata !{i32 786478, null, null, metadata !"test", metadata !"test", metadata !"", i32 3, null, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i32*)* @test, null, null, null, i32 3} -!3 = metadata !{i32 786449, null, i32 4, metadata !"clang version 3.5.0 ", i1 false, metadata !"", i32 0, null, null, metadata !4, null, null, metadata !"", i32 2} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/scratch/pr20038/reduce/] [DW_LANG_C_plus_plus] -!4 = metadata !{metadata !2} +!0 = !{i32 2, !"Debug Info Version", i32 2} +!1 = !MDLocation(line: 8, scope: !2) +!2 = !{!"0x2e\00test\00test\00\003\001\001\000\006\00256\000\003", null, null, null, null, void (i32**)* @test, null, null, null} ; [ DW_TAG_subprogram ] +!3 = !{!"0x11\004\00clang version 3.5.0 \000\00\000\00\002", null, null, null, !4, null, null} ; [ DW_TAG_compile_unit ] [/usr/local/google/home/blaikie/dev/scratch/pr20038/reduce/] [DW_LANG_C_plus_plus] +!4 = !{!2} diff --git a/test/Transforms/ArgumentPromotion/fp80.ll b/test/Transforms/ArgumentPromotion/fp80.ll new file mode 100644 index 0000000..a770d60 --- /dev/null +++ b/test/Transforms/ArgumentPromotion/fp80.ll @@ -0,0 +1,58 @@ +; RUN: opt < %s -argpromotion -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%union.u = type { x86_fp80 } +%struct.s = type { double, i16, i8, [5 x i8] } + +@b = internal global %struct.s { double 3.14, i16 9439, i8 25, [5 x i8] undef }, align 16 + +%struct.Foo = type { i32, i64 } +@a = internal global %struct.Foo { i32 1, i64 2 }, align 8 + +define void @run() { +entry: + tail call i8 @UseLongDoubleUnsafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*)) + tail call x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*)) + call i64 @AccessPaddingOfStruct(%struct.Foo* @a) + call i64 @CaptureAStruct(%struct.Foo* @a) + ret void +} + +; CHECK: internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) { +define internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) { +entry: + %bitcast = bitcast %union.u* %arg to %struct.s* + %gep = getelementptr inbounds %struct.s* %bitcast, i64 0, i32 2 + %result = load i8* %gep + ret i8 %result +} + +; CHECK: internal x86_fp80 @UseLongDoubleSafely(x86_fp80 {{%.*}}) { +define internal x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 %arg) { + %gep = getelementptr inbounds %union.u* %arg, i64 0, i32 0 + %fp80 = load x86_fp80* %gep + ret x86_fp80 %fp80 +} + +; CHECK: define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) { +define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) { + %p = bitcast %struct.Foo* %a to i64* + %v = load i64* %p + ret i64 %v +} + +; CHECK: define internal i64 @CaptureAStruct(%struct.Foo* byval %a) { +define internal i64 @CaptureAStruct(%struct.Foo* byval %a) { +entry: + %a_ptr = alloca %struct.Foo* + br label %loop + +loop: + %phi = phi %struct.Foo* [ null, %entry ], [ %gep, %loop ] + %0 = phi %struct.Foo* [ %a, %entry ], [ %0, %loop ] + store %struct.Foo* %phi, %struct.Foo** %a_ptr + %gep = getelementptr %struct.Foo* %a, i64 0 + br label %loop +} diff --git a/test/Transforms/ArgumentPromotion/reserve-tbaa.ll b/test/Transforms/ArgumentPromotion/reserve-tbaa.ll index 4688a83..db9d70d 100644 --- a/test/Transforms/ArgumentPromotion/reserve-tbaa.ll +++ b/test/Transforms/ArgumentPromotion/reserve-tbaa.ll @@ -37,16 +37,16 @@ entry: ret i32 0 } -!1 = metadata !{metadata !2, metadata !2, i64 0} -!2 = metadata !{metadata !"long", metadata !3, i64 0} -!3 = metadata !{metadata !"omnipotent char", metadata !4, i64 0} -!4 = metadata !{metadata !"Simple C/C++ TBAA"} -!5 = metadata !{metadata !6, metadata !6, i64 0} -!6 = metadata !{metadata !"int", metadata !3, i64 0} -!7 = metadata !{metadata !3, metadata !3, i64 0} -!8 = metadata !{metadata !9, metadata !9, i64 0} -!9 = metadata !{metadata !"any pointer", metadata !3, i64 0} -; CHECK: ![[I32]] = metadata !{metadata ![[I32_TYPE:[0-9]+]], metadata ![[I32_TYPE]], i64 0} -; CHECK: ![[I32_TYPE]] = metadata !{metadata !"int", metadata !{{.*}}, i64 0} -; CHECK: ![[LONG]] = metadata !{metadata ![[LONG_TYPE:[0-9]+]], metadata ![[LONG_TYPE]], i64 0} -; CHECK: ![[LONG_TYPE]] = metadata !{metadata !"long", metadata !{{.*}}, i64 0} +!1 = !{!2, !2, i64 0} +!2 = !{!"long", !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C/C++ TBAA"} +!5 = !{!6, !6, i64 0} +!6 = !{!"int", !3, i64 0} +!7 = !{!3, !3, i64 0} +!8 = !{!9, !9, i64 0} +!9 = !{!"any pointer", !3, i64 0} +; CHECK: ![[I32]] = !{![[I32_TYPE:[0-9]+]], ![[I32_TYPE]], i64 0} +; CHECK: ![[I32_TYPE]] = !{!"int", !{{.*}}, i64 0} +; CHECK: ![[LONG]] = !{![[LONG_TYPE:[0-9]+]], ![[LONG_TYPE]], i64 0} +; CHECK: ![[LONG_TYPE]] = !{!"long", !{{.*}}, i64 0} diff --git a/test/Transforms/ArgumentPromotion/tail.ll b/test/Transforms/ArgumentPromotion/tail.ll index 43b8996..2ea387c 100644 --- a/test/Transforms/ArgumentPromotion/tail.ll +++ b/test/Transforms/ArgumentPromotion/tail.ll @@ -1,6 +1,8 @@ ; RUN: opt %s -argpromotion -S -o - | FileCheck %s ; PR14710 +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + %pair = type { i32, i32 } declare i8* @foo(%pair*) diff --git a/test/Transforms/ArgumentPromotion/variadic.ll b/test/Transforms/ArgumentPromotion/variadic.ll new file mode 100644 index 0000000..0ae52b3 --- /dev/null +++ b/test/Transforms/ArgumentPromotion/variadic.ll @@ -0,0 +1,28 @@ +; RUN: opt < %s -argpromotion -S | FileCheck %s + +; Unused arguments from variadic functions cannot be eliminated as that changes +; their classiciation according to the SysV amd64 ABI. Clang and other frontends +; bake in the classification when they use things like byval, as in this test. + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.tt0 = type { i64, i64 } +%struct.__va_list_tag = type { i32, i32, i8*, i8* } + +@t45 = internal global %struct.tt0 { i64 1335139741, i64 438042995 }, align 8 + +; Function Attrs: nounwind uwtable +define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 { +entry: + tail call void (i8*, i8*, i8*, i8*, i8*, ...)* @callee_t0f(i8* undef, i8* undef, i8* undef, i8* undef, i8* undef, %struct.tt0* byval align 8 @t45) + ret i32 0 +} + +; Function Attrs: nounwind uwtable +define internal void @callee_t0f(i8* nocapture readnone %tp13, i8* nocapture readnone %tp14, i8* nocapture readnone %tp15, i8* nocapture readnone %tp16, i8* nocapture readnone %tp17, ...) { +entry: + ret void +} + +; CHECK-LABEL: define internal void @callee_t0f(i8* nocapture readnone %tp13, i8* nocapture readnone %tp14, i8* nocapture readnone %tp15, i8* nocapture readnone %tp16, i8* nocapture readnone %tp17, ...) diff --git a/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll new file mode 100644 index 0000000..282d42f --- /dev/null +++ b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v7.ll @@ -0,0 +1,364 @@ +; RUN: opt -S -o - -mtriple=armv7-apple-ios7.0 -atomic-expand %s | FileCheck %s + +define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { +; CHECK-LABEL: @test_atomic_xchg_i8 +; CHECK-NOT: dmb +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK-NOT: dmb +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw xchg i8* %ptr, i8 %xchgend monotonic + ret i8 %res +} + +define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) { +; CHECK-LABEL: @test_atomic_add_i16 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16 +; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend +; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i16 [[OLDVAL]] + %res = atomicrmw add i16* %ptr, i16 %addend seq_cst + ret i16 %res +} + +define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) { +; CHECK-LABEL: @test_atomic_sub_i32 +; CHECK-NOT: dmb +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr) +; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i32 [[OLDVAL]] + %res = atomicrmw sub i32* %ptr, i32 %subend acquire + ret i32 %res +} + +define i8 @test_atomic_and_i8(i8* %ptr, i8 %andend) { +; CHECK-LABEL: @test_atomic_and_i8 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[NEWVAL:%.*]] = and i8 [[OLDVAL]], %andend +; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK-NOT: dmb +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw and i8* %ptr, i8 %andend release + ret i8 %res +} + +define i16 @test_atomic_nand_i16(i16* %ptr, i16 %nandend) { +; CHECK-LABEL: @test_atomic_nand_i16 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16 +; CHECK: [[NEWVAL_TMP:%.*]] = and i16 [[OLDVAL]], %nandend +; CHECK: [[NEWVAL:%.*]] = xor i16 [[NEWVAL_TMP]], -1 +; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i16 [[OLDVAL]] + %res = atomicrmw nand i16* %ptr, i16 %nandend seq_cst + ret i16 %res +} + +define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) { +; CHECK-LABEL: @test_atomic_or_i64 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]]) +; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 +; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 +; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 +; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 +; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 +; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] +; CHECK: [[NEWVAL:%.*]] = or i64 [[OLDVAL]], %orend +; CHECK: [[NEWLO:%.*]] = trunc i64 [[NEWVAL]] to i32 +; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 [[NEWVAL]], 32 +; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i64 [[OLDVAL]] + %res = atomicrmw or i64* %ptr, i64 %orend seq_cst + ret i64 %res +} + +define i8 @test_atomic_xor_i8(i8* %ptr, i8 %xorend) { +; CHECK-LABEL: @test_atomic_xor_i8 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[NEWVAL:%.*]] = xor i8 [[OLDVAL]], %xorend +; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw xor i8* %ptr, i8 %xorend seq_cst + ret i8 %res +} + +define i8 @test_atomic_max_i8(i8* %ptr, i8 %maxend) { +; CHECK-LABEL: @test_atomic_max_i8 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[WANT_OLD:%.*]] = icmp sgt i8 [[OLDVAL]], %maxend +; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %maxend +; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw max i8* %ptr, i8 %maxend seq_cst + ret i8 %res +} + +define i8 @test_atomic_min_i8(i8* %ptr, i8 %minend) { +; CHECK-LABEL: @test_atomic_min_i8 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[WANT_OLD:%.*]] = icmp sle i8 [[OLDVAL]], %minend +; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %minend +; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw min i8* %ptr, i8 %minend seq_cst + ret i8 %res +} + +define i8 @test_atomic_umax_i8(i8* %ptr, i8 %umaxend) { +; CHECK-LABEL: @test_atomic_umax_i8 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[WANT_OLD:%.*]] = icmp ugt i8 [[OLDVAL]], %umaxend +; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %umaxend +; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw umax i8* %ptr, i8 %umaxend seq_cst + ret i8 %res +} + +define i8 @test_atomic_umin_i8(i8* %ptr, i8 %uminend) { +; CHECK-LABEL: @test_atomic_umin_i8 +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[WANT_OLD:%.*]] = icmp ule i8 [[OLDVAL]], %uminend +; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %uminend +; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw umin i8* %ptr, i8 %uminend seq_cst + ret i8 %res +} + +define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) { +; CHECK-LABEL: @test_cmpxchg_i8_seqcst_seqcst +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i8 +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i8 [[OLDVAL]] + + %pairold = cmpxchg i8* %ptr, i8 %desired, i8 %newval seq_cst seq_cst + %old = extractvalue { i8, i1 } %pairold, 0 + ret i8 %old +} + +define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newval) { +; CHECK-LABEL: @test_cmpxchg_i16_seqcst_monotonic +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16 +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: dmb +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i16 [[OLDVAL]] + + %pairold = cmpxchg i16* %ptr, i16 %desired, i16 %newval seq_cst monotonic + %old = extractvalue { i16, i1 } %pairold, 0 + ret i16 %old +} + +define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newval) { +; CHECK-LABEL: @test_cmpxchg_i32_acquire_acquire +; CHECK-NOT: dmb +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr) +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* %ptr) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i32 [[OLDVAL]] + + %pairold = cmpxchg i32* %ptr, i32 %desired, i32 %newval acquire acquire + %old = extractvalue { i32, i1 } %pairold, 0 + ret i32 %old +} + +define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %newval) { +; CHECK-LABEL: @test_cmpxchg_i64_monotonic_monotonic +; CHECK-NOT: dmb +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]]) +; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 +; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 +; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 +; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 +; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 +; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i64 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[NEWLO:%.*]] = trunc i64 %newval to i32 +; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 %newval, 32 +; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK-NOT: dmb +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: dmb +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i64 [[OLDVAL]] + + %pairold = cmpxchg i64* %ptr, i64 %desired, i64 %newval monotonic monotonic + %old = extractvalue { i64, i1 } %pairold, 0 + ret i64 %old +} diff --git a/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll new file mode 100644 index 0000000..42d7b78 --- /dev/null +++ b/test/Transforms/AtomicExpand/ARM/atomic-expansion-v8.ll @@ -0,0 +1,226 @@ +; RUN: opt -S -o - -mtriple=armv8-linux-gnueabihf -atomic-expand %s | FileCheck %s + +define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { +; CHECK-LABEL: @test_atomic_xchg_i8 +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 +; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK-NOT: fence +; CHECK: ret i8 [[OLDVAL]] + %res = atomicrmw xchg i8* %ptr, i8 %xchgend monotonic + ret i8 %res +} + +define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) { +; CHECK-LABEL: @test_atomic_add_i16 +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16 +; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend +; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK-NOT: fence +; CHECK: ret i16 [[OLDVAL]] + %res = atomicrmw add i16* %ptr, i16 %addend seq_cst + ret i16 %res +} + +define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) { +; CHECK-LABEL: @test_atomic_sub_i32 +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* %ptr) +; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* %ptr) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK-NOT: fence +; CHECK: ret i32 [[OLDVAL]] + %res = atomicrmw sub i32* %ptr, i32 %subend acquire + ret i32 %res +} + +define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) { +; CHECK-LABEL: @test_atomic_or_i64 +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] +; CHECK: [[LOOP]]: +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldaexd(i8* [[PTR8]]) +; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 +; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 +; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 +; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 +; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 +; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] +; CHECK: [[NEWVAL:%.*]] = or i64 [[OLDVAL]], %orend +; CHECK: [[NEWLO:%.*]] = trunc i64 [[NEWVAL]] to i32 +; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 [[NEWVAL]], 32 +; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) +; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] +; CHECK: [[END]]: +; CHECK-NOT: fence +; CHECK: ret i64 [[OLDVAL]] + %res = atomicrmw or i64* %ptr, i64 %orend seq_cst + ret i64 %res +} + +define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) { +; CHECK-LABEL: @test_cmpxchg_i8_seqcst_seqcst +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i8 +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i8(i32 [[NEWVAL32]], i8* %ptr) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK-NOT: fence_cst +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: fence_cst +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i8 [[OLDVAL]] + + %pairold = cmpxchg i8* %ptr, i8 %desired, i8 %newval seq_cst seq_cst + %old = extractvalue { i8, i1 } %pairold, 0 + ret i8 %old +} + +define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newval) { +; CHECK-LABEL: @test_cmpxchg_i16_seqcst_monotonic +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* %ptr) +; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16 +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32 +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* %ptr) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK-NOT: fence +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: fence +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i16 [[OLDVAL]] + + %pairold = cmpxchg i16* %ptr, i16 %desired, i16 %newval seq_cst monotonic + %old = extractvalue { i16, i1 } %pairold, 0 + ret i16 %old +} + +define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newval) { +; CHECK-LABEL: @test_cmpxchg_i32_acquire_acquire +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* %ptr) +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* %ptr) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK-NOT: fence_cst +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: fence_cst +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i32 [[OLDVAL]] + + %pairold = cmpxchg i32* %ptr, i32 %desired, i32 %newval acquire acquire + %old = extractvalue { i32, i1 } %pairold, 0 + ret i32 %old +} + +define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %newval) { +; CHECK-LABEL: @test_cmpxchg_i64_monotonic_monotonic +; CHECK-NOT: fence +; CHECK: br label %[[LOOP:.*]] + +; CHECK: [[LOOP]]: +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]]) +; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 +; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 +; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 +; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 +; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 +; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i64 [[OLDVAL]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[NEWLO:%.*]] = trunc i64 %newval to i32 +; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 %newval, 32 +; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 +; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* +; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) +; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 +; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK-NOT: fence_cst +; CHECK: br label %[[DONE:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: fence_cst +; CHECK: br label %[[DONE]] + +; CHECK: [[DONE]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i64 [[OLDVAL]] + + %pairold = cmpxchg i64* %ptr, i64 %desired, i64 %newval monotonic monotonic + %old = extractvalue { i64, i1 } %pairold, 0 + ret i64 %old +} diff --git a/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll b/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll new file mode 100644 index 0000000..5465300 --- /dev/null +++ b/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll @@ -0,0 +1,98 @@ +; RUN: opt -atomic-expand -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s + +define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) { +; CHECK-LABEL: @test_cmpxchg_seq_cst +; Intrinsic for "dmb ishst" is then expected +; CHECK: call void @llvm.arm.dmb(i32 10) +; CHECK: br label %[[START:.*]] + +; CHECK: [[START]]: +; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) +; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 +; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[END:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[END]] + +; CHECK: [[END]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i32 [[LOADED]] + + %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst seq_cst + %oldval = extractvalue { i32, i1 } %pair, 0 + ret i32 %oldval +} + +define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) { +; CHECK-LABEL: @test_cmpxchg_weak_fail +; CHECK: call void @llvm.arm.dmb(i32 10) +; CHECK: br label %[[START:.*]] + +; CHECK: [[START]]: +; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) +; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 +; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK: call void @llvm.arm.dmb(i32 11) +; CHECK: br label %[[END:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: dmb +; CHECK: br label %[[END]] + +; CHECK: [[END]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i1 [[SUCCESS]] + + %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst monotonic + %oldval = extractvalue { i32, i1 } %pair, 1 + ret i1 %oldval +} + +define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) { +; CHECK-LABEL: @test_cmpxchg_monotonic +; CHECK-NOT: dmb +; CHECK: br label %[[START:.*]] + +; CHECK: [[START]]: +; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) +; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired +; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[TRY_STORE]]: +; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) +; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 +; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] + +; CHECK: [[SUCCESS_BB]]: +; CHECK-NOT: dmb +; CHECK: br label %[[END:.*]] + +; CHECK: [[FAILURE_BB]]: +; CHECK-NOT: dmb +; CHECK: br label %[[END]] + +; CHECK: [[END]]: +; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] +; CHECK: ret i32 [[LOADED]] + + %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new monotonic monotonic + %oldval = extractvalue { i32, i1 } %pair, 0 + ret i32 %oldval +} diff --git a/test/Transforms/AtomicExpand/ARM/lit.local.cfg b/test/Transforms/AtomicExpand/ARM/lit.local.cfg new file mode 100644 index 0000000..98c6700 --- /dev/null +++ b/test/Transforms/AtomicExpand/ARM/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'ARM' in config.root.targets: + config.unsupported = True + diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v7.ll b/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v7.ll deleted file mode 100644 index 6a93016..0000000 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v7.ll +++ /dev/null @@ -1,364 +0,0 @@ -; RUN: opt -S -o - -mtriple=armv7-apple-ios7.0 -atomic-ll-sc %s | FileCheck %s - -define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { -; CHECK-LABEL: @test_atomic_xchg_i8 -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK-NOT: fence -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw xchg i8* %ptr, i8 %xchgend monotonic - ret i8 %res -} - -define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) { -; CHECK-LABEL: @test_atomic_add_i16 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16 -; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend -; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i16 [[OLDVAL]] - %res = atomicrmw add i16* %ptr, i16 %addend seq_cst - ret i16 %res -} - -define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) { -; CHECK-LABEL: @test_atomic_sub_i32 -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr) -; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence acquire -; CHECK: ret i32 [[OLDVAL]] - %res = atomicrmw sub i32* %ptr, i32 %subend acquire - ret i32 %res -} - -define i8 @test_atomic_and_i8(i8* %ptr, i8 %andend) { -; CHECK-LABEL: @test_atomic_and_i8 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[NEWVAL:%.*]] = and i8 [[OLDVAL]], %andend -; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK-NOT: fence -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw and i8* %ptr, i8 %andend release - ret i8 %res -} - -define i16 @test_atomic_nand_i16(i16* %ptr, i16 %nandend) { -; CHECK-LABEL: @test_atomic_nand_i16 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16 -; CHECK: [[NEWVAL_TMP:%.*]] = and i16 [[OLDVAL]], %nandend -; CHECK: [[NEWVAL:%.*]] = xor i16 [[NEWVAL_TMP]], -1 -; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i16 [[OLDVAL]] - %res = atomicrmw nand i16* %ptr, i16 %nandend seq_cst - ret i16 %res -} - -define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) { -; CHECK-LABEL: @test_atomic_or_i64 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]]) -; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 -; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 -; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 -; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 -; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 -; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] -; CHECK: [[NEWVAL:%.*]] = or i64 [[OLDVAL]], %orend -; CHECK: [[NEWLO:%.*]] = trunc i64 [[NEWVAL]] to i32 -; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 [[NEWVAL]], 32 -; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i64 [[OLDVAL]] - %res = atomicrmw or i64* %ptr, i64 %orend seq_cst - ret i64 %res -} - -define i8 @test_atomic_xor_i8(i8* %ptr, i8 %xorend) { -; CHECK-LABEL: @test_atomic_xor_i8 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[NEWVAL:%.*]] = xor i8 [[OLDVAL]], %xorend -; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw xor i8* %ptr, i8 %xorend seq_cst - ret i8 %res -} - -define i8 @test_atomic_max_i8(i8* %ptr, i8 %maxend) { -; CHECK-LABEL: @test_atomic_max_i8 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[WANT_OLD:%.*]] = icmp sgt i8 [[OLDVAL]], %maxend -; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %maxend -; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw max i8* %ptr, i8 %maxend seq_cst - ret i8 %res -} - -define i8 @test_atomic_min_i8(i8* %ptr, i8 %minend) { -; CHECK-LABEL: @test_atomic_min_i8 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[WANT_OLD:%.*]] = icmp sle i8 [[OLDVAL]], %minend -; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %minend -; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw min i8* %ptr, i8 %minend seq_cst - ret i8 %res -} - -define i8 @test_atomic_umax_i8(i8* %ptr, i8 %umaxend) { -; CHECK-LABEL: @test_atomic_umax_i8 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[WANT_OLD:%.*]] = icmp ugt i8 [[OLDVAL]], %umaxend -; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %umaxend -; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw umax i8* %ptr, i8 %umaxend seq_cst - ret i8 %res -} - -define i8 @test_atomic_umin_i8(i8* %ptr, i8 %uminend) { -; CHECK-LABEL: @test_atomic_umin_i8 -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[WANT_OLD:%.*]] = icmp ule i8 [[OLDVAL]], %uminend -; CHECK: [[NEWVAL:%.*]] = select i1 [[WANT_OLD]], i8 [[OLDVAL]], i8 %uminend -; CHECK: [[NEWVAL32:%.*]] = zext i8 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK: fence seq_cst -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw umin i8* %ptr, i8 %uminend seq_cst - ret i8 %res -} - -define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) { -; CHECK-LABEL: @test_cmpxchg_i8_seqcst_seqcst -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i8 -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK: fence seq_cst -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i8 [[OLDVAL]] - - %pairold = cmpxchg i8* %ptr, i8 %desired, i8 %newval seq_cst seq_cst - %old = extractvalue { i8, i1 } %pairold, 0 - ret i8 %old -} - -define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newval) { -; CHECK-LABEL: @test_cmpxchg_i16_seqcst_monotonic -; CHECK: fence release -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i16(i16* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16 -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i16(i32 [[NEWVAL32]], i16* %ptr) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i16 [[OLDVAL]] - - %pairold = cmpxchg i16* %ptr, i16 %desired, i16 %newval seq_cst monotonic - %old = extractvalue { i16, i1 } %pairold, 0 - ret i16 %old -} - -define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newval) { -; CHECK-LABEL: @test_cmpxchg_i32_acquire_acquire -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %ptr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* %ptr) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: fence acquire -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK: fence acquire -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i32 [[OLDVAL]] - - %pairold = cmpxchg i32* %ptr, i32 %desired, i32 %newval acquire acquire - %old = extractvalue { i32, i1 } %pairold, 0 - ret i32 %old -} - -define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %newval) { -; CHECK-LABEL: @test_cmpxchg_i64_monotonic_monotonic -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]]) -; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 -; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 -; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 -; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 -; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 -; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i64 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[NEWLO:%.*]] = trunc i64 %newval to i32 -; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 %newval, 32 -; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i64 [[OLDVAL]] - - %pairold = cmpxchg i64* %ptr, i64 %desired, i64 %newval monotonic monotonic - %old = extractvalue { i64, i1 } %pairold, 0 - ret i64 %old -} \ No newline at end of file diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v8.ll b/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v8.ll deleted file mode 100644 index 8092c10..0000000 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/atomic-expansion-v8.ll +++ /dev/null @@ -1,226 +0,0 @@ -; RUN: opt -S -o - -mtriple=armv8-linux-gnueabihf -atomic-ll-sc %s | FileCheck %s - -define i8 @test_atomic_xchg_i8(i8* %ptr, i8 %xchgend) { -; CHECK-LABEL: @test_atomic_xchg_i8 -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldrex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i8 -; CHECK: [[NEWVAL32:%.*]] = zext i8 %xchgend to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK-NOT: fence -; CHECK: ret i8 [[OLDVAL]] - %res = atomicrmw xchg i8* %ptr, i8 %xchgend monotonic - ret i8 %res -} - -define i16 @test_atomic_add_i16(i16* %ptr, i16 %addend) { -; CHECK-LABEL: @test_atomic_add_i16 -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 [[OLDVAL32]] to i16 -; CHECK: [[NEWVAL:%.*]] = add i16 [[OLDVAL]], %addend -; CHECK: [[NEWVAL32:%.*]] = zext i16 [[NEWVAL]] to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK-NOT: fence -; CHECK: ret i16 [[OLDVAL]] - %res = atomicrmw add i16* %ptr, i16 %addend seq_cst - ret i16 %res -} - -define i32 @test_atomic_sub_i32(i32* %ptr, i32 %subend) { -; CHECK-LABEL: @test_atomic_sub_i32 -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* %ptr) -; CHECK: [[NEWVAL:%.*]] = sub i32 [[OLDVAL]], %subend -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 [[NEWVAL]], i32* %ptr) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK-NOT: fence -; CHECK: ret i32 [[OLDVAL]] - %res = atomicrmw sub i32* %ptr, i32 %subend acquire - ret i32 %res -} - -define i64 @test_atomic_or_i64(i64* %ptr, i64 %orend) { -; CHECK-LABEL: @test_atomic_or_i64 -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] -; CHECK: [[LOOP]]: -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldaexd(i8* [[PTR8]]) -; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 -; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 -; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 -; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 -; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 -; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] -; CHECK: [[NEWVAL:%.*]] = or i64 [[OLDVAL]], %orend -; CHECK: [[NEWLO:%.*]] = trunc i64 [[NEWVAL]] to i32 -; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 [[NEWVAL]], 32 -; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) -; CHECK: [[TST:%.*]] = icmp ne i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[LOOP]], label %[[END:.*]] -; CHECK: [[END]]: -; CHECK-NOT: fence -; CHECK: ret i64 [[OLDVAL]] - %res = atomicrmw or i64* %ptr, i64 %orend seq_cst - ret i64 %res -} - -define i8 @test_cmpxchg_i8_seqcst_seqcst(i8* %ptr, i8 %desired, i8 %newval) { -; CHECK-LABEL: @test_cmpxchg_i8_seqcst_seqcst -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i8(i8* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i8 -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i8 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[NEWVAL32:%.*]] = zext i8 %newval to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i8(i32 [[NEWVAL32]], i8* %ptr) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence_cst -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence_cst -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i8 [[OLDVAL]] - - %pairold = cmpxchg i8* %ptr, i8 %desired, i8 %newval seq_cst seq_cst - %old = extractvalue { i8, i1 } %pairold, 0 - ret i8 %old -} - -define i16 @test_cmpxchg_i16_seqcst_monotonic(i16* %ptr, i16 %desired, i16 %newval) { -; CHECK-LABEL: @test_cmpxchg_i16_seqcst_monotonic -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL32:%.*]] = call i32 @llvm.arm.ldaex.p0i16(i16* %ptr) -; CHECK: [[OLDVAL:%.*]] = trunc i32 %1 to i16 -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i16 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[NEWVAL32:%.*]] = zext i16 %newval to i32 -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.stlex.p0i16(i32 [[NEWVAL32]], i16* %ptr) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i16 [[OLDVAL]] - - %pairold = cmpxchg i16* %ptr, i16 %desired, i16 %newval seq_cst monotonic - %old = extractvalue { i16, i1 } %pairold, 0 - ret i16 %old -} - -define i32 @test_cmpxchg_i32_acquire_acquire(i32* %ptr, i32 %desired, i32 %newval) { -; CHECK-LABEL: @test_cmpxchg_i32_acquire_acquire -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[OLDVAL:%.*]] = call i32 @llvm.arm.ldaex.p0i32(i32* %ptr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %newval, i32* %ptr) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence_cst -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence_cst -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i32 [[OLDVAL]] - - %pairold = cmpxchg i32* %ptr, i32 %desired, i32 %newval acquire acquire - %old = extractvalue { i32, i1 } %pairold, 0 - ret i32 %old -} - -define i64 @test_cmpxchg_i64_monotonic_monotonic(i64* %ptr, i64 %desired, i64 %newval) { -; CHECK-LABEL: @test_cmpxchg_i64_monotonic_monotonic -; CHECK-NOT: fence -; CHECK: br label %[[LOOP:.*]] - -; CHECK: [[LOOP]]: -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[LOHI:%.*]] = call { i32, i32 } @llvm.arm.ldrexd(i8* [[PTR8]]) -; CHECK: [[LO:%.*]] = extractvalue { i32, i32 } [[LOHI]], 0 -; CHECK: [[HI:%.*]] = extractvalue { i32, i32 } [[LOHI]], 1 -; CHECK: [[LO64:%.*]] = zext i32 [[LO]] to i64 -; CHECK: [[HI64_TMP:%.*]] = zext i32 [[HI]] to i64 -; CHECK: [[HI64:%.*]] = shl i64 [[HI64_TMP]], 32 -; CHECK: [[OLDVAL:%.*]] = or i64 [[LO64]], [[HI64]] -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i64 [[OLDVAL]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[NEWLO:%.*]] = trunc i64 %newval to i32 -; CHECK: [[NEWHI_TMP:%.*]] = lshr i64 %newval, 32 -; CHECK: [[NEWHI:%.*]] = trunc i64 [[NEWHI_TMP]] to i32 -; CHECK: [[PTR8:%.*]] = bitcast i64* %ptr to i8* -; CHECK: [[TRYAGAIN:%.*]] = call i32 @llvm.arm.strexd(i32 [[NEWLO]], i32 [[NEWHI]], i8* [[PTR8]]) -; CHECK: [[TST:%.*]] = icmp eq i32 [[TRYAGAIN]], 0 -; CHECK: br i1 [[TST]], label %[[SUCCESS_BB:.*]], label %[[LOOP]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence_cst -; CHECK: br label %[[DONE:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence_cst -; CHECK: br label %[[DONE]] - -; CHECK: [[DONE]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i64 [[OLDVAL]] - - %pairold = cmpxchg i64* %ptr, i64 %desired, i64 %newval monotonic monotonic - %old = extractvalue { i64, i1 } %pairold, 0 - ret i64 %old -} \ No newline at end of file diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/cmpxchg-weak.ll b/test/Transforms/AtomicExpandLoadLinked/ARM/cmpxchg-weak.ll deleted file mode 100644 index 07a4a7f..0000000 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/cmpxchg-weak.ll +++ /dev/null @@ -1,97 +0,0 @@ -; RUN: opt -atomic-ll-sc -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s - -define i32 @test_cmpxchg_seq_cst(i32* %addr, i32 %desired, i32 %new) { -; CHECK-LABEL: @test_cmpxchg_seq_cst -; CHECK: fence release -; CHECK: br label %[[START:.*]] - -; CHECK: [[START]]: -; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) -; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 -; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst -; CHECK: br label %[[END:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK: fence seq_cst -; CHECK: br label %[[END]] - -; CHECK: [[END]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i32 [[LOADED]] - - %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst seq_cst - %oldval = extractvalue { i32, i1 } %pair, 0 - ret i32 %oldval -} - -define i1 @test_cmpxchg_weak_fail(i32* %addr, i32 %desired, i32 %new) { -; CHECK-LABEL: @test_cmpxchg_weak_fail -; CHECK: fence release -; CHECK: br label %[[START:.*]] - -; CHECK: [[START]]: -; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) -; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 -; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: fence seq_cst -; CHECK: br label %[[END:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[END]] - -; CHECK: [[END]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i1 [[SUCCESS]] - - %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new seq_cst monotonic - %oldval = extractvalue { i32, i1 } %pair, 1 - ret i1 %oldval -} - -define i32 @test_cmpxchg_monotonic(i32* %addr, i32 %desired, i32 %new) { -; CHECK-LABEL: @test_cmpxchg_monotonic -; CHECK-NOT: fence -; CHECK: br label %[[START:.*]] - -; CHECK: [[START]]: -; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0i32(i32* %addr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[TRY_STORE:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0i32(i32 %new, i32* %addr) -; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 -; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[END:.*]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: fence -; CHECK: br label %[[END]] - -; CHECK: [[END]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i32 [[LOADED]] - - %pair = cmpxchg weak i32* %addr, i32 %desired, i32 %new monotonic monotonic - %oldval = extractvalue { i32, i1 } %pair, 0 - ret i32 %oldval -} diff --git a/test/Transforms/AtomicExpandLoadLinked/ARM/lit.local.cfg b/test/Transforms/AtomicExpandLoadLinked/ARM/lit.local.cfg deleted file mode 100644 index 98c6700..0000000 --- a/test/Transforms/AtomicExpandLoadLinked/ARM/lit.local.cfg +++ /dev/null @@ -1,3 +0,0 @@ -if not 'ARM' in config.root.targets: - config.unsupported = True - diff --git a/test/Transforms/BBVectorize/loop1.ll b/test/Transforms/BBVectorize/loop1.ll index ed7be15..ca36170 100644 --- a/test/Transforms/BBVectorize/loop1.ll +++ b/test/Transforms/BBVectorize/loop1.ll @@ -83,7 +83,7 @@ for.body: ; preds = %for.body, %entry ; CHECK-UNRL: %add12 = fadd <2 x double> %add7, %mul11 ; CHECK-UNRL: %4 = bitcast double* %arrayidx14 to <2 x double>* ; CHECK-UNRL: store <2 x double> %add12, <2 x double>* %4, align 8 -; CHECK-UNRL: %indvars.iv.next.1 = add i64 %indvars.iv, 2 +; CHECK-UNRL: %indvars.iv.next.1 = add nsw i64 %indvars.iv, 2 ; CHECK-UNRL: %lftr.wideiv.1 = trunc i64 %indvars.iv.next.1 to i32 ; CHECK-UNRL: %exitcond.1 = icmp eq i32 %lftr.wideiv.1, 10 ; CHECK-UNRL: br i1 %exitcond.1, label %for.end, label %for.body diff --git a/test/Transforms/BBVectorize/metadata.ll b/test/Transforms/BBVectorize/metadata.ll index ac7297d..874fbb8 100644 --- a/test/Transforms/BBVectorize/metadata.ll +++ b/test/Transforms/BBVectorize/metadata.ll @@ -41,9 +41,9 @@ entry: ; CHECK: ret void } -!0 = metadata !{i64 0, i64 2} -!1 = metadata !{i64 3, i64 5} +!0 = !{i64 0, i64 2} +!1 = !{i64 3, i64 5} -!2 = metadata !{ float 5.0 } -!3 = metadata !{ float 2.5 } +!2 = !{ float 5.0 } +!3 = !{ float 2.5 } diff --git a/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll b/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll index 598ea0e..d4b94fe 100644 --- a/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll +++ b/test/Transforms/BranchFolding/2007-10-19-InlineAsmDirectives.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -std-compile-opts -o - | llc -no-integrated-as -o - | grep bork_directive | wc -l | grep 2 +; RUN: opt < %s -O3 -o - | llc -no-integrated-as -o - | grep bork_directive | wc -l | grep 2 ;; We don't want branch folding to fold asm directives. diff --git a/test/Transforms/CodeGenPrepare/AArch64/lit.local.cfg b/test/Transforms/CodeGenPrepare/AArch64/lit.local.cfg new file mode 100644 index 0000000..cec29af --- /dev/null +++ b/test/Transforms/CodeGenPrepare/AArch64/lit.local.cfg @@ -0,0 +1,3 @@ +if not 'AArch64' in config.root.targets: + config.unsupported = True + diff --git a/test/Transforms/CodeGenPrepare/AArch64/trunc-weird-user.ll b/test/Transforms/CodeGenPrepare/AArch64/trunc-weird-user.ll new file mode 100644 index 0000000..b4e6a40 --- /dev/null +++ b/test/Transforms/CodeGenPrepare/AArch64/trunc-weird-user.ll @@ -0,0 +1,36 @@ +; RUN: opt -S -codegenprepare -mtriple=arm64-apple-ios7.0 %s | FileCheck %s + +%foo = type { i8 } + +define %foo @test_merge(i32 %in) { +; CHECK-LABEL: @test_merge + + ; CodeGenPrepare was requesting the EVT for { i8 } to determine + ; whether the insertvalue user of the trunc was legal. This + ; asserted. + +; CHECK: insertvalue %foo undef, i8 %byte, 0 + %lobit = lshr i32 %in, 31 + %byte = trunc i32 %lobit to i8 + %struct = insertvalue %foo undef, i8 %byte, 0 + ret %"foo" %struct +} + +define i64* @test_merge_PR21548(i32 %a, i64* %p1, i64* %p2, i64* %p3) { +; CHECK-LABEL: @test_merge_PR21548 + %as = lshr i32 %a, 3 + %Tr = trunc i32 %as to i1 + br i1 %Tr, label %BB2, label %BB3 + +BB2: + ; Similarly to above: + ; CodeGenPrepare was requesting the EVT for i8* to determine + ; whether the select user of the trunc was legal. This asserted. + +; CHECK: select i1 {{%.*}}, i64* %p1, i64* %p2 + %p = select i1 %Tr, i64* %p1, i64* %p2 + ret i64* %p + +BB3: + ret i64* %p3 +} diff --git a/test/Transforms/ConstProp/trunc_vec.ll b/test/Transforms/ConstProp/trunc_vec.ll new file mode 100644 index 0000000..99db329 --- /dev/null +++ b/test/Transforms/ConstProp/trunc_vec.ll @@ -0,0 +1,9 @@ +; RUN: opt -constprop < %s + +; Make sure we don't crash on this one + +define <8 x i8> @test_truc_vec() { + %x = bitcast <2 x i64> to <8 x i16> + %y = trunc <8 x i16> %x to <8 x i8> + ret <8 x i8> %y +} diff --git a/test/Transforms/CorrelatedValuePropagation/icmp.ll b/test/Transforms/CorrelatedValuePropagation/icmp.ll new file mode 100644 index 0000000..c2863ff --- /dev/null +++ b/test/Transforms/CorrelatedValuePropagation/icmp.ll @@ -0,0 +1,63 @@ +; RUN: opt -correlated-propagation -S %s | FileCheck %s + +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx10.10.0" + +; Function Attrs: noreturn +declare void @check1(i1) #1 + +; Function Attrs: noreturn +declare void @check2(i1) #1 + +; Make sure we propagate the value of %tmp35 to the true/false cases +; CHECK-LABEL: @test1 +; CHECK: call void @check1(i1 false) +; CHECK: call void @check2(i1 true) +define void @test1(i64 %tmp35) { +bb: + %tmp36 = icmp sgt i64 %tmp35, 0 + br i1 %tmp36, label %bb_true, label %bb_false + +bb_true: + %tmp47 = icmp slt i64 %tmp35, 0 + tail call void @check1(i1 %tmp47) #4 + unreachable + +bb_false: + %tmp48 = icmp sle i64 %tmp35, 0 + tail call void @check2(i1 %tmp48) #4 + unreachable +} + +; Function Attrs: noreturn +; This is the same as test1 but with a diamond to ensure we +; get %tmp36 from both true and false BBs. +; CHECK-LABEL: @test2 +; CHECK: call void @check1(i1 false) +; CHECK: call void @check2(i1 true) +define void @test2(i64 %tmp35, i1 %inner_cmp) { +bb: + %tmp36 = icmp sgt i64 %tmp35, 0 + br i1 %tmp36, label %bb_true, label %bb_false + +bb_true: + br i1 %inner_cmp, label %inner_true, label %inner_false + +inner_true: + br label %merge + +inner_false: + br label %merge + +merge: + %tmp47 = icmp slt i64 %tmp35, 0 + tail call void @check1(i1 %tmp47) #0 + unreachable + +bb_false: + %tmp48 = icmp sle i64 %tmp35, 0 + tail call void @check2(i1 %tmp48) #4 + unreachable +} + +attributes #4 = { noreturn } diff --git a/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll b/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll index 26982db..dd283ae 100644 --- a/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll +++ b/test/Transforms/DeadArgElim/2010-04-30-DbgInfo.ll @@ -4,24 +4,24 @@ define i8* @vfs_addname(i8* %name, i32 %len, i32 %hash, i32 %flags) nounwind ssp { entry: - call void @llvm.dbg.value(metadata !{i8* %name}, i64 0, metadata !0) - call void @llvm.dbg.value(metadata !{i32 %len}, i64 0, metadata !10) - call void @llvm.dbg.value(metadata !{i32 %hash}, i64 0, metadata !11) - call void @llvm.dbg.value(metadata !{i32 %flags}, i64 0, metadata !12) + call void @llvm.dbg.value(metadata i8* %name, i64 0, metadata !0, metadata !{}) + call void @llvm.dbg.value(metadata i32 %len, i64 0, metadata !10, metadata !{}) + call void @llvm.dbg.value(metadata i32 %hash, i64 0, metadata !11, metadata !{}) + call void @llvm.dbg.value(metadata i32 %flags, i64 0, metadata !12, metadata !{}) ; CHECK: call fastcc i8* @add_name_internal(i8* %name, i32 %hash) [[NUW:#[0-9]+]], !dbg !{{[0-9]+}} %0 = call fastcc i8* @add_name_internal(i8* %name, i32 %len, i32 %hash, i8 zeroext 0, i32 %flags) nounwind, !dbg !13 ; [#uses=1] ret i8* %0, !dbg !13 } -declare void @llvm.dbg.declare(metadata, metadata) nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone define internal fastcc i8* @add_name_internal(i8* %name, i32 %len, i32 %hash, i8 zeroext %extra, i32 %flags) noinline nounwind ssp { entry: - call void @llvm.dbg.value(metadata !{i8* %name}, i64 0, metadata !15) - call void @llvm.dbg.value(metadata !{i32 %len}, i64 0, metadata !20) - call void @llvm.dbg.value(metadata !{i32 %hash}, i64 0, metadata !21) - call void @llvm.dbg.value(metadata !{i8 %extra}, i64 0, metadata !22) - call void @llvm.dbg.value(metadata !{i32 %flags}, i64 0, metadata !23) + call void @llvm.dbg.value(metadata i8* %name, i64 0, metadata !15, metadata !{}) + call void @llvm.dbg.value(metadata i32 %len, i64 0, metadata !20, metadata !{}) + call void @llvm.dbg.value(metadata i32 %hash, i64 0, metadata !21, metadata !{}) + call void @llvm.dbg.value(metadata i8 %extra, i64 0, metadata !22, metadata !{}) + call void @llvm.dbg.value(metadata i32 %flags, i64 0, metadata !23, metadata !{}) %0 = icmp eq i32 %hash, 0, !dbg !24 ; [#uses=1] br i1 %0, label %bb, label %bb1, !dbg !24 @@ -36,7 +36,7 @@ bb2: ; preds = %bb1, %bb ret i8* %.0, !dbg !27 } -declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) nounwind readnone ; CHECK: attributes #0 = { nounwind ssp } ; CHECK: attributes #1 = { nounwind readnone } @@ -45,34 +45,34 @@ declare void @llvm.dbg.value(metadata, i64, metadata) nounwind readnone !llvm.dbg.cu = !{!3} !llvm.module.flags = !{!30} -!0 = metadata !{i32 524545, metadata !1, metadata !"name", metadata !2, i32 8, metadata !6} ; [ DW_TAG_arg_variable ] -!1 = metadata !{i32 524334, metadata !28, metadata !2, metadata !"vfs_addname", metadata !"vfs_addname", metadata !"vfs_addname", i32 12, metadata !4, i1 false, i1 true, i32 0, i32 0, null, i1 false, i32 0, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!2 = metadata !{i32 524329, metadata !28} ; [ DW_TAG_file_type ] -!3 = metadata !{i32 524305, metadata !28, i32 1, metadata !"4.2.1 (Based on Apple Inc. build 5658) (LLVM build 9999)", i1 true, metadata !"", i32 0, metadata !29, metadata !29, null, null, null, metadata !""} ; [ DW_TAG_compile_unit ] -!4 = metadata !{i32 524309, metadata !28, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !5, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!5 = metadata !{metadata !6, metadata !6, metadata !9, metadata !9, metadata !9} -!6 = metadata !{i32 524303, metadata !28, metadata !2, metadata !"", i32 0, i64 64, i64 64, i64 0, i32 0, metadata !7} ; [ DW_TAG_pointer_type ] -!7 = metadata !{i32 524326, metadata !28, metadata !2, metadata !"", i32 0, i64 8, i64 8, i64 0, i32 0, metadata !8} ; [ DW_TAG_const_type ] -!8 = metadata !{i32 524324, metadata !28, metadata !2, metadata !"char", i32 0, i64 8, i64 8, i64 0, i32 0, i32 6} ; [ DW_TAG_base_type ] -!9 = metadata !{i32 524324, metadata !28, metadata !2, metadata !"unsigned int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 7} ; [ DW_TAG_base_type ] -!10 = metadata !{i32 524545, metadata !1, metadata !"len", metadata !2, i32 9, metadata !9} ; [ DW_TAG_arg_variable ] -!11 = metadata !{i32 524545, metadata !1, metadata !"hash", metadata !2, i32 10, metadata !9} ; [ DW_TAG_arg_variable ] -!12 = metadata !{i32 524545, metadata !1, metadata !"flags", metadata !2, i32 11, metadata !9} ; [ DW_TAG_arg_variable ] -!13 = metadata !{i32 13, i32 0, metadata !14, null} -!14 = metadata !{i32 524299, metadata !28, metadata !1, i32 12, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!15 = metadata !{i32 524545, metadata !16, metadata !"name", metadata !2, i32 17, metadata !6} ; [ DW_TAG_arg_variable ] -!16 = metadata !{i32 524334, metadata !28, metadata !2, metadata !"add_name_internal", metadata !"add_name_internal", metadata !"add_name_internal", i32 22, metadata !17, i1 true, i1 true, i32 0, i32 0, null, i1 false, i32 0, null, null, null, null, i32 0} ; [ DW_TAG_subprogram ] -!17 = metadata !{i32 524309, metadata !28, metadata !2, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !18, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!18 = metadata !{metadata !6, metadata !6, metadata !9, metadata !9, metadata !19, metadata !9} -!19 = metadata !{i32 524324, metadata !28, metadata !2, metadata !"unsigned char", i32 0, i64 8, i64 8, i64 0, i32 0, i32 8} ; [ DW_TAG_base_type ] -!20 = metadata !{i32 524545, metadata !16, metadata !"len", metadata !2, i32 18, metadata !9} ; [ DW_TAG_arg_variable ] -!21 = metadata !{i32 524545, metadata !16, metadata !"hash", metadata !2, i32 19, metadata !9} ; [ DW_TAG_arg_variable ] -!22 = metadata !{i32 524545, metadata !16, metadata !"extra", metadata !2, i32 20, metadata !19} ; [ DW_TAG_arg_variable ] -!23 = metadata !{i32 524545, metadata !16, metadata !"flags", metadata !2, i32 21, metadata !9} ; [ DW_TAG_arg_variable ] -!24 = metadata !{i32 23, i32 0, metadata !25, null} -!25 = metadata !{i32 524299, metadata !28, metadata !16, i32 22, i32 0, i32 0} ; [ DW_TAG_lexical_block ] -!26 = metadata !{i32 24, i32 0, metadata !25, null} -!27 = metadata !{i32 26, i32 0, metadata !25, null} -!28 = metadata !{metadata !"tail.c", metadata !"/Users/echeng/LLVM/radars/r7927803/"} -!29 = metadata !{i32 0} -!30 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x101\00name\008\000", !1, !2, !6} ; [ DW_TAG_arg_variable ] +!1 = !{!"0x2e\00vfs_addname\00vfs_addname\00vfs_addname\0012\000\001\000\006\000\000\000", !28, !2, !4, null, null, null, null, null} ; [ DW_TAG_subprogram ] +!2 = !{!"0x29", !28} ; [ DW_TAG_file_type ] +!3 = !{!"0x11\001\004.2.1 (Based on Apple Inc. build 5658) (LLVM build 9999)\001\00\000\00\000", !28, !29, !29, null, null, null} ; [ DW_TAG_compile_unit ] +!4 = !{!"0x15\00\000\000\000\000\000\000", !28, !2, null, !5, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!5 = !{!6, !6, !9, !9, !9} +!6 = !{!"0xf\00\000\0064\0064\000\000", !28, !2, !7} ; [ DW_TAG_pointer_type ] +!7 = !{!"0x26\00\000\008\008\000\000", !28, !2, !8} ; [ DW_TAG_const_type ] +!8 = !{!"0x24\00char\000\008\008\000\000\006", !28, !2} ; [ DW_TAG_base_type ] +!9 = !{!"0x24\00unsigned int\000\0032\0032\000\000\007", !28, !2} ; [ DW_TAG_base_type ] +!10 = !{!"0x101\00len\009\000", !1, !2, !9} ; [ DW_TAG_arg_variable ] +!11 = !{!"0x101\00hash\0010\000", !1, !2, !9} ; [ DW_TAG_arg_variable ] +!12 = !{!"0x101\00flags\0011\000", !1, !2, !9} ; [ DW_TAG_arg_variable ] +!13 = !MDLocation(line: 13, scope: !14) +!14 = !{!"0xb\0012\000\000", !28, !1} ; [ DW_TAG_lexical_block ] +!15 = !{!"0x101\00name\0017\000", !16, !2, !6} ; [ DW_TAG_arg_variable ] +!16 = !{!"0x2e\00add_name_internal\00add_name_internal\00add_name_internal\0022\001\001\000\006\000\000\000", !28, !2, !17, null, null, null, null, null} ; [ DW_TAG_subprogram ] +!17 = !{!"0x15\00\000\000\000\000\000\000", !28, !2, null, !18, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!18 = !{!6, !6, !9, !9, !19, !9} +!19 = !{!"0x24\00unsigned char\000\008\008\000\000\008", !28, !2} ; [ DW_TAG_base_type ] +!20 = !{!"0x101\00len\0018\000", !16, !2, !9} ; [ DW_TAG_arg_variable ] +!21 = !{!"0x101\00hash\0019\000", !16, !2, !9} ; [ DW_TAG_arg_variable ] +!22 = !{!"0x101\00extra\0020\000", !16, !2, !19} ; [ DW_TAG_arg_variable ] +!23 = !{!"0x101\00flags\0021\000", !16, !2, !9} ; [ DW_TAG_arg_variable ] +!24 = !MDLocation(line: 23, scope: !25) +!25 = !{!"0xb\0022\000\000", !28, !16} ; [ DW_TAG_lexical_block ] +!26 = !MDLocation(line: 24, scope: !25) +!27 = !MDLocation(line: 26, scope: !25) +!28 = !{!"tail.c", !"/Users/echeng/LLVM/radars/r7927803/"} +!29 = !{i32 0} +!30 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/DeadArgElim/dbginfo.ll b/test/Transforms/DeadArgElim/dbginfo.ll index 7bdcbf5..5bbf821 100644 --- a/test/Transforms/DeadArgElim/dbginfo.ll +++ b/test/Transforms/DeadArgElim/dbginfo.ll @@ -1,65 +1,70 @@ ; RUN: opt -deadargelim -S < %s | FileCheck %s ; PR14016 -; Check that debug info metadata for subprograms stores pointers to -; updated LLVM functions. +; Built with clang (then manually running -mem2reg with opt) from the following source: +; static void f1(int, ...) { +; } +; +; void f2() { +; f1(1); +; } -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" +; Test both varargs removal and removal of a traditional dead arg together, to +; test both the basic functionality, and a particular wrinkle involving updating +; the function->debug info mapping on update to ensure it's accurate when used +; again for the next removal. -@x = global i32 0, align 4 +; CHECK: void ()* @_ZL2f1iz, {{.*}} ; [ DW_TAG_subprogram ] {{.*}} [f1] -define void @_Z3runv() uwtable { -entry: - call void @_ZN12_GLOBAL__N_18dead_argEPv(i8* null), !dbg !10 - call void (...)* @_ZN12_GLOBAL__N_111dead_varargEz(), !dbg !12 - ret void, !dbg !13 -} +; Check that debug info metadata for subprograms stores pointers to +; updated LLVM functions. -; Argument will be deleted -define internal void @_ZN12_GLOBAL__N_18dead_argEPv(i8* %foo) nounwind uwtable { +; Function Attrs: uwtable +define void @_Z2f2v() #0 { entry: - %0 = load i32* @x, align 4, !dbg !14 - %inc = add nsw i32 %0, 1, !dbg !14 - store i32 %inc, i32* @x, align 4, !dbg !14 + call void (i32, ...)* @_ZL2f1iz(i32 1), !dbg !15 ret void, !dbg !16 } -; Vararg will be deleted -define internal void @_ZN12_GLOBAL__N_111dead_varargEz(...) nounwind uwtable { +; Function Attrs: nounwind uwtable +define internal void @_ZL2f1iz(i32, ...) #1 { entry: - %0 = load i32* @x, align 4, !dbg !17 - %inc = add nsw i32 %0, 1, !dbg !17 - store i32 %inc, i32* @x, align 4, !dbg !17 - ret void, !dbg !19 + call void @llvm.dbg.value(metadata i32 %0, i64 0, metadata !17, metadata !18), !dbg !19 + ret void, !dbg !20 } -!llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!21} - -!0 = metadata !{i32 786449, metadata !20, i32 4, metadata !"clang version 3.2 (trunk 165305)", i1 false, metadata !"", i32 0, metadata !1, metadata !1, metadata !3, metadata !1, metadata !1, metadata !""} ; [ DW_TAG_compile_unit ] [/home/samsonov/tmp/clang-di/test.cc] [DW_LANG_C_plus_plus] -!1 = metadata !{i32 0} -!3 = metadata !{metadata !5, metadata !8, metadata !9} -!5 = metadata !{i32 786478, metadata !20, metadata !6, metadata !"run", metadata !"run", metadata !"", i32 8, metadata !7, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, void ()* @_Z3runv, null, null, metadata !1, i32 8} ; [ DW_TAG_subprogram ] [line 8] [def] [run] -!6 = metadata !{i32 786473, metadata !20} ; [ DW_TAG_file_type ] -!7 = metadata !{i32 786453, i32 0, null, i32 0, i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !1, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!8 = metadata !{i32 786478, metadata !20, metadata !6, metadata !"dead_vararg", metadata !"dead_vararg", metadata !"", i32 5, metadata !7, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (...)* @_ZN12_GLOBAL__N_111dead_varargEz, null, null, metadata !1, i32 5} ; [ DW_TAG_subprogram ] [line 5] [local] [def] [dead_vararg] +; Function Attrs: nounwind readnone +declare void @llvm.dbg.declare(metadata, metadata, metadata) #2 -; CHECK: metadata !"dead_vararg"{{.*}}void ()* @_ZN12_GLOBAL__N_111dead_varargEz +; Function Attrs: nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2 -!9 = metadata !{i32 786478, metadata !20, metadata !6, metadata !"dead_arg", metadata !"dead_arg", metadata !"", i32 4, metadata !7, i1 true, i1 true, i32 0, i32 0, null, i32 256, i1 false, void (i8*)* @_ZN12_GLOBAL__N_18dead_argEPv, null, null, metadata !1, i32 4} ; [ DW_TAG_subprogram ] [line 4] [local] [def] [dead_arg] +attributes #0 = { uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone } -; CHECK: metadata !"dead_arg"{{.*}}void ()* @_ZN12_GLOBAL__N_18dead_argEPv +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!12, !13} +!llvm.ident = !{!14} -!10 = metadata !{i32 8, i32 14, metadata !11, null} -!11 = metadata !{i32 786443, metadata !20, metadata !5, i32 8, i32 12, i32 0} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc] -!12 = metadata !{i32 8, i32 27, metadata !11, null} -!13 = metadata !{i32 8, i32 42, metadata !11, null} -!14 = metadata !{i32 4, i32 28, metadata !15, null} -!15 = metadata !{i32 786443, metadata !20, metadata !9, i32 4, i32 26, i32 2} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc] -!16 = metadata !{i32 4, i32 33, metadata !15, null} -!17 = metadata !{i32 5, i32 25, metadata !18, null} -!18 = metadata !{i32 786443, metadata !20, metadata !8, i32 5, i32 23, i32 1} ; [ DW_TAG_lexical_block ] [/home/samsonov/tmp/clang-di/test.cc] -!19 = metadata !{i32 5, i32 30, metadata !18, null} -!20 = metadata !{metadata !"test.cc", metadata !"/home/samsonov/tmp/clang-di"} -!21 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!0 = !{!"0x11\004\00clang version 3.6.0 \000\00\000\00\001", !1, !2, !2, !3, !2, !2} ; [ DW_TAG_compile_unit ] [/tmp/dbginfo/dbg.cpp] [DW_LANG_C_plus_plus] +!1 = !{!"dbg.cpp", !"/tmp/dbginfo"} +!2 = !{} +!3 = !{!4, !8} +!4 = !{!"0x2e\00f2\00f2\00_Z2f2v\004\000\001\000\000\00256\000\004", !1, !5, !6, null, void ()* @_Z2f2v, null, null, !2} ; [ DW_TAG_subprogram ] [line 4] [def] [f2] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/tmp/dbginfo/dbg.cpp] +!6 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{null} +!8 = !{!"0x2e\00f1\00f1\00_ZL2f1iz\001\001\001\000\000\00256\000\001", !1, !5, !9, null, void (i32, ...)* @_ZL2f1iz, null, null, !2} ; [ DW_TAG_subprogram ] [line 1] [local] [def] [f1] +!9 = !{!"0x15\00\000\000\000\000\000\000", null, null, null, !10, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!10 = !{null, !11, null} +!11 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!12 = !{i32 2, !"Dwarf Version", i32 4} +!13 = !{i32 2, !"Debug Info Version", i32 2} +!14 = !{!"clang version 3.6.0 "} +!15 = !MDLocation(line: 5, column: 3, scope: !4) +!16 = !MDLocation(line: 6, column: 1, scope: !4) +!17 = !{!"0x101\00\0016777217\000", !8, !5, !11} ; [ DW_TAG_arg_variable ] [line 1] +!18 = !{!"0x102"} ; [ DW_TAG_expression ] +!19 = !MDLocation(line: 1, column: 19, scope: !8) +!20 = !MDLocation(line: 2, column: 1, scope: !8) diff --git a/test/Transforms/DeadArgElim/dead_vaargs.ll b/test/Transforms/DeadArgElim/dead_vaargs.ll index db3135c..c8189c6 100644 --- a/test/Transforms/DeadArgElim/dead_vaargs.ll +++ b/test/Transforms/DeadArgElim/dead_vaargs.ll @@ -1,12 +1,36 @@ -; RUN: opt < %s -deadargelim -S | not grep 47 -; RUN: opt < %s -deadargelim -S | not grep 1.0 +; RUN: opt < %s -deadargelim -S | FileCheck %s define i32 @bar(i32 %A) { - %tmp4 = tail call i32 (i32, ...)* @foo( i32 %A, i32 %A, i32 %A, i32 %A, i64 47, double 1.000000e+00 ) ; [#uses=1] - ret i32 %tmp4 + call void (i32, ...)* @thunk(i32 %A, i64 47, double 1.000000e+00) + %a = call i32 (i32, ...)* @has_vastart(i32 %A, i64 47, double 1.000000e+00) + %b = call i32 (i32, ...)* @no_vastart( i32 %A, i32 %A, i32 %A, i32 %A, i64 47, double 1.000000e+00 ) + %c = add i32 %a, %b + ret i32 %c } +; CHECK-LABEL: define i32 @bar +; CHECK: call void (i32, ...)* @thunk(i32 %A, i64 47, double 1.000000e+00) +; CHECK: call i32 (i32, ...)* @has_vastart(i32 %A, i64 47, double 1.000000e+00) +; CHECK: call i32 @no_vastart(i32 %A) -define internal i32 @foo(i32 %X, ...) { - ret i32 %X +declare void @thunk_target(i32 %X, ...) + +define internal void @thunk(i32 %X, ...) { + musttail call void(i32, ...)* @thunk_target(i32 %X, ...) + ret void +} +; CHECK-LABEL: define internal void @thunk(i32 %X, ...) +; CHECK: musttail call void (i32, ...)* @thunk_target(i32 %X, ...) + +define internal i32 @has_vastart(i32 %X, ...) { + %valist = alloca i8 + call void @llvm.va_start(i8* %valist) + ret i32 %X } +; CHECK-LABEL: define internal i32 @has_vastart(i32 %X, ...) +declare void @llvm.va_start(i8*) + +define internal i32 @no_vastart(i32 %X, ...) { + ret i32 %X +} +; CHECK-LABEL: define internal i32 @no_vastart(i32 %X) diff --git a/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll b/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll index 079eec4..39d5358 100644 --- a/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll +++ b/test/Transforms/DeadStoreElimination/2011-03-25-DSEMiscompile.ll @@ -5,9 +5,9 @@ target triple = "i386-apple-darwin9.8" @A = external global [0 x i32] -declare cc10 void @Func2(i32*, i32*, i32*, i32) +declare ghccc void @Func2(i32*, i32*, i32*, i32) -define cc10 void @Func1(i32* noalias %Arg1, i32* noalias %Arg2, i32* %Arg3, i32 %Arg4) { +define ghccc void @Func1(i32* noalias %Arg1, i32* noalias %Arg2, i32* %Arg3, i32 %Arg4) { entry: store i32 add (i32 ptrtoint ([0 x i32]* @A to i32), i32 1), i32* %Arg2 ; CHECK: store i32 add (i32 ptrtoint ([0 x i32]* @A to i32), i32 1), i32* %Arg2 @@ -18,6 +18,6 @@ entry: %ln2gE = bitcast i32* %ln2gD to double* store double %ln2gB, double* %ln2gE ; CHECK: store double %ln2gB, double* %ln2gE - tail call cc10 void @Func2(i32* %Arg1, i32* %Arg2, i32* %Arg3, i32 %Arg4) nounwind + tail call ghccc void @Func2(i32* %Arg1, i32* %Arg2, i32* %Arg3, i32 %Arg4) nounwind ret void } diff --git a/test/Transforms/DeadStoreElimination/atomic.ll b/test/Transforms/DeadStoreElimination/atomic.ll index 2e84298..af303fa 100644 --- a/test/Transforms/DeadStoreElimination/atomic.ll +++ b/test/Transforms/DeadStoreElimination/atomic.ll @@ -5,7 +5,7 @@ target triple = "x86_64-apple-macosx10.7.0" ; Sanity tests for atomic stores. ; Note that it turns out essentially every transformation DSE does is legal on -; atomic ops, just some transformations are not allowed across them. +; atomic ops, just some transformations are not allowed across release-acquire pairs. @x = common global i32 0, align 4 @y = common global i32 0, align 4 @@ -13,35 +13,32 @@ target triple = "x86_64-apple-macosx10.7.0" declare void @randomop(i32*) ; DSE across unordered store (allowed) -define void @test1() nounwind uwtable ssp { -; CHECK: test1 +define void @test1() { +; CHECK-LABEL: test1 ; CHECK-NOT: store i32 0 ; CHECK: store i32 1 -entry: store i32 0, i32* @x store atomic i32 0, i32* @y unordered, align 4 store i32 1, i32* @x ret void } -; DSE across seq_cst load (allowed in theory; not implemented ATM) -define i32 @test2() nounwind uwtable ssp { -; CHECK: test2 -; CHECK: store i32 0 +; DSE across seq_cst load (allowed) +define i32 @test2() { +; CHECK-LABEL: test2 +; CHECK-NOT: store i32 0 ; CHECK: store i32 1 -entry: store i32 0, i32* @x %x = load atomic i32* @y seq_cst, align 4 store i32 1, i32* @x ret i32 %x } -; DSE across seq_cst store (store before atomic store must not be removed) -define void @test3() nounwind uwtable ssp { -; CHECK: test3 -; CHECK: store i32 +; DSE across seq_cst store (allowed) +define void @test3() { +; CHECK-LABEL: test3 +; CHECK-NOT: store i32 0 ; CHECK: store atomic i32 2 -entry: store i32 0, i32* @x store atomic i32 2, i32* @y seq_cst, align 4 store i32 1, i32* @x @@ -49,32 +46,29 @@ entry: } ; DSE remove unordered store (allowed) -define void @test4() nounwind uwtable ssp { -; CHECK: test4 +define void @test4() { +; CHECK-LABEL: test4 ; CHECK-NOT: store atomic ; CHECK: store i32 1 -entry: store atomic i32 0, i32* @x unordered, align 4 store i32 1, i32* @x ret void } ; DSE unordered store overwriting non-atomic store (allowed) -define void @test5() nounwind uwtable ssp { -; CHECK: test5 +define void @test5() { +; CHECK-LABEL: test5 ; CHECK: store atomic i32 1 -entry: store i32 0, i32* @x store atomic i32 1, i32* @x unordered, align 4 ret void } ; DSE no-op unordered atomic store (allowed) -define void @test6() nounwind uwtable ssp { -; CHECK: test6 +define void @test6() { +; CHECK-LABEL: test6 ; CHECK-NOT: store ; CHECK: ret void -entry: %x = load atomic i32* @x unordered, align 4 store atomic i32 %x, i32* @x unordered, align 4 ret void @@ -82,10 +76,9 @@ entry: ; DSE seq_cst store (be conservative; DSE doesn't have infrastructure ; to reason about atomic operations). -define void @test7() nounwind uwtable ssp { -; CHECK: test7 -; CHECK: store atomic -entry: +define void @test7() { +; CHECK-LABEL: test7 +; CHECK: store atomic %a = alloca i32 store atomic i32 0, i32* %a seq_cst, align 4 ret void @@ -93,11 +86,10 @@ entry: ; DSE and seq_cst load (be conservative; DSE doesn't have infrastructure ; to reason about atomic operations). -define i32 @test8() nounwind uwtable ssp { -; CHECK: test8 +define i32 @test8() { +; CHECK-LABEL: test8 ; CHECK: store -; CHECK: load atomic -entry: +; CHECK: load atomic %a = alloca i32 call void @randomop(i32* %a) store i32 0, i32* %a, align 4 @@ -105,3 +97,82 @@ entry: ret i32 %x } +; DSE across monotonic load (allowed as long as the eliminated store isUnordered) +define i32 @test9() { +; CHECK-LABEL: test9 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + %x = load atomic i32* @y monotonic, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; DSE across monotonic store (allowed as long as the eliminated store isUnordered) +define void @test10() { +; CHECK-LABEL: test10 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + store atomic i32 42, i32* @y monotonic, align 4 + store i32 1, i32* @x + ret void +} + +; DSE across monotonic load (forbidden since the eliminated store is atomic) +define i32 @test11() { +; CHECK-LABEL: test11 +; CHECK: store atomic i32 0 +; CHECK: store atomic i32 1 + store atomic i32 0, i32* @x monotonic, align 4 + %x = load atomic i32* @y monotonic, align 4 + store atomic i32 1, i32* @x monotonic, align 4 + ret i32 %x +} + +; DSE across monotonic store (forbidden since the eliminated store is atomic) +define void @test12() { +; CHECK-LABEL: test12 +; CHECK: store atomic i32 0 +; CHECK: store atomic i32 1 + store atomic i32 0, i32* @x monotonic, align 4 + store atomic i32 42, i32* @y monotonic, align 4 + store atomic i32 1, i32* @x monotonic, align 4 + ret void +} + +; DSE is allowed across a pair of an atomic read and then write. +define i32 @test13() { +; CHECK-LABEL: test13 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + %x = load atomic i32* @y seq_cst, align 4 + store atomic i32 %x, i32* @y seq_cst, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; Same if it is acquire-release instead of seq_cst/seq_cst +define i32 @test14() { +; CHECK-LABEL: test14 +; CHECK-NOT: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + %x = load atomic i32* @y acquire, align 4 + store atomic i32 %x, i32* @y release, align 4 + store i32 1, i32* @x + ret i32 %x +} + +; But DSE is not allowed across a release-acquire pair. +define i32 @test15() { +; CHECK-LABEL: test15 +; CHECK: store i32 0 +; CHECK: store i32 1 + store i32 0, i32* @x + store atomic i32 0, i32* @y release, align 4 + %x = load atomic i32* @y acquire, align 4 + store i32 1, i32* @x + ret i32 %x +} diff --git a/test/Transforms/DeadStoreElimination/const-pointers.ll b/test/Transforms/DeadStoreElimination/const-pointers.ll index c90d824..3e772d7 100644 --- a/test/Transforms/DeadStoreElimination/const-pointers.ll +++ b/test/Transforms/DeadStoreElimination/const-pointers.ll @@ -1,4 +1,5 @@ ; RUN: opt -basicaa -dse -S < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" %t = type { i32 } diff --git a/test/Transforms/DeadStoreElimination/inst-limits.ll b/test/Transforms/DeadStoreElimination/inst-limits.ll index 9df8801..3ef5607 100644 --- a/test/Transforms/DeadStoreElimination/inst-limits.ll +++ b/test/Transforms/DeadStoreElimination/inst-limits.ll @@ -1,4 +1,5 @@ ; RUN: opt -S -dse < %s | FileCheck %s +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" ; If there are two stores to the same location, DSE should be able to remove ; the first store if the two stores are separated by no more than 98 @@ -117,7 +118,7 @@ entry: ; Insert a meaningless dbg.value intrinsic; it should have no ; effect on the working of DSE in any way. - call void @llvm.dbg.value(metadata !12, i64 0, metadata !10) + call void @llvm.dbg.value(metadata i32* undef, i64 0, metadata !10, metadata !{}) ; CHECK: store i32 -1, i32* @x, align 4 store i32 -1, i32* @x, align 4 @@ -239,23 +240,23 @@ entry: } ; Function Attrs: nounwind readnone -declare void @llvm.dbg.value(metadata, i64, metadata) +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) !llvm.dbg.cu = !{!0} !llvm.module.flags = !{!11, !13} -!0 = metadata !{i32 786449, metadata !1, i32 4, metadata !"clang version 3.4", i1 true, metadata !"", i32 0, metadata !2, metadata !2, metadata !3, metadata !9, metadata !2, metadata !""} ; [ DW_TAG_compile_unit ] [/home/tmp/test.c] [DW_LANG_C99] -!1 = metadata !{metadata !"test.c", metadata !"/home/tmp"} -!2 = metadata !{i32 0} -!3 = metadata !{metadata !4} -!4 = metadata !{i32 786478, metadata !1, metadata !5, metadata !"test_within_limit", metadata !"test_within_limit", metadata !"", i32 3, metadata !6, i1 false, i1 true, i32 0, i32 0, null, i32 256, i1 false, i32 ()* @test_within_limit, null, null, metadata !2, i32 4} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 4] [test] -!5 = metadata !{i32 786473, metadata !1} ; [ DW_TAG_file_type ] [/home/tmp/test.c] -!6 = metadata !{i32 786453, i32 0, null, metadata !"", i32 0, i64 0, i64 0, i64 0, i32 0, null, metadata !7, i32 0, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] -!7 = metadata !{metadata !8} -!8 = metadata !{i32 786468, null, null, metadata !"int", i32 0, i64 32, i64 32, i64 0, i32 0, i32 5} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] -!9 = metadata !{metadata !10} -!10 = metadata !{i32 786484, i32 0, null, metadata !"x", metadata !"x", metadata !"", metadata !5, i32 1, metadata !8, i32 0, i32 1, i32* @x, null} ; [ DW_TAG_variable ] [x] [line 1] [def] -!11 = metadata !{i32 2, metadata !"Dwarf Version", i32 4} -!12 = metadata !{i32* undef} +!0 = !{!"0x11\004\00clang version 3.4\001\00\000\00\000", !1, !2, !2, !3, !9, !2} ; [ DW_TAG_compile_unit ] [/home/tmp/test.c] [DW_LANG_C99] +!1 = !{!"test.c", !"/home/tmp"} +!2 = !{i32 0} +!3 = !{!4} +!4 = !{!"0x2e\00test_within_limit\00test_within_limit\00\003\000\001\000\006\00256\000\004", !1, !5, !6, null, i32 ()* @test_within_limit, null, null, !2} ; [ DW_TAG_subprogram ] [line 3] [def] [scope 4] [test] +!5 = !{!"0x29", !1} ; [ DW_TAG_file_type ] [/home/tmp/test.c] +!6 = !{!"0x15\00\000\000\000\000\000\000", i32 0, null, null, !7, null, null, null} ; [ DW_TAG_subroutine_type ] [line 0, size 0, align 0, offset 0] [from ] +!7 = !{!8} +!8 = !{!"0x24\00int\000\0032\0032\000\000\005", null, null} ; [ DW_TAG_base_type ] [int] [line 0, size 32, align 32, offset 0, enc DW_ATE_signed] +!9 = !{!10} +!10 = !{!"0x34\00x\00x\00\001\000\001", null, !5, !8, i32* @x, null} ; [ DW_TAG_variable ] [x] [line 1] [def] +!11 = !{i32 2, !"Dwarf Version", i32 4} +!12 = !{i32* undef} -!13 = metadata !{i32 1, metadata !"Debug Info Version", i32 1} +!13 = !{i32 1, !"Debug Info Version", i32 2} diff --git a/test/Transforms/DeadStoreElimination/no-targetdata.ll b/test/Transforms/DeadStoreElimination/no-targetdata.ll index c0c7c58..2539533 100644 --- a/test/Transforms/DeadStoreElimination/no-targetdata.ll +++ b/test/Transforms/DeadStoreElimination/no-targetdata.ll @@ -1,15 +1,21 @@ ; RUN: opt -basicaa -dse -S < %s | FileCheck %s -declare void @test1f() - -define void @test1(i32* noalias %p) { - store i32 1, i32* %p - call void @test1f() - store i32 2, i32 *%p - ret void -; CHECK-LABEL: define void @test1( -; CHECK-NOT: store -; CHECK-NEXT: call void -; CHECK-NEXT: store i32 2 -; CHECK-NEXT: ret void +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i32, i1) nounwind + +define void @fn(i8* nocapture %buf) #0 { +entry: + +; We would not eliminate the first memcpy with data layout, and we should not +; eliminate it without data layout. +; CHECK-LABEL: @fn +; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64 +; CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64 +; CHECK: ret void + + %arrayidx = getelementptr i8* %buf, i64 18 + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %arrayidx, i8* %buf, i64 18, i32 1, i1 false) + store i8 1, i8* %arrayidx, align 1 + tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* %buf, i8* %arrayidx, i64 18, i32 1, i1 false) + ret void } + diff --git a/test/Transforms/DebugIR/crash.ll b/test/Transforms/DebugIR/crash.ll deleted file mode 100644 index f4a88d7..0000000 --- a/test/Transforms/DebugIR/crash.ll +++ /dev/null @@ -1,42 +0,0 @@ -; ModuleID = 'crash.c' -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-pc-linux-gnu" - -@.str = private unnamed_addr constant [18 x i8] c"Hello, segfault!\0A\00", align 1 -@.str1 = private unnamed_addr constant [14 x i8] c"Now crash %d\0A\00", align 1 - -; Function Attrs: nounwind uwtable -define i32 @main(i32 %argc, i8** %argv) #0 { - %1 = alloca i32, align 4 ;CHECK: !dbg - %2 = alloca i32, align 4 ;CHECK-NEXT: !dbg - %3 = alloca i8**, align 8 ;CHECK-NEXT: !dbg - %null_ptr = alloca i32*, align 8 ;CHECK-NEXT: !dbg - store i32 0, i32* %1 ;CHECK-NEXT: !dbg - store i32 %argc, i32* %2, align 4 ;CHECK-NEXT: !dbg - store i8** %argv, i8*** %3, align 8 ;CHECK-NEXT: !dbg - store i32* null, i32** %null_ptr, align 8 ;CHECK-NEXT: !dbg - %4 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([18 x i8]* @.str, i32 0, i32 0)) ;CHECK-NEXT: !dbg - %5 = load i32** %null_ptr, align 8 ;CHECK-NEXT: !dbg - %6 = load i32* %5, align 4 ;CHECK-NEXT: !dbg - %7 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str1, i32 0, i32 0), i32 %6) ;CHECK-NEXT: !dbg - %8 = load i32* %2, align 4 ;CHECK-NEXT: !dbg - ret i32 %8 ;CHECK-NEXT: !dbg -} - -declare i32 @printf(i8*, ...) #1 - -attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } -attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"="true" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "unsafe-fp-math"="false" "use-soft-float"="false" } - -; CHECK: = metadata !{i32 14, -; CHECK-NEXT: = metadata !{i32 15, -; CHECK-NEXT: = metadata !{i32 16, -; CHECK-NEXT: = metadata !{i32 17, -; CHECK-NEXT: = metadata !{i32 18, -; CHECK-NEXT: = metadata !{i32 19, -; CHECK-NEXT: = metadata !{i32 20, -; CHECK-NEXT: = metadata !{i32 21, -; CHECK-NEXT: = metadata !{i32 22, -; CHECK-NEXT: = metadata !{i32 23, - -; RUN: opt %s -debug-ir -S | FileCheck %s diff --git a/test/Transforms/DebugIR/exception.ll b/test/Transforms/DebugIR/exception.ll deleted file mode 100644 index 2436d38..0000000 --- a/test/Transforms/DebugIR/exception.ll +++ /dev/null @@ -1,127 +0,0 @@ -; ModuleID = 'exception.cpp' -target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" -target triple = "x86_64-pc-linux-gnu" - -@_ZTIi = external constant i8* - -; Function Attrs: uwtable -define i32 @main(i32 %argc, i8** %argv) #0 { - %1 = alloca i32, align 4 ; CHECK: !dbg - %2 = alloca i32, align 4 ; CHECK-NEXT: !dbg - %3 = alloca i8**, align 8 ; CHECK-NEXT: !dbg - %4 = alloca i8* ; CHECK-NEXT: !dbg - %5 = alloca i32 ; CHECK-NEXT: !dbg - %e = alloca i32, align 4 ; CHECK-NEXT: !dbg - %6 = alloca i32 ; CHECK-NEXT: !dbg - store i32 0, i32* %1 ; CHECK-NEXT: !dbg - store i32 %argc, i32* %2, align 4 ; CHECK-NEXT: !dbg - store i8** %argv, i8*** %3, align 8 ; CHECK-NEXT: !dbg - %7 = call i8* @__cxa_allocate_exception(i64 4) #2 ; CHECK-NEXT: !dbg - %8 = bitcast i8* %7 to i32* ; CHECK-NEXT: !dbg - %9 = load i32* %2, align 4 ; CHECK-NEXT: !dbg - store i32 %9, i32* %8 ; CHECK-NEXT: !dbg - invoke void @__cxa_throw(i8* %7, i8* bitcast (i8** @_ZTIi to i8*), i8* null) #3 - to label %31 unwind label %10 ; CHECK: !dbg - -; "; - // Print instructions. - for (unsigned ii = 0, ie = (*i)->getInsts()->size(); ii != ie; - ++ii) { - if (ii != 0) // Not the first line, start a new row. - Out << '|'; - if (ii + 1 == ie) // Last line, add an end id. - Out << ""; - - // Escape special chars and print the instruction in mnemonic form. - std::string Str; - raw_string_ostream OS(Str); - IP->printInst(&(*i)->getInsts()->at(ii).Inst, OS, ""); - Out << DOT::EscapeString(OS.str()); - } - Out << "\" shape=\"record\" ];\n"; - - // Add edges. - for (MCBasicBlock::succ_const_iterator si = (*i)->succ_begin(), - se = (*i)->succ_end(); si != se; ++si) - Out << (*i)->getInsts()->getBeginAddr() << ":o -> " - << (*si)->getInsts()->getBeginAddr() << ":a\n"; - } - Out << "}\n"; -} - void llvm::DumpBytes(StringRef bytes) { static const char hex_rep[] = "0123456789abcdef"; // FIXME: The real way to do this is to figure out the longest instruction @@ -303,7 +259,7 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { } std::unique_ptr STI( - TheTarget->createMCSubtargetInfo(TripleName, "", FeaturesStr)); + TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); if (!STI) { errs() << "error: no subtarget info for target " << TripleName << "\n"; return; @@ -326,19 +282,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { return; } - - if (Symbolize) { - std::unique_ptr RelInfo( - TheTarget->createMCRelocationInfo(TripleName, Ctx)); - if (RelInfo) { - std::unique_ptr Symzer( - MCObjectSymbolizer::createObjectSymbolizer(Ctx, std::move(RelInfo), - Obj)); - if (Symzer) - DisAsm->setSymbolizer(std::move(Symzer)); - } - } - std::unique_ptr MIA( TheTarget->createMCInstrAnalysis(MII.get())); @@ -351,45 +294,6 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { return; } - if (CFG || !YAMLCFG.empty()) { - std::unique_ptr OD( - new MCObjectDisassembler(*Obj, *DisAsm, *MIA)); - std::unique_ptr Mod(OD->buildModule(/* withCFG */ true)); - for (MCModule::const_atom_iterator AI = Mod->atom_begin(), - AE = Mod->atom_end(); - AI != AE; ++AI) { - outs() << "Atom " << (*AI)->getName() << ": \n"; - if (const MCTextAtom *TA = dyn_cast(*AI)) { - for (MCTextAtom::const_iterator II = TA->begin(), IE = TA->end(); - II != IE; - ++II) { - IP->printInst(&II->Inst, outs(), ""); - outs() << "\n"; - } - } - } - if (CFG) { - for (MCModule::const_func_iterator FI = Mod->func_begin(), - FE = Mod->func_end(); - FI != FE; ++FI) { - static int filenum = 0; - emitDOTFile((Twine((*FI)->getName()) + "_" + - utostr(filenum) + ".dot").str().c_str(), - **FI, IP.get()); - ++filenum; - } - } - if (!YAMLCFG.empty()) { - std::string Error; - raw_fd_ostream YAMLOut(YAMLCFG.c_str(), Error, sys::fs::F_Text); - if (!Error.empty()) { - errs() << ToolName << ": warning: " << Error << '\n'; - return; - } - mcmodule2yaml(YAMLOut, *Mod, *MII, *MRI); - } - } - StringRef Fmt = Obj->getBytesInAddress() > 4 ? "\t\t%016" PRIx64 ": " : "\t\t\t%08" PRIx64 ": "; @@ -404,25 +308,18 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { } for (const SectionRef &Section : Obj->sections()) { - bool Text; - if (error(Section.isText(Text))) - break; - if (!Text) + if (!Section.isText() || Section.isVirtual()) continue; - uint64_t SectionAddr; - if (error(Section.getAddress(SectionAddr))) - break; - - uint64_t SectSize; - if (error(Section.getSize(SectSize))) - break; + uint64_t SectionAddr = Section.getAddress(); + uint64_t SectSize = Section.getSize(); + if (!SectSize) + continue; // Make a list of all the symbols in this section. std::vector> Symbols; for (const SymbolRef &Symbol : Obj->symbols()) { - bool contains; - if (!error(Section.containsSymbol(Symbol, contains)) && contains) { + if (Section.containsSymbol(Symbol)) { uint64_t Address; if (error(Symbol.getAddress(Address))) break; @@ -477,10 +374,12 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { SmallString<40> Comments; raw_svector_ostream CommentStream(Comments); - StringRef Bytes; - if (error(Section.getContents(Bytes))) + StringRef BytesStr; + if (error(Section.getContents(BytesStr))) break; - StringRefMemoryObject memoryObject(Bytes, SectionAddr); + ArrayRef Bytes(reinterpret_cast(BytesStr.data()), + BytesStr.size()); + uint64_t Size; uint64_t Index; @@ -488,17 +387,12 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { std::vector::const_iterator rel_end = Rels.end(); // Disassemble symbol by symbol. for (unsigned si = 0, se = Symbols.size(); si != se; ++si) { + uint64_t Start = Symbols[si].first; - uint64_t End; - // The end is either the size of the section or the beginning of the next - // symbol. - if (si == se - 1) - End = SectSize; - // Make sure this symbol takes up space. - else if (Symbols[si + 1].first != Start) - End = Symbols[si + 1].first - 1; - else - // This symbol has the same address as the next symbol. Skip it. + // The end is either the section end or the beginning of the next symbol. + uint64_t End = (si == se - 1) ? SectSize : Symbols[si + 1].first; + // If this symbol has the same address as the next symbol, then skip it. + if (Start == End) continue; outs() << '\n' << Symbols[si].second << ":\n"; @@ -512,13 +406,14 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { for (Index = Start; Index < End; Index += Size) { MCInst Inst; - if (DisAsm->getInstruction(Inst, Size, memoryObject, - SectionAddr + Index, - DebugOut, CommentStream)) { + if (DisAsm->getInstruction(Inst, Size, Bytes.slice(Index), + SectionAddr + Index, DebugOut, + CommentStream)) { outs() << format("%8" PRIx64 ":", SectionAddr + Index); if (!NoShowRawInsn) { outs() << "\t"; - DumpBytes(StringRef(Bytes.data() + Index, Size)); + DumpBytes(StringRef( + reinterpret_cast(Bytes.data()) + Index, Size)); } IP->printInst(&Inst, outs(), ""); outs() << CommentStream.str(); @@ -561,6 +456,11 @@ static void DisassembleObject(const ObjectFile *Obj, bool InlineRelocs) { static void PrintRelocations(const ObjectFile *Obj) { StringRef Fmt = Obj->getBytesInAddress() > 4 ? "%016" PRIx64 : "%08" PRIx64; + // Regular objdump doesn't print relocations in non-relocatable object + // files. + if (!Obj->isRelocatableObject()) + return; + for (const SectionRef &Section : Obj->sections()) { if (Section.relocation_begin() == Section.relocation_end()) continue; @@ -598,19 +498,11 @@ static void PrintSectionHeaders(const ObjectFile *Obj) { StringRef Name; if (error(Section.getName(Name))) return; - uint64_t Address; - if (error(Section.getAddress(Address))) - return; - uint64_t Size; - if (error(Section.getSize(Size))) - return; - bool Text, Data, BSS; - if (error(Section.isText(Text))) - return; - if (error(Section.isData(Data))) - return; - if (error(Section.isBSS(BSS))) - return; + uint64_t Address = Section.getAddress(); + uint64_t Size = Section.getSize(); + bool Text = Section.isText(); + bool Data = Section.isData(); + bool BSS = Section.isBSS(); std::string Type = (std::string(Text ? "TEXT " : "") + (Data ? "DATA " : "") + (BSS ? "BSS" : "")); outs() << format("%3d %-13s %08" PRIx64 " %016" PRIx64 " %s\n", i, @@ -624,20 +516,15 @@ static void PrintSectionContents(const ObjectFile *Obj) { for (const SectionRef &Section : Obj->sections()) { StringRef Name; StringRef Contents; - uint64_t BaseAddr; - bool BSS; if (error(Section.getName(Name))) continue; - if (error(Section.getAddress(BaseAddr))) - continue; - if (error(Section.isBSS(BSS))) + uint64_t BaseAddr = Section.getAddress(); + uint64_t Size = Section.getSize(); + if (!Size) continue; outs() << "Contents of section " << Name << ":\n"; - if (BSS) { - uint64_t Size; - if (error(Section.getSize(Size))) - continue; + if (Section.isBSS()) { outs() << format("\n", BaseAddr, BaseAddr + Size); @@ -674,34 +561,32 @@ static void PrintSectionContents(const ObjectFile *Obj) { } static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { - const coff_file_header *header; - if (error(coff->getHeader(header))) - return; - - for (unsigned SI = 0, SE = header->NumberOfSymbols; SI != SE; ++SI) { - const coff_symbol *Symbol; + for (unsigned SI = 0, SE = coff->getNumberOfSymbols(); SI != SE; ++SI) { + ErrorOr Symbol = coff->getSymbol(SI); StringRef Name; - if (error(coff->getSymbol(SI, Symbol))) + if (error(Symbol.getError())) return; - if (error(coff->getSymbolName(Symbol, Name))) + if (error(coff->getSymbolName(*Symbol, Name))) return; outs() << "[" << format("%2d", SI) << "]" - << "(sec " << format("%2d", int(Symbol->SectionNumber)) << ")" + << "(sec " << format("%2d", int(Symbol->getSectionNumber())) << ")" << "(fl 0x00)" // Flag bits, which COFF doesn't have. - << "(ty " << format("%3x", unsigned(Symbol->Type)) << ")" - << "(scl " << format("%3x", unsigned(Symbol->StorageClass)) << ") " - << "(nx " << unsigned(Symbol->NumberOfAuxSymbols) << ") " - << "0x" << format("%08x", unsigned(Symbol->Value)) << " " + << "(ty " << format("%3x", unsigned(Symbol->getType())) << ")" + << "(scl " << format("%3x", unsigned(Symbol->getStorageClass())) << ") " + << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") " + << "0x" << format("%08x", unsigned(Symbol->getValue())) << " " << Name << "\n"; - for (unsigned AI = 0, AE = Symbol->NumberOfAuxSymbols; AI < AE; ++AI, ++SI) { + for (unsigned AI = 0, AE = Symbol->getNumberOfAuxSymbols(); AI < AE; ++AI, ++SI) { if (Symbol->isSectionDefinition()) { const coff_aux_section_definition *asd; if (error(coff->getAuxSymbol(SI + 1, asd))) return; + int32_t AuxNumber = asd->getNumber(Symbol->isBigObj()); + outs() << "AUX " << format("scnlen 0x%x nreloc %d nlnno %d checksum 0x%x " , unsigned(asd->Length) @@ -709,18 +594,18 @@ static void PrintCOFFSymbolTable(const COFFObjectFile *coff) { , unsigned(asd->NumberOfLinenumbers) , unsigned(asd->CheckSum)) << format("assoc %d comdat %d\n" - , unsigned(asd->Number) + , unsigned(AuxNumber) , unsigned(asd->Selection)); } else if (Symbol->isFileRecord()) { - const coff_aux_file *AF; - if (error(coff->getAuxSymbol(SI + 1, AF))) + const char *FileName; + if (error(coff->getAuxSymbol(SI + 1, FileName))) return; - StringRef Name(AF->FileName, - Symbol->NumberOfAuxSymbols * COFF::SymbolSize); + StringRef Name(FileName, Symbol->getNumberOfAuxSymbols() * + coff->getSymbolTableEntrySize()); outs() << "AUX " << Name.rtrim(StringRef("\0", 1)) << '\n'; - SI = SI + Symbol->NumberOfAuxSymbols; + SI = SI + Symbol->getNumberOfAuxSymbols(); break; } else { outs() << "AUX Unknown\n"; @@ -813,10 +698,67 @@ static void PrintUnwindInfo(const ObjectFile *o) { if (const COFFObjectFile *coff = dyn_cast(o)) { printCOFFUnwindInfo(coff); - } else { + } else if (const MachOObjectFile *MachO = dyn_cast(o)) + printMachOUnwindInfo(MachO); + else { // TODO: Extract DWARF dump tool to objdump. errs() << "This operation is only currently supported " - "for COFF object files.\n"; + "for COFF and MachO object files.\n"; + return; + } +} + +void llvm::printExportsTrie(const ObjectFile *o) { + outs() << "Exports trie:\n"; + if (const MachOObjectFile *MachO = dyn_cast(o)) + printMachOExportsTrie(MachO); + else { + errs() << "This operation is only currently supported " + "for Mach-O executable files.\n"; + return; + } +} + +void llvm::printRebaseTable(const ObjectFile *o) { + outs() << "Rebase table:\n"; + if (const MachOObjectFile *MachO = dyn_cast(o)) + printMachORebaseTable(MachO); + else { + errs() << "This operation is only currently supported " + "for Mach-O executable files.\n"; + return; + } +} + +void llvm::printBindTable(const ObjectFile *o) { + outs() << "Bind table:\n"; + if (const MachOObjectFile *MachO = dyn_cast(o)) + printMachOBindTable(MachO); + else { + errs() << "This operation is only currently supported " + "for Mach-O executable files.\n"; + return; + } +} + +void llvm::printLazyBindTable(const ObjectFile *o) { + outs() << "Lazy bind table:\n"; + if (const MachOObjectFile *MachO = dyn_cast(o)) + printMachOLazyBindTable(MachO); + else { + errs() << "This operation is only currently supported " + "for Mach-O executable files.\n"; + return; + } +} + +void llvm::printWeakBindTable(const ObjectFile *o) { + outs() << "Weak bind table:\n"; + if (const MachOObjectFile *MachO = dyn_cast(o)) + printMachOWeakBindTable(MachO); + else { + errs() << "This operation is only currently supported " + "for Mach-O executable files.\n"; return; } } @@ -826,6 +768,8 @@ static void printPrivateFileHeader(const ObjectFile *o) { printELFFileHeader(o); } else if (o->isCOFF()) { printCOFFFileHeader(o); + } else if (o->isMachO()) { + printMachOFileHeader(o); } } @@ -848,6 +792,16 @@ static void DumpObject(const ObjectFile *o) { PrintUnwindInfo(o); if (PrivateHeaders) printPrivateFileHeader(o); + if (ExportsTrie) + printExportsTrie(o); + if (Rebase) + printRebaseTable(o); + if (Bind) + printBindTable(o); + if (LazyBind) + printLazyBindTable(o); + if (WeakBind) + printWeakBindTable(o); } /// @brief Dump each object file in \a a; @@ -878,22 +832,25 @@ static void DumpInput(StringRef file) { return; } - if (MachOOpt && Disassemble) { - DisassembleInputMachO(file); + // If we are using the Mach-O specific object file parser, then let it parse + // the file and process the command line options. So the -arch flags can + // be used to select specific slices, etc. + if (MachOOpt) { + ParseInputMachO(file); return; } // Attempt to open the binary. - ErrorOr BinaryOrErr = createBinary(file); + ErrorOr> BinaryOrErr = createBinary(file); if (std::error_code EC = BinaryOrErr.getError()) { errs() << ToolName << ": '" << file << "': " << EC.message() << ".\n"; return; } - std::unique_ptr binary(BinaryOrErr.get()); + Binary &Binary = *BinaryOrErr.get().getBinary(); - if (Archive *a = dyn_cast(binary.get())) + if (Archive *a = dyn_cast(&Binary)) DumpArchive(a); - else if (ObjectFile *o = dyn_cast(binary.get())) + else if (ObjectFile *o = dyn_cast(&Binary)) DumpObject(o); else errs() << ToolName << ": '" << file << "': " << "Unrecognized file type.\n"; @@ -929,7 +886,13 @@ int main(int argc, char **argv) { && !SectionContents && !SymbolTable && !UnwindInfo - && !PrivateHeaders) { + && !PrivateHeaders + && !ExportsTrie + && !Rebase + && !Bind + && !LazyBind + && !WeakBind + && !(UniversalHeaders && MachOOpt)) { cl::PrintHelpMessage(); return 2; } @@ -937,5 +900,5 @@ int main(int argc, char **argv) { std::for_each(InputFilenames.begin(), InputFilenames.end(), DumpInput); - return 0; + return ReturnValue; } diff --git a/tools/llvm-objdump/llvm-objdump.h b/tools/llvm-objdump/llvm-objdump.h index 80f8f58..f829dd1 100644 --- a/tools/llvm-objdump/llvm-objdump.h +++ b/tools/llvm-objdump/llvm-objdump.h @@ -7,32 +7,55 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_OBJDUMP_H -#define LLVM_OBJDUMP_H +#ifndef LLVM_TOOLS_LLVM_OBJDUMP_LLVM_OBJDUMP_H +#define LLVM_TOOLS_LLVM_OBJDUMP_LLVM_OBJDUMP_H #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataTypes.h" -#include "llvm/Support/StringRefMemoryObject.h" namespace llvm { namespace object { class COFFObjectFile; + class MachOObjectFile; class ObjectFile; class RelocationRef; } extern cl::opt TripleName; extern cl::opt ArchName; +extern cl::opt MCPU; +extern cl::list MAttrs; +extern cl::opt Disassemble; +extern cl::opt NoShowRawInsn; +extern cl::opt PrivateHeaders; +extern cl::opt ExportsTrie; +extern cl::opt Rebase; +extern cl::opt Bind; +extern cl::opt LazyBind; +extern cl::opt WeakBind; +extern cl::opt UniversalHeaders; // Various helper functions. bool error(std::error_code ec); bool RelocAddressLess(object::RelocationRef a, object::RelocationRef b); void DumpBytes(StringRef bytes); -void DisassembleInputMachO(StringRef Filename); +void ParseInputMachO(StringRef Filename); void printCOFFUnwindInfo(const object::COFFObjectFile* o); +void printMachOUnwindInfo(const object::MachOObjectFile* o); +void printMachOExportsTrie(const object::MachOObjectFile* o); +void printMachORebaseTable(const object::MachOObjectFile* o); +void printMachOBindTable(const object::MachOObjectFile* o); +void printMachOLazyBindTable(const object::MachOObjectFile* o); +void printMachOWeakBindTable(const object::MachOObjectFile* o); void printELFFileHeader(const object::ObjectFile *o); void printCOFFFileHeader(const object::ObjectFile *o); +void printMachOFileHeader(const object::ObjectFile *o); +void printExportsTrie(const object::ObjectFile *o); +void printRebaseTable(const object::ObjectFile *o); +void printBindTable(const object::ObjectFile *o); +void printLazyBindTable(const object::ObjectFile *o); +void printWeakBindTable(const object::ObjectFile *o); } // end namespace llvm diff --git a/tools/llvm-profdata/CMakeLists.txt b/tools/llvm-profdata/CMakeLists.txt index 3529114..0e330fd 100644 --- a/tools/llvm-profdata/CMakeLists.txt +++ b/tools/llvm-profdata/CMakeLists.txt @@ -1,4 +1,8 @@ -set(LLVM_LINK_COMPONENTS profiledata support) +set(LLVM_LINK_COMPONENTS + Core + ProfileData + Support + ) add_llvm_tool(llvm-profdata llvm-profdata.cpp diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp index 49ad37e..25531c7 100644 --- a/tools/llvm-profdata/llvm-profdata.cpp +++ b/tools/llvm-profdata/llvm-profdata.cpp @@ -12,8 +12,11 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringRef.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/InstrProfWriter.h" +#include "llvm/ProfileData/SampleProfReader.h" +#include "llvm/ProfileData/SampleProfWriter.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" @@ -33,32 +36,24 @@ static void exitWithError(const Twine &Message, StringRef Whence = "") { ::exit(1); } -int merge_main(int argc, const char *argv[]) { - cl::list Inputs(cl::Positional, cl::Required, cl::OneOrMore, - cl::desc("")); - - cl::opt OutputFilename("output", cl::value_desc("output"), - cl::init("-"), cl::Required, - cl::desc("Output file")); - cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), - cl::aliasopt(OutputFilename)); - - cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n"); +enum ProfileKinds { instr, sample }; +void mergeInstrProfile(cl::list Inputs, StringRef OutputFilename) { if (OutputFilename.compare("-") == 0) exitWithError("Cannot write indexed profdata format to stdout."); - std::string ErrorInfo; - raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_None); - if (!ErrorInfo.empty()) - exitWithError(ErrorInfo, OutputFilename); + std::error_code EC; + raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None); + if (EC) + exitWithError(EC.message(), OutputFilename); InstrProfWriter Writer; for (const auto &Filename : Inputs) { - std::unique_ptr Reader; - if (std::error_code ec = InstrProfReader::create(Filename, Reader)) + auto ReaderOrErr = InstrProfReader::create(Filename); + if (std::error_code ec = ReaderOrErr.getError()) exitWithError(ec.message(), Filename); + auto Reader = std::move(ReaderOrErr.get()); for (const auto &I : *Reader) if (std::error_code EC = Writer.addFunctionCounts(I.Name, I.Hash, I.Counts)) @@ -67,50 +62,86 @@ int merge_main(int argc, const char *argv[]) { exitWithError(Reader->getError().message(), Filename); } Writer.write(Output); - - return 0; } -int show_main(int argc, const char *argv[]) { - cl::opt Filename(cl::Positional, cl::Required, - cl::desc("")); +void mergeSampleProfile(cl::list Inputs, StringRef OutputFilename, + sampleprof::SampleProfileFormat OutputFormat) { + using namespace sampleprof; + auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat); + if (std::error_code EC = WriterOrErr.getError()) + exitWithError(EC.message(), OutputFilename); - cl::opt ShowCounts("counts", cl::init(false), - cl::desc("Show counter values for shown functions")); - cl::opt ShowAllFunctions("all-functions", cl::init(false), - cl::desc("Details for every function")); - cl::opt ShowFunction("function", - cl::desc("Details for matching functions")); + auto Writer = std::move(WriterOrErr.get()); + StringMap ProfileMap; + for (const auto &Filename : Inputs) { + auto ReaderOrErr = + SampleProfileReader::create(Filename, getGlobalContext()); + if (std::error_code EC = ReaderOrErr.getError()) + exitWithError(EC.message(), Filename); + + auto Reader = std::move(ReaderOrErr.get()); + if (std::error_code EC = Reader->read()) + exitWithError(EC.message(), Filename); + + StringMap &Profiles = Reader->getProfiles(); + for (StringMap::iterator I = Profiles.begin(), + E = Profiles.end(); + I != E; ++I) { + StringRef FName = I->first(); + FunctionSamples &Samples = I->second; + ProfileMap[FName].merge(Samples); + } + } + Writer->write(ProfileMap); +} + +int merge_main(int argc, const char *argv[]) { + cl::list Inputs(cl::Positional, cl::Required, cl::OneOrMore, + cl::desc("")); cl::opt OutputFilename("output", cl::value_desc("output"), - cl::init("-"), + cl::init("-"), cl::Required, cl::desc("Output file")); cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), cl::aliasopt(OutputFilename)); + cl::opt ProfileKind( + cl::desc("Profile kind:"), cl::init(instr), + cl::values(clEnumVal(instr, "Instrumentation profile (default)"), + clEnumVal(sample, "Sample profile"), clEnumValEnd)); + + cl::opt OutputFormat( + cl::desc("Format of output profile (only meaningful with --sample)"), + cl::init(sampleprof::SPF_Binary), + cl::values(clEnumValN(sampleprof::SPF_Binary, "binary", + "Binary encoding (default)"), + clEnumValN(sampleprof::SPF_Text, "text", "Text encoding"), + clEnumValN(sampleprof::SPF_GCC, "gcc", "GCC encoding"), + clEnumValEnd)); - cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); - - std::unique_ptr Reader; - if (std::error_code EC = InstrProfReader::create(Filename, Reader)) - exitWithError(EC.message(), Filename); + cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n"); - if (OutputFilename.empty()) - OutputFilename = "-"; + if (ProfileKind == instr) + mergeInstrProfile(Inputs, OutputFilename); + else + mergeSampleProfile(Inputs, OutputFilename, OutputFormat); - std::string ErrorInfo; - raw_fd_ostream OS(OutputFilename.data(), ErrorInfo, sys::fs::F_Text); - if (!ErrorInfo.empty()) - exitWithError(ErrorInfo, OutputFilename); + return 0; +} - if (ShowAllFunctions && !ShowFunction.empty()) - errs() << "warning: -function argument ignored: showing all functions\n"; +int showInstrProfile(std::string Filename, bool ShowCounts, + bool ShowAllFunctions, std::string ShowFunction, + raw_fd_ostream &OS) { + auto ReaderOrErr = InstrProfReader::create(Filename); + if (std::error_code EC = ReaderOrErr.getError()) + exitWithError(EC.message(), Filename); + auto Reader = std::move(ReaderOrErr.get()); uint64_t MaxFunctionCount = 0, MaxBlockCount = 0; size_t ShownFunctions = 0, TotalFunctions = 0; for (const auto &Func : *Reader) { - bool Show = ShowAllFunctions || - (!ShowFunction.empty() && - Func.Name.find(ShowFunction) != Func.Name.npos); + bool Show = + ShowAllFunctions || (!ShowFunction.empty() && + Func.Name.find(ShowFunction) != Func.Name.npos); ++TotalFunctions; assert(Func.Counts.size() > 0 && "function missing entry counter"); @@ -150,6 +181,65 @@ int show_main(int argc, const char *argv[]) { return 0; } +int showSampleProfile(std::string Filename, bool ShowCounts, + bool ShowAllFunctions, std::string ShowFunction, + raw_fd_ostream &OS) { + using namespace sampleprof; + auto ReaderOrErr = SampleProfileReader::create(Filename, getGlobalContext()); + if (std::error_code EC = ReaderOrErr.getError()) + exitWithError(EC.message(), Filename); + + auto Reader = std::move(ReaderOrErr.get()); + Reader->read(); + if (ShowAllFunctions || ShowFunction.empty()) + Reader->dump(OS); + else + Reader->dumpFunctionProfile(ShowFunction, OS); + + return 0; +} + +int show_main(int argc, const char *argv[]) { + cl::opt Filename(cl::Positional, cl::Required, + cl::desc("")); + + cl::opt ShowCounts("counts", cl::init(false), + cl::desc("Show counter values for shown functions")); + cl::opt ShowAllFunctions("all-functions", cl::init(false), + cl::desc("Details for every function")); + cl::opt ShowFunction("function", + cl::desc("Details for matching functions")); + + cl::opt OutputFilename("output", cl::value_desc("output"), + cl::init("-"), cl::desc("Output file")); + cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), + cl::aliasopt(OutputFilename)); + cl::opt ProfileKind( + cl::desc("Profile kind:"), cl::init(instr), + cl::values(clEnumVal(instr, "Instrumentation profile (default)"), + clEnumVal(sample, "Sample profile"), clEnumValEnd)); + + cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); + + if (OutputFilename.empty()) + OutputFilename = "-"; + + std::error_code EC; + raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::F_Text); + if (EC) + exitWithError(EC.message(), OutputFilename); + + if (ShowAllFunctions && !ShowFunction.empty()) + errs() << "warning: -function argument ignored: showing all functions\n"; + + if (ProfileKind == instr) + return showInstrProfile(Filename, ShowCounts, ShowAllFunctions, + ShowFunction, OS); + else + return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, + ShowFunction, OS); +} + int main(int argc, const char *argv[]) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); diff --git a/tools/llvm-readobj/ARMAttributeParser.cpp b/tools/llvm-readobj/ARMAttributeParser.cpp index d35cd14..e2d7191 100644 --- a/tools/llvm-readobj/ARMAttributeParser.cpp +++ b/tools/llvm-readobj/ARMAttributeParser.cpp @@ -141,7 +141,7 @@ void ARMAttributeParser::CPU_arch_profile(AttrType Tag, const uint8_t *Data, case 'R': Profile = "Real-time"; break; case 'M': Profile = "Microcontroller"; break; case 'S': Profile = "Classic"; break; - case '0': Profile = "None"; break; + case 0: Profile = "None"; break; } PrintAttribute(Tag, Encoded, Profile); diff --git a/tools/llvm-readobj/ARMAttributeParser.h b/tools/llvm-readobj/ARMAttributeParser.h index c286251..f924c83 100644 --- a/tools/llvm-readobj/ARMAttributeParser.h +++ b/tools/llvm-readobj/ARMAttributeParser.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_READOBJ_ARMATTRIBUTE_PARSER_H -#define LLVM_READOBJ_ARMATTRIBUTE_PARSER_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMATTRIBUTEPARSER_H +#define LLVM_TOOLS_LLVM_READOBJ_ARMATTRIBUTEPARSER_H #include "StreamWriter.h" #include "llvm/Support/ARMBuildAttributes.h" diff --git a/tools/llvm-readobj/ARMEHABIPrinter.h b/tools/llvm-readobj/ARMEHABIPrinter.h index 7608cfb..b15421d 100644 --- a/tools/llvm-readobj/ARMEHABIPrinter.h +++ b/tools/llvm-readobj/ARMEHABIPrinter.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_READOBJ_ARMEHABI_PRINTER_H -#define LLVM_READOBJ_ARMEHABI_PRINTER_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H +#define LLVM_TOOLS_LLVM_READOBJ_ARMEHABIPRINTER_H #include "Error.h" #include "StreamWriter.h" diff --git a/tools/llvm-readobj/ARMWinEHPrinter.cpp b/tools/llvm-readobj/ARMWinEHPrinter.cpp index b486e4a..62252fc 100644 --- a/tools/llvm-readobj/ARMWinEHPrinter.cpp +++ b/tools/llvm-readobj/ARMWinEHPrinter.cpp @@ -64,8 +64,8 @@ #include "ARMWinEHPrinter.h" #include "Error.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/ARMWinEH.h" #include "llvm/Support/Format.h" @@ -186,13 +186,8 @@ void Decoder::printRegisters(const std::pair &RegisterMask) ErrorOr Decoder::getSectionContaining(const COFFObjectFile &COFF, uint64_t VA) { for (const auto &Section : COFF.sections()) { - uint64_t Address; - uint64_t Size; - - if (std::error_code EC = Section.getAddress(Address)) - return EC; - if (std::error_code EC = Section.getSize(Size)) - return EC; + uint64_t Address = Section.getAddress(); + uint64_t Size = Section.getSize(); if (VA >= Address && (VA - Address) <= Size) return Section; @@ -233,7 +228,7 @@ ErrorOr Decoder::getRelocatedSymbol(const COFFObjectFile &, return readobj_error::unknown_symbol; } -bool Decoder::opcode_0xxxxxxx(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_0xxxxxxx(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { uint8_t Imm = OC[Offset] & 0x7f; SW.startLine() << format("0x%02x ; %s sp, #(%u * 4)\n", @@ -244,7 +239,7 @@ bool Decoder::opcode_0xxxxxxx(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_10Lxxxxx(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_10Lxxxxx(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { unsigned Link = (OC[Offset] & 0x20) >> 5; uint16_t RegisterMask = (Link << (Prologue ? 14 : 15)) @@ -263,7 +258,7 @@ bool Decoder::opcode_10Lxxxxx(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_1100xxxx(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_1100xxxx(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { if (Prologue) SW.startLine() << format("0x%02x ; mov r%u, sp\n", @@ -275,7 +270,7 @@ bool Decoder::opcode_1100xxxx(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11010Lxx(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11010Lxx(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { unsigned Link = (OC[Offset] & 0x4) >> 3; unsigned Count = (OC[Offset] & 0x3); @@ -292,7 +287,7 @@ bool Decoder::opcode_11010Lxx(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11011Lxx(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11011Lxx(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { unsigned Link = (OC[Offset] & 0x4) >> 2; unsigned Count = (OC[Offset] & 0x3) + 4; @@ -309,7 +304,7 @@ bool Decoder::opcode_11011Lxx(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11100xxx(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11100xxx(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { unsigned High = (OC[Offset] & 0x7); uint32_t VFPMask = (((1 << (High + 1)) - 1) << 8); @@ -323,7 +318,7 @@ bool Decoder::opcode_11100xxx(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_111010xx(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_111010xx(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { uint16_t Imm = ((OC[Offset + 0] & 0x03) << 8) | ((OC[Offset + 1] & 0xff) << 0); @@ -336,7 +331,7 @@ bool Decoder::opcode_111010xx(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_1110110L(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_1110110L(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { uint8_t GPRMask = ((OC[Offset + 0] & 0x01) << (Prologue ? 14 : 15)) | ((OC[Offset + 1] & 0xff) << 0); @@ -350,7 +345,7 @@ bool Decoder::opcode_1110110L(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11101110(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11101110(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { assert(!Prologue && "may not be used in prologue"); @@ -366,7 +361,7 @@ bool Decoder::opcode_11101110(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11101111(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11101111(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { assert(!Prologue && "may not be used in prologue"); @@ -382,7 +377,7 @@ bool Decoder::opcode_11101111(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11110101(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11110101(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { unsigned Start = (OC[Offset + 1] & 0xf0) >> 4; unsigned End = (OC[Offset + 1] & 0x0f) >> 0; @@ -397,7 +392,7 @@ bool Decoder::opcode_11110101(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11110110(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11110110(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { unsigned Start = (OC[Offset + 1] & 0xf0) >> 4; unsigned End = (OC[Offset + 1] & 0x0f) >> 0; @@ -412,7 +407,7 @@ bool Decoder::opcode_11110110(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11110111(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11110111(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0); @@ -425,7 +420,7 @@ bool Decoder::opcode_11110111(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11111000(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111000(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { uint32_t Imm = (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) @@ -440,7 +435,7 @@ bool Decoder::opcode_11111000(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11111001(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111001(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { uint32_t Imm = (OC[Offset + 1] << 8) | (OC[Offset + 2] << 0); @@ -453,7 +448,7 @@ bool Decoder::opcode_11111001(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11111010(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111010(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { uint32_t Imm = (OC[Offset + 1] << 16) | (OC[Offset + 2] << 8) @@ -468,41 +463,41 @@ bool Decoder::opcode_11111010(const ulittle8_t *OC, unsigned &Offset, return false; } -bool Decoder::opcode_11111011(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111011(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { SW.startLine() << format("0x%02x ; nop\n", OC[Offset]); ++Offset; return false; } -bool Decoder::opcode_11111100(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111100(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { SW.startLine() << format("0x%02x ; nop.w\n", OC[Offset]); ++Offset; return false; } -bool Decoder::opcode_11111101(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111101(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { SW.startLine() << format("0x%02x ; b\n", OC[Offset]); ++Offset; return true; } -bool Decoder::opcode_11111110(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111110(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { SW.startLine() << format("0x%02x ; b.w\n", OC[Offset]); ++Offset; return true; } -bool Decoder::opcode_11111111(const ulittle8_t *OC, unsigned &Offset, +bool Decoder::opcode_11111111(const uint8_t *OC, unsigned &Offset, unsigned Length, bool Prologue) { ++Offset; return true; } -void Decoder::decodeOpcodes(ArrayRef Opcodes, unsigned Offset, +void Decoder::decodeOpcodes(ArrayRef Opcodes, unsigned Offset, bool Prologue) { assert((!Prologue || Offset == 0) && "prologue should always use offset 0"); @@ -525,10 +520,7 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, if (COFF.getSectionContents(COFF.getCOFFSection(Section), Contents)) return false; - uint64_t SectionVA; - if (Section.getAddress(SectionVA)) - return false; - + uint64_t SectionVA = Section.getAddress(); uint64_t Offset = VA - SectionVA; const ulittle32_t *Data = reinterpret_cast(Contents.data() + Offset); @@ -546,7 +538,7 @@ bool Decoder::dumpXDataRecord(const COFFObjectFile &COFF, static_cast(XData.CodeWords() * sizeof(uint32_t))); if (XData.E()) { - ArrayRef UC = XData.UnwindByteCode(); + ArrayRef UC = XData.UnwindByteCode(); if (!XData.F()) { ListScope PS(SW, "Prologue"); decodeOpcodes(UC, 0, /*Prologue=*/true); @@ -741,4 +733,3 @@ std::error_code Decoder::dumpProcedureData(const COFFObjectFile &COFF) { } } } - diff --git a/tools/llvm-readobj/ARMWinEHPrinter.h b/tools/llvm-readobj/ARMWinEHPrinter.h index 740c8b5..274ef11 100644 --- a/tools/llvm-readobj/ARMWinEHPrinter.h +++ b/tools/llvm-readobj/ARMWinEHPrinter.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_READOBJ_ARMWINEHPRINTER_H -#define LLVM_READOBJ_ARMWINEHPRINTER_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_ARMWINEHPRINTER_H +#define LLVM_TOOLS_LLVM_READOBJ_ARMWINEHPRINTER_H #include "StreamWriter.h" #include "llvm/Object/COFF.h" @@ -28,55 +28,54 @@ class Decoder { struct RingEntry { uint8_t Mask; uint8_t Value; - bool (Decoder::*Routine)(const support::ulittle8_t *, unsigned &, unsigned, - bool); + bool (Decoder::*Routine)(const uint8_t *, unsigned &, unsigned, bool); }; static const RingEntry Ring[]; - bool opcode_0xxxxxxx(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_0xxxxxxx(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_10Lxxxxx(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_10Lxxxxx(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_1100xxxx(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_1100xxxx(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11010Lxx(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11010Lxx(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11011Lxx(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11011Lxx(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11100xxx(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11100xxx(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_111010xx(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_111010xx(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_1110110L(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_1110110L(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11101110(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11101110(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11101111(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11101111(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11110101(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11110101(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11110110(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11110110(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11110111(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11110111(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111000(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111000(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111001(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111001(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111010(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111010(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111011(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111011(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111100(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111100(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111101(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111101(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111110(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111110(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - bool opcode_11111111(const support::ulittle8_t *Opcodes, unsigned &Offset, + bool opcode_11111111(const uint8_t *Opcodes, unsigned &Offset, unsigned Length, bool Prologue); - void decodeOpcodes(ArrayRef Opcodes, unsigned Offset, + void decodeOpcodes(ArrayRef Opcodes, unsigned Offset, bool Prologue); void printRegisters(const std::pair &RegisterMask); @@ -116,4 +115,3 @@ public: } #endif - diff --git a/tools/llvm-readobj/COFFDumper.cpp b/tools/llvm-readobj/COFFDumper.cpp index 7842cd4..156e39a 100644 --- a/tools/llvm-readobj/COFFDumper.cpp +++ b/tools/llvm-readobj/COFFDumper.cpp @@ -20,6 +20,7 @@ #include "Win64EHDumper.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/COFF.h" @@ -49,35 +50,50 @@ public: cacheRelocations(); } - virtual void printFileHeaders() override; - virtual void printSections() override; - virtual void printRelocations() override; - virtual void printSymbols() override; - virtual void printDynamicSymbols() override; - virtual void printUnwindInfo() override; + void printFileHeaders() override; + void printSections() override; + void printRelocations() override; + void printSymbols() override; + void printDynamicSymbols() override; + void printUnwindInfo() override; + void printCOFFImports() override; + void printCOFFExports() override; + void printCOFFDirectives() override; + void printCOFFBaseReloc() override; private: void printSymbol(const SymbolRef &Sym); void printRelocation(const SectionRef &Section, const RelocationRef &Reloc); void printDataDirectory(uint32_t Index, const std::string &FieldName); + void printDOSHeader(const dos_header *DH); template void printPEHeader(const PEHeader *Hdr); void printBaseOfDataField(const pe32_header *Hdr); void printBaseOfDataField(const pe32plus_header *Hdr); void printCodeViewLineTables(const SectionRef &Section); + void printCodeViewSymbolsSubsection(StringRef Subsection, + const SectionRef &Section, + uint32_t Offset); + void cacheRelocations(); std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset, SymbolRef &Sym); std::error_code resolveSymbolName(const coff_section *Section, uint64_t Offset, StringRef &Name); + void printImportedSymbols(iterator_range Range); + void printDelayImportedSymbols( + const DelayImportDirectoryEntryRef &I, + iterator_range Range); typedef DenseMap > RelocMapTy; const llvm::object::COFFObjectFile *Obj; RelocMapTy RelocMap; + StringRef CVFileIndexToStringOffsetTable; + StringRef CVStringTable; }; } // namespace @@ -313,9 +329,10 @@ WeakExternalCharacteristics[] = { template static std::error_code getSymbolAuxData(const COFFObjectFile *Obj, - const coff_symbol *Symbol, - const T *&Aux) { + COFFSymbolRef Symbol, + uint8_t AuxSymbolIdx, const T *&Aux) { ArrayRef AuxData = Obj->getSymbolAuxData(Symbol); + AuxData = AuxData.slice(AuxSymbolIdx * Obj->getSymbolTableEntrySize()); Aux = reinterpret_cast(AuxData.data()); return readobj_error::success; } @@ -342,25 +359,20 @@ void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName } void COFFDumper::printFileHeaders() { - // Print COFF header - const coff_file_header *COFFHeader = nullptr; - if (error(Obj->getCOFFHeader(COFFHeader))) - return; - - time_t TDS = COFFHeader->TimeDateStamp; + time_t TDS = Obj->getTimeDateStamp(); char FormattedTime[20] = { }; strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS)); { DictScope D(W, "ImageFileHeader"); - W.printEnum ("Machine", COFFHeader->Machine, + W.printEnum ("Machine", Obj->getMachine(), makeArrayRef(ImageFileMachineType)); - W.printNumber("SectionCount", COFFHeader->NumberOfSections); - W.printHex ("TimeDateStamp", FormattedTime, COFFHeader->TimeDateStamp); - W.printHex ("PointerToSymbolTable", COFFHeader->PointerToSymbolTable); - W.printNumber("SymbolCount", COFFHeader->NumberOfSymbols); - W.printNumber("OptionalHeaderSize", COFFHeader->SizeOfOptionalHeader); - W.printFlags ("Characteristics", COFFHeader->Characteristics, + W.printNumber("SectionCount", Obj->getNumberOfSections()); + W.printHex ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp()); + W.printHex ("PointerToSymbolTable", Obj->getPointerToSymbolTable()); + W.printNumber("SymbolCount", Obj->getNumberOfSymbols()); + W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader()); + W.printFlags ("Characteristics", Obj->getCharacteristics(), makeArrayRef(ImageFileCharacteristics)); } @@ -377,6 +389,30 @@ void COFFDumper::printFileHeaders() { return; if (PEPlusHeader) printPEHeader(PEPlusHeader); + + if (const dos_header *DH = Obj->getDOSHeader()) + printDOSHeader(DH); +} + +void COFFDumper::printDOSHeader(const dos_header *DH) { + DictScope D(W, "DOSHeader"); + W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic))); + W.printNumber("UsedBytesInTheLastPage", DH->UsedBytesInTheLastPage); + W.printNumber("FileSizeInPages", DH->FileSizeInPages); + W.printNumber("NumberOfRelocationItems", DH->NumberOfRelocationItems); + W.printNumber("HeaderSizeInParagraphs", DH->HeaderSizeInParagraphs); + W.printNumber("MinimumExtraParagraphs", DH->MinimumExtraParagraphs); + W.printNumber("MaximumExtraParagraphs", DH->MaximumExtraParagraphs); + W.printNumber("InitialRelativeSS", DH->InitialRelativeSS); + W.printNumber("InitialSP", DH->InitialSP); + W.printNumber("Checksum", DH->Checksum); + W.printNumber("InitialIP", DH->InitialIP); + W.printNumber("InitialRelativeCS", DH->InitialRelativeCS); + W.printNumber("AddressOfRelocationTable", DH->AddressOfRelocationTable); + W.printNumber("OverlayNumber", DH->OverlayNumber); + W.printNumber("OEMid", DH->OEMid); + W.printNumber("OEMinfo", DH->OEMinfo); + W.printNumber("AddressOfNewExeHeader", DH->AddressOfNewExeHeader); } template @@ -404,7 +440,7 @@ void COFFDumper::printPEHeader(const PEHeader *Hdr) { W.printNumber("SizeOfImage", Hdr->SizeOfImage); W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders); W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem)); - W.printFlags ("Subsystem", Hdr->DLLCharacteristics, + W.printFlags ("Characteristics", Hdr->DLLCharacteristics, makeArrayRef(PEDLLCharacteristics)); W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve); W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit); @@ -440,11 +476,10 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { SmallVector FunctionNames; StringMap FunctionLineTables; - StringRef FileIndexToStringOffsetTable; - StringRef StringTable; ListScope D(W, "CodeViewLineTables"); { + // FIXME: Add more offset correctness checks. DataExtractor DE(Data, true, 4); uint32_t Offset = 0, Magic = DE.getU32(&Offset); @@ -474,6 +509,9 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { W.printBinaryBlock("Contents", Contents); switch (SubSectionType) { + case COFF::DEBUG_SYMBOL_SUBSECTION: + printCodeViewSymbolsSubsection(Contents, Section, Offset); + break; case COFF::DEBUG_LINE_TABLE_SUBSECTION: { // Holds a PC to file:line table. Some data to parse this subsection is // stored in the other subsections, so just check sanity and store the @@ -502,25 +540,25 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { break; } case COFF::DEBUG_STRING_TABLE_SUBSECTION: - if (PayloadSize == 0 || StringTable.data() != nullptr || + if (PayloadSize == 0 || CVStringTable.data() != nullptr || Contents.back() != '\0') { // Empty or duplicate or non-null-terminated subsection. error(object_error::parse_failed); return; } - StringTable = Contents; + CVStringTable = Contents; break; case COFF::DEBUG_INDEX_SUBSECTION: // Holds the translation table from file indices // to offsets in the string table. if (PayloadSize == 0 || - FileIndexToStringOffsetTable.data() != nullptr) { + CVFileIndexToStringOffsetTable.data() != nullptr) { // Empty or duplicate subsection. error(object_error::parse_failed); return; } - FileIndexToStringOffsetTable = Contents; + CVFileIndexToStringOffsetTable = Contents; break; } Offset += PayloadSize; @@ -555,7 +593,7 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { uint32_t FilenameOffset; { - DataExtractor SDE(FileIndexToStringOffsetTable, true, 4); + DataExtractor SDE(CVFileIndexToStringOffsetTable, true, 4); uint32_t OffsetInSDE = OffsetInIndex; if (!SDE.isValidOffset(OffsetInSDE)) { error(object_error::parse_failed); @@ -564,15 +602,15 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { FilenameOffset = SDE.getU32(&OffsetInSDE); } - if (FilenameOffset == 0 || FilenameOffset + 1 >= StringTable.size() || - StringTable.data()[FilenameOffset - 1] != '\0') { + if (FilenameOffset == 0 || FilenameOffset + 1 >= CVStringTable.size() || + CVStringTable.data()[FilenameOffset - 1] != '\0') { // Each string in an F3 subsection should be preceded by a null // character. error(object_error::parse_failed); return; } - StringRef Filename(StringTable.data() + FilenameOffset); + StringRef Filename(CVStringTable.data() + FilenameOffset); ListScope S(W, "FilenameSegment"); W.printString("Filename", Filename); for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset); @@ -593,6 +631,80 @@ void COFFDumper::printCodeViewLineTables(const SectionRef &Section) { } } +void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, + const SectionRef &Section, + uint32_t OffsetInSection) { + if (Subsection.size() == 0) { + error(object_error::parse_failed); + return; + } + DataExtractor DE(Subsection, true, 4); + uint32_t Offset = 0; + + // Function-level subsections have "procedure start" and "procedure end" + // commands that should come in pairs and surround relevant info. + bool InFunctionScope = false; + while (DE.isValidOffset(Offset)) { + // Read subsection segments one by one. + uint16_t Size = DE.getU16(&Offset); + // The section size includes the size of the type identifier. + if (Size < 2 || !DE.isValidOffsetForDataOfSize(Offset, Size)) { + error(object_error::parse_failed); + return; + } + Size -= 2; + uint16_t Type = DE.getU16(&Offset); + switch (Type) { + case COFF::DEBUG_SYMBOL_TYPE_PROC_START: { + DictScope S(W, "ProcStart"); + if (InFunctionScope || Size < 36) { + error(object_error::parse_failed); + return; + } + InFunctionScope = true; + + // We're currently interested in a limited subset of fields in this + // segment, just ignore the rest of the fields for now. + uint8_t Unused[12]; + DE.getU8(&Offset, Unused, 12); + uint32_t CodeSize = DE.getU32(&Offset); + DE.getU8(&Offset, Unused, 12); + StringRef SectionName; + if (error(resolveSymbolName(Obj->getCOFFSection(Section), + OffsetInSection + Offset, SectionName))) + return; + Offset += 4; + DE.getU8(&Offset, Unused, 3); + StringRef DisplayName = DE.getCStr(&Offset); + if (!DE.isValidOffset(Offset)) { + error(object_error::parse_failed); + return; + } + W.printString("DisplayName", DisplayName); + W.printString("Section", SectionName); + W.printHex("CodeSize", CodeSize); + + break; + } + case COFF::DEBUG_SYMBOL_TYPE_PROC_END: { + W.startLine() << "ProcEnd\n"; + if (!InFunctionScope || Size > 0) { + error(object_error::parse_failed); + return; + } + InFunctionScope = false; + break; + } + default: + Offset += Size; + break; + } + } + + if (InFunctionScope) + error(object_error::parse_failed); +} + void COFFDumper::printSections() { ListScope SectionsD(W, "Sections"); int SectionNumber = 0; @@ -628,8 +740,7 @@ void COFFDumper::printSections() { if (opts::SectionSymbols) { ListScope D(W, "Symbols"); for (const SymbolRef &Symbol : Obj->symbols()) { - bool Contained = false; - if (Sec.containsSymbol(Symbol, Contained) || !Contained) + if (!Sec.containsSymbol(Symbol)) continue; printSymbol(Symbol); @@ -639,7 +750,8 @@ void COFFDumper::printSections() { if (Name == ".debug$S" && opts::CodeViewLineTables) printCodeViewLineTables(Sec); - if (opts::SectionData) { + if (opts::SectionData && + !(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) { StringRef Data; if (error(Sec.getContents(Data))) break; @@ -683,7 +795,6 @@ void COFFDumper::printRelocation(const SectionRef &Section, uint64_t RelocType; SmallString<32> RelocName; StringRef SymbolName; - StringRef Contents; if (error(Reloc.getOffset(Offset))) return; if (error(Reloc.getType(RelocType))) @@ -691,21 +802,19 @@ void COFFDumper::printRelocation(const SectionRef &Section, if (error(Reloc.getTypeName(RelocName))) return; symbol_iterator Symbol = Reloc.getSymbol(); - if (error(Symbol->getName(SymbolName))) - return; - if (error(Section.getContents(Contents))) + if (Symbol != Obj->symbol_end() && error(Symbol->getName(SymbolName))) return; if (opts::ExpandRelocs) { DictScope Group(W, "Relocation"); W.printHex("Offset", Offset); W.printNumber("Type", RelocName, RelocType); - W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printString("Symbol", SymbolName.empty() ? "-" : SymbolName); } else { raw_ostream& OS = W.startLine(); OS << W.hex(Offset) << " " << RelocName - << " " << (SymbolName.size() > 0 ? SymbolName : "-") + << " " << (SymbolName.empty() ? "-" : SymbolName) << "\n"; } } @@ -719,12 +828,30 @@ void COFFDumper::printSymbols() { void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); } +static ErrorOr +getSectionName(const llvm::object::COFFObjectFile *Obj, int32_t SectionNumber, + const coff_section *Section) { + if (Section) { + StringRef SectionName; + if (std::error_code EC = Obj->getSectionName(Section, SectionName)) + return EC; + return SectionName; + } + if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG) + return StringRef("IMAGE_SYM_DEBUG"); + if (SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE) + return StringRef("IMAGE_SYM_ABSOLUTE"); + if (SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED) + return StringRef("IMAGE_SYM_UNDEFINED"); + return StringRef(""); +} + void COFFDumper::printSymbol(const SymbolRef &Sym) { DictScope D(W, "Symbol"); - const coff_symbol *Symbol = Obj->getCOFFSymbol(Sym); + COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym); const coff_section *Section; - if (std::error_code EC = Obj->getSection(Symbol->SectionNumber, Section)) { + if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) { W.startLine() << "Invalid section number: " << EC.message() << "\n"; W.flush(); return; @@ -735,23 +862,25 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { SymbolName = ""; StringRef SectionName = ""; - if (Section) - Obj->getSectionName(Section, SectionName); + ErrorOr Res = + getSectionName(Obj, Symbol.getSectionNumber(), Section); + if (Res) + SectionName = *Res; W.printString("Name", SymbolName); - W.printNumber("Value", Symbol->Value); - W.printNumber("Section", SectionName, Symbol->SectionNumber); - W.printEnum ("BaseType", Symbol->getBaseType(), makeArrayRef(ImageSymType)); - W.printEnum ("ComplexType", Symbol->getComplexType(), + W.printNumber("Value", Symbol.getValue()); + W.printNumber("Section", SectionName, Symbol.getSectionNumber()); + W.printEnum ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType)); + W.printEnum ("ComplexType", Symbol.getComplexType(), makeArrayRef(ImageSymDType)); - W.printEnum ("StorageClass", Symbol->StorageClass, + W.printEnum ("StorageClass", Symbol.getStorageClass(), makeArrayRef(ImageSymClass)); - W.printNumber("AuxSymbolCount", Symbol->NumberOfAuxSymbols); + W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols()); - for (unsigned I = 0; I < Symbol->NumberOfAuxSymbols; ++I) { - if (Symbol->isFunctionDefinition()) { + for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) { + if (Symbol.isFunctionDefinition()) { const coff_aux_function_definition *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; DictScope AS(W, "AuxFunctionDef"); @@ -759,18 +888,16 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("TotalSize", Aux->TotalSize); W.printHex("PointerToLineNumber", Aux->PointerToLinenumber); W.printHex("PointerToNextFunction", Aux->PointerToNextFunction); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); - } else if (Symbol->isWeakExternal()) { + } else if (Symbol.isAnyUndefined()) { const coff_aux_weak_external *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; - const coff_symbol *Linked; + ErrorOr Linked = Obj->getSymbol(Aux->TagIndex); StringRef LinkedName; - std::error_code EC; - if ((EC = Obj->getSymbol(Aux->TagIndex, Linked)) || - (EC = Obj->getSymbolName(Linked, LinkedName))) { + std::error_code EC = Linked.getError(); + if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) { LinkedName = ""; error(EC); } @@ -779,56 +906,60 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("Linked", LinkedName, Aux->TagIndex); W.printEnum ("Search", Aux->Characteristics, makeArrayRef(WeakExternalCharacteristics)); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); - } else if (Symbol->isFileRecord()) { - const coff_aux_file *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + } else if (Symbol.isFileRecord()) { + const char *FileName; + if (error(getSymbolAuxData(Obj, Symbol, I, FileName))) break; DictScope AS(W, "AuxFileRecord"); - StringRef Name(Aux->FileName, - Symbol->NumberOfAuxSymbols * COFF::SymbolSize); + StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() * + Obj->getSymbolTableEntrySize()); W.printString("FileName", Name.rtrim(StringRef("\0", 1))); break; - } else if (Symbol->isSectionDefinition()) { + } else if (Symbol.isSectionDefinition()) { const coff_aux_section_definition *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; + int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj()); + DictScope AS(W, "AuxSectionDef"); W.printNumber("Length", Aux->Length); W.printNumber("RelocationCount", Aux->NumberOfRelocations); W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers); W.printHex("Checksum", Aux->CheckSum); - W.printNumber("Number", Aux->Number); + W.printNumber("Number", AuxNumber); W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect)); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) { const coff_section *Assoc; - StringRef AssocName; - std::error_code EC; - if ((EC = Obj->getSection(Aux->Number, Assoc)) || - (EC = Obj->getSectionName(Assoc, AssocName))) { + StringRef AssocName = ""; + std::error_code EC = Obj->getSection(AuxNumber, Assoc); + ErrorOr Res = getSectionName(Obj, AuxNumber, Assoc); + if (Res) + AssocName = *Res; + if (!EC) + EC = Res.getError(); + if (EC) { AssocName = ""; error(EC); } - W.printNumber("AssocSection", AssocName, Aux->Number); + W.printNumber("AssocSection", AssocName, AuxNumber); } - } else if (Symbol->isCLRToken()) { + } else if (Symbol.isCLRToken()) { const coff_aux_clr_token *Aux; - if (error(getSymbolAuxData(Obj, Symbol + I, Aux))) + if (error(getSymbolAuxData(Obj, Symbol, I, Aux))) break; - const coff_symbol *ReferredSym; + ErrorOr ReferredSym = + Obj->getSymbol(Aux->SymbolTableIndex); StringRef ReferredName; - std::error_code EC; - if ((EC = Obj->getSymbol(Aux->SymbolTableIndex, ReferredSym)) || - (EC = Obj->getSymbolName(ReferredSym, ReferredName))) { + std::error_code EC = ReferredSym.getError(); + if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) { ReferredName = ""; error(EC); } @@ -837,7 +968,6 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { W.printNumber("AuxType", Aux->AuxType); W.printNumber("Reserved", Aux->Reserved); W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex); - W.printBinary("Unused", makeArrayRef(Aux->Unused)); } else { W.startLine() << "\n"; @@ -846,12 +976,8 @@ void COFFDumper::printSymbol(const SymbolRef &Sym) { } void COFFDumper::printUnwindInfo() { - const coff_file_header *Header; - if (error(Obj->getCOFFHeader(Header))) - return; - ListScope D(W, "UnwindInformation"); - switch (Header->Machine) { + switch (Obj->getMachine()) { case COFF::IMAGE_FILE_MACHINE_AMD64: { Win64EH::Dumper Dumper(W); Win64EH::Dumper::SymbolResolver @@ -870,9 +996,133 @@ void COFFDumper::printUnwindInfo() { break; } default: - W.printEnum("unsupported Image Machine", Header->Machine, + W.printEnum("unsupported Image Machine", Obj->getMachine(), makeArrayRef(ImageFileMachineType)); break; } } +void COFFDumper::printImportedSymbols( + iterator_range Range) { + for (const ImportedSymbolRef &I : Range) { + StringRef Sym; + if (error(I.getSymbolName(Sym))) return; + uint16_t Ordinal; + if (error(I.getOrdinal(Ordinal))) return; + W.printNumber("Symbol", Sym, Ordinal); + } +} + +void COFFDumper::printDelayImportedSymbols( + const DelayImportDirectoryEntryRef &I, + iterator_range Range) { + int Index = 0; + for (const ImportedSymbolRef &S : Range) { + DictScope Import(W, "Import"); + StringRef Sym; + if (error(S.getSymbolName(Sym))) return; + uint16_t Ordinal; + if (error(S.getOrdinal(Ordinal))) return; + W.printNumber("Symbol", Sym, Ordinal); + uint64_t Addr; + if (error(I.getImportAddress(Index++, Addr))) return; + W.printHex("Address", Addr); + } +} + +void COFFDumper::printCOFFImports() { + // Regular imports + for (const ImportDirectoryEntryRef &I : Obj->import_directories()) { + DictScope Import(W, "Import"); + StringRef Name; + if (error(I.getName(Name))) return; + W.printString("Name", Name); + uint32_t Addr; + if (error(I.getImportLookupTableRVA(Addr))) return; + W.printHex("ImportLookupTableRVA", Addr); + if (error(I.getImportAddressTableRVA(Addr))) return; + W.printHex("ImportAddressTableRVA", Addr); + printImportedSymbols(I.imported_symbols()); + } + + // Delay imports + for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) { + DictScope Import(W, "DelayImport"); + StringRef Name; + if (error(I.getName(Name))) return; + W.printString("Name", Name); + const delay_import_directory_table_entry *Table; + if (error(I.getDelayImportTable(Table))) return; + W.printHex("Attributes", Table->Attributes); + W.printHex("ModuleHandle", Table->ModuleHandle); + W.printHex("ImportAddressTable", Table->DelayImportAddressTable); + W.printHex("ImportNameTable", Table->DelayImportNameTable); + W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable); + W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable); + printDelayImportedSymbols(I, I.imported_symbols()); + } +} + +void COFFDumper::printCOFFExports() { + for (const ExportDirectoryEntryRef &E : Obj->export_directories()) { + DictScope Export(W, "Export"); + + StringRef Name; + uint32_t Ordinal, RVA; + + if (error(E.getSymbolName(Name))) + continue; + if (error(E.getOrdinal(Ordinal))) + continue; + if (error(E.getExportRVA(RVA))) + continue; + + W.printNumber("Ordinal", Ordinal); + W.printString("Name", Name); + W.printHex("RVA", RVA); + } +} + +void COFFDumper::printCOFFDirectives() { + for (const SectionRef &Section : Obj->sections()) { + StringRef Contents; + StringRef Name; + + if (error(Section.getName(Name))) + continue; + if (Name != ".drectve") + continue; + + if (error(Section.getContents(Contents))) + return; + + W.printString("Directive(s)", Contents); + } +} + +static StringRef getBaseRelocTypeName(uint8_t Type) { + switch (Type) { + case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE"; + case COFF::IMAGE_REL_BASED_HIGH: return "HIGH"; + case COFF::IMAGE_REL_BASED_LOW: return "LOW"; + case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW"; + case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ"; + case COFF::IMAGE_REL_BASED_DIR64: return "DIR64"; + default: return "unknown (" + llvm::utostr(Type) + ")"; + } +} + +void COFFDumper::printCOFFBaseReloc() { + ListScope D(W, "BaseReloc"); + for (const BaseRelocRef &I : Obj->base_relocs()) { + uint8_t Type; + uint32_t RVA; + if (error(I.getRVA(RVA))) + continue; + if (error(I.getType(Type))) + continue; + DictScope Import(W, "Entry"); + W.printString("Type", getBaseRelocTypeName(Type)); + W.printHex("Address", RVA); + } +} diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 1791f5a..d68c786 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -604,7 +604,7 @@ void ELFDumper::printSections() { } } - if (opts::SectionData) { + if (opts::SectionData && Section->sh_type != ELF::SHT_NOBITS) { ArrayRef Data = errorOrDefault(Obj->getSectionContents(Section)); W.printBinaryBlock("SectionData", StringRef((const char *)Data.data(), Data.size())); @@ -676,7 +676,8 @@ void ELFDumper::printRelocation(const Elf_Shdr *Sec, DictScope Group(W, "Relocation"); W.printHex("Offset", Rel.r_offset); W.printNumber("Type", RelocName, (int)Rel.getType(Obj->isMips64EL())); - W.printString("Symbol", SymbolName.size() > 0 ? SymbolName : "-"); + W.printNumber("Symbol", SymbolName.size() > 0 ? SymbolName : "-", + Rel.getSymbol(Obj->isMips64EL())); W.printHex("Addend", Rel.r_addend); } else { raw_ostream& OS = W.startLine(); diff --git a/tools/llvm-readobj/Error.cpp b/tools/llvm-readobj/Error.cpp index a078f5c..7e6f780 100644 --- a/tools/llvm-readobj/Error.cpp +++ b/tools/llvm-readobj/Error.cpp @@ -24,7 +24,7 @@ public: }; } // namespace -const char *_readobj_error_category::name() const { +const char *_readobj_error_category::name() const LLVM_NOEXCEPT { return "llvm.readobj"; } diff --git a/tools/llvm-readobj/Error.h b/tools/llvm-readobj/Error.h index 81ce408..f3e24bb 100644 --- a/tools/llvm-readobj/Error.h +++ b/tools/llvm-readobj/Error.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_READOBJ_ERROR_H -#define LLVM_READOBJ_ERROR_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_ERROR_H +#define LLVM_TOOLS_LLVM_READOBJ_ERROR_H #include diff --git a/tools/llvm-readobj/MachODumper.cpp b/tools/llvm-readobj/MachODumper.cpp index a5e5cf8..7e8fdad 100644 --- a/tools/llvm-readobj/MachODumper.cpp +++ b/tools/llvm-readobj/MachODumper.cpp @@ -31,14 +31,17 @@ public: : ObjDumper(Writer) , Obj(Obj) { } - virtual void printFileHeaders() override; - virtual void printSections() override; - virtual void printRelocations() override; - virtual void printSymbols() override; - virtual void printDynamicSymbols() override; - virtual void printUnwindInfo() override; + void printFileHeaders() override; + void printSections() override; + void printRelocations() override; + void printSymbols() override; + void printDynamicSymbols() override; + void printUnwindInfo() override; private: + template + void printFileHeaders(const MachHeader &Header); + void printSymbol(const SymbolRef &Symbol); void printRelocation(const RelocationRef &Reloc); @@ -68,6 +71,137 @@ std::error_code createMachODumper(const object::ObjectFile *Obj, } // namespace llvm +static const EnumEntry MachOMagics[] = { + { "Magic", MachO::MH_MAGIC }, + { "Cigam", MachO::MH_CIGAM }, + { "Magic64", MachO::MH_MAGIC_64 }, + { "Cigam64", MachO::MH_CIGAM_64 }, + { "FatMagic", MachO::FAT_MAGIC }, + { "FatCigam", MachO::FAT_CIGAM }, +}; + +static const EnumEntry MachOHeaderFileTypes[] = { + { "Relocatable", MachO::MH_OBJECT }, + { "Executable", MachO::MH_EXECUTE }, + { "FixedVMLibrary", MachO::MH_FVMLIB }, + { "Core", MachO::MH_CORE }, + { "PreloadedExecutable", MachO::MH_PRELOAD }, + { "DynamicLibrary", MachO::MH_DYLIB }, + { "DynamicLinker", MachO::MH_DYLINKER }, + { "Bundle", MachO::MH_BUNDLE }, + { "DynamicLibraryStub", MachO::MH_DYLIB_STUB }, + { "DWARFSymbol", MachO::MH_DSYM }, + { "KextBundle", MachO::MH_KEXT_BUNDLE }, +}; + +static const EnumEntry MachOHeaderCpuTypes[] = { + { "Any" , static_cast(MachO::CPU_TYPE_ANY) }, + { "X86" , MachO::CPU_TYPE_X86 }, + { "X86-64" , MachO::CPU_TYPE_X86_64 }, + { "Mc98000" , MachO::CPU_TYPE_MC98000 }, + { "Arm" , MachO::CPU_TYPE_ARM }, + { "Arm64" , MachO::CPU_TYPE_ARM64 }, + { "Sparc" , MachO::CPU_TYPE_SPARC }, + { "PowerPC" , MachO::CPU_TYPE_POWERPC }, + { "PowerPC64" , MachO::CPU_TYPE_POWERPC64 }, +}; + +static const EnumEntry MachOHeaderCpuSubtypesX86[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_I386_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_386), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_486SX), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_586), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTPRO), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M3), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTII_M5), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_CELERON_MOBILE), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_3_XEON), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_PENTIUM_4_M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ITANIUM_2), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_XEON_MP), +}; + +static const EnumEntry MachOHeaderCpuSubtypesX64[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_ARCH1), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_X86_64_H), +}; + +static const EnumEntry MachOHeaderCpuSubtypesARM[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V4T), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V5TEJ), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_XSCALE), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7S), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7K), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V6M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7M), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM_V7EM), +}; + +static const EnumEntry MachOHeaderCpuSubtypesARM64[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_ARM64_ALL), +}; + +static const EnumEntry MachOHeaderCpuSubtypesSPARC[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_SPARC_ALL), +}; + +static const EnumEntry MachOHeaderCpuSubtypesPPC[] = { + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_ALL), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_601), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_602), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603e), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_603ev), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_604e), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_620), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_750), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7400), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_7450), + LLVM_READOBJ_ENUM_ENT(MachO, CPU_SUBTYPE_POWERPC_970), +}; + +static const EnumEntry MachOHeaderFlags[] = { + LLVM_READOBJ_ENUM_ENT(MachO, MH_NOUNDEFS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_INCRLINK), + LLVM_READOBJ_ENUM_ENT(MachO, MH_DYLDLINK), + LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDATLOAD), + LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBOUND), + LLVM_READOBJ_ENUM_ENT(MachO, MH_SPLIT_SEGS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_LAZY_INIT), + LLVM_READOBJ_ENUM_ENT(MachO, MH_TWOLEVEL), + LLVM_READOBJ_ENUM_ENT(MachO, MH_FORCE_FLAT), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NOMULTIDEFS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NOFIXPREBINDING), + LLVM_READOBJ_ENUM_ENT(MachO, MH_PREBINDABLE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLMODSBOUND), + LLVM_READOBJ_ENUM_ENT(MachO, MH_SUBSECTIONS_VIA_SYMBOLS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_CANONICAL), + LLVM_READOBJ_ENUM_ENT(MachO, MH_WEAK_DEFINES), + LLVM_READOBJ_ENUM_ENT(MachO, MH_BINDS_TO_WEAK), + LLVM_READOBJ_ENUM_ENT(MachO, MH_ALLOW_STACK_EXECUTION), + LLVM_READOBJ_ENUM_ENT(MachO, MH_ROOT_SAFE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_SETUID_SAFE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_REEXPORTED_DYLIBS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_PIE), + LLVM_READOBJ_ENUM_ENT(MachO, MH_DEAD_STRIPPABLE_DYLIB), + LLVM_READOBJ_ENUM_ENT(MachO, MH_HAS_TLV_DESCRIPTORS), + LLVM_READOBJ_ENUM_ENT(MachO, MH_NO_HEAP_EXECUTION), + LLVM_READOBJ_ENUM_ENT(MachO, MH_APP_EXTENSION_SAFE), +}; static const EnumEntry MachOSectionTypes[] = { { "Regular" , 0x00 }, @@ -205,7 +339,47 @@ static void getSymbol(const MachOObjectFile *Obj, } void MachODumper::printFileHeaders() { - W.startLine() << "FileHeaders not implemented.\n"; + DictScope H(W, "MachHeader"); + if (!Obj->is64Bit()) { + printFileHeaders(Obj->getHeader()); + } else { + printFileHeaders(Obj->getHeader64()); + W.printHex("Reserved", Obj->getHeader64().reserved); + } +} + +template +void MachODumper::printFileHeaders(const MachHeader &Header) { + W.printEnum("Magic", Header.magic, makeArrayRef(MachOMagics)); + W.printEnum("CpuType", Header.cputype, makeArrayRef(MachOHeaderCpuTypes)); + uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK; + switch (Header.cputype) { + case MachO::CPU_TYPE_X86: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX86)); + break; + case MachO::CPU_TYPE_X86_64: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX64)); + break; + case MachO::CPU_TYPE_ARM: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM)); + break; + case MachO::CPU_TYPE_POWERPC: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesPPC)); + break; + case MachO::CPU_TYPE_SPARC: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesSPARC)); + break; + case MachO::CPU_TYPE_ARM64: + W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM64)); + break; + case MachO::CPU_TYPE_POWERPC64: + default: + W.printHex("CpuSubtype", subtype); + } + W.printEnum("FileType", Header.filetype, makeArrayRef(MachOHeaderFileTypes)); + W.printNumber("NumOfLoadCommands", Header.ncmds); + W.printNumber("SizeOfLoadCommands", Header.sizeofcmds); + W.printFlags("Flags", Header.flags, makeArrayRef(MachOHeaderFlags)); } void MachODumper::printSections() { @@ -257,8 +431,7 @@ void MachODumper::printSections(const MachOObjectFile *Obj) { if (opts::SectionSymbols) { ListScope D(W, "Symbols"); for (const SymbolRef &Symbol : Obj->symbols()) { - bool Contained = false; - if (Section.containsSymbol(Symbol, Contained) || !Contained) + if (!Section.containsSymbol(Symbol)) continue; printSymbol(Symbol); @@ -266,11 +439,14 @@ void MachODumper::printSections(const MachOObjectFile *Obj) { } if (opts::SectionData) { - StringRef Data; - if (error(Section.getContents(Data))) - break; + bool IsBSS = Section.isBSS(); + if (!IsBSS) { + StringRef Data; + if (error(Section.getContents(Data))) + break; - W.printBinaryBlock("SectionData", Data); + W.printBinaryBlock("SectionData", Data); + } } } } diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index f80a28b..27e658f 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_READOBJ_OBJDUMPER_H -#define LLVM_READOBJ_OBJDUMPER_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_OBJDUMPER_H +#define LLVM_TOOLS_LLVM_READOBJ_OBJDUMPER_H #include #include @@ -43,6 +43,12 @@ public: // Only implemented for MIPS ELF at this time. virtual void printMipsPLTGOT() { } + // Only implemented for PE/COFF. + virtual void printCOFFImports() { } + virtual void printCOFFExports() { } + virtual void printCOFFDirectives() { } + virtual void printCOFFBaseReloc() { } + protected: StreamWriter& W; }; diff --git a/tools/llvm-readobj/StreamWriter.h b/tools/llvm-readobj/StreamWriter.h index 04b38fb..2fc53ee 100644 --- a/tools/llvm-readobj/StreamWriter.h +++ b/tools/llvm-readobj/StreamWriter.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_READOBJ_STREAMWRITER_H -#define LLVM_READOBJ_STREAMWRITER_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_STREAMWRITER_H +#define LLVM_TOOLS_LLVM_READOBJ_STREAMWRITER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" @@ -214,8 +214,8 @@ public: } void printBinary(StringRef Label, StringRef Str, ArrayRef Value) { - ArrayRef V(reinterpret_cast(Value.data()), - Value.size()); + auto V = makeArrayRef(reinterpret_cast(Value.data()), + Value.size()); printBinaryImpl(Label, Str, V, false); } @@ -224,20 +224,20 @@ public: } void printBinary(StringRef Label, ArrayRef Value) { - ArrayRef V(reinterpret_cast(Value.data()), - Value.size()); + auto V = makeArrayRef(reinterpret_cast(Value.data()), + Value.size()); printBinaryImpl(Label, StringRef(), V, false); } void printBinary(StringRef Label, StringRef Value) { - ArrayRef V(reinterpret_cast(Value.data()), - Value.size()); + auto V = makeArrayRef(reinterpret_cast(Value.data()), + Value.size()); printBinaryImpl(Label, StringRef(), V, false); } void printBinaryBlock(StringRef Label, StringRef Value) { - ArrayRef V(reinterpret_cast(Value.data()), - Value.size()); + auto V = makeArrayRef(reinterpret_cast(Value.data()), + Value.size()); printBinaryImpl(Label, StringRef(), V, true); } diff --git a/tools/llvm-readobj/Win64EHDumper.h b/tools/llvm-readobj/Win64EHDumper.h index 9ce4d39..a80df9c 100644 --- a/tools/llvm-readobj/Win64EHDumper.h +++ b/tools/llvm-readobj/Win64EHDumper.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_READOBJ_WIN64EHPRINTER_H -#define LLVM_TOOLS_READOBJ_WIN64EHPRINTER_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_WIN64EHDUMPER_H +#define LLVM_TOOLS_LLVM_READOBJ_WIN64EHDUMPER_H #include "StreamWriter.h" #include "llvm/Support/Win64EH.h" diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index 8d2a997..f95fea8 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -24,6 +24,7 @@ #include "ObjDumper.h" #include "StreamWriter.h" #include "llvm/Object/Archive.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" @@ -140,6 +141,24 @@ namespace opts { cl::opt MipsPLTGOT("mips-plt-got", cl::desc("Display the MIPS GOT and PLT GOT sections")); + + // -coff-imports + cl::opt + COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); + + // -coff-exports + cl::opt + COFFExports("coff-exports", cl::desc("Display the PE/COFF export table")); + + // -coff-directives + cl::opt + COFFDirectives("coff-directives", + cl::desc("Display the PE/COFF .drectve section")); + + // -coff-basereloc + cl::opt + COFFBaseRelocs("coff-basereloc", + cl::desc("Display the PE/COFF .reloc section")); } // namespace opts static int ReturnValue = EXIT_SUCCESS; @@ -158,8 +177,8 @@ bool error(std::error_code EC) { bool relocAddressLess(RelocationRef a, RelocationRef b) { uint64_t a_addr, b_addr; - if (error(a.getOffset(a_addr))) return false; - if (error(b.getOffset(b_addr))) return false; + if (error(a.getOffset(a_addr))) exit(ReturnValue); + if (error(b.getOffset(b_addr))) exit(ReturnValue); return a_addr < b_addr; } @@ -210,6 +229,17 @@ static std::error_code createDumper(const ObjectFile *Obj, StreamWriter &Writer, return readobj_error::unsupported_obj_file_format; } +static StringRef getLoadName(const ObjectFile *Obj) { + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + if (auto *ELF = dyn_cast(Obj)) + return ELF->getLoadName(); + llvm_unreachable("Not ELF"); +} /// @brief Dumps the specified object file. static void dumpObject(const ObjectFile *Obj) { @@ -228,7 +258,7 @@ static void dumpObject(const ObjectFile *Obj) { << "\n"; outs() << "AddressSize: " << (8*Obj->getBytesInAddress()) << "bit\n"; if (Obj->isELF()) - outs() << "LoadName: " << Obj->getLoadName() << "\n"; + outs() << "LoadName: " << getLoadName(Obj) << "\n"; if (opts::FileHeaders) Dumper->printFileHeaders(); @@ -254,6 +284,14 @@ static void dumpObject(const ObjectFile *Obj) { if (isMipsArch(Obj->getArch()) && Obj->isELF()) if (opts::MipsPLTGOT) Dumper->printMipsPLTGOT(); + if (opts::COFFImports) + Dumper->printCOFFImports(); + if (opts::COFFExports) + Dumper->printCOFFExports(); + if (opts::COFFDirectives) + Dumper->printCOFFDirectives(); + if (opts::COFFBaseRelocs) + Dumper->printCOFFBaseReloc(); } @@ -287,16 +325,16 @@ static void dumpInput(StringRef File) { } // Attempt to open the binary. - ErrorOr BinaryOrErr = createBinary(File); + ErrorOr> BinaryOrErr = createBinary(File); if (std::error_code EC = BinaryOrErr.getError()) { reportError(File, EC); return; } - std::unique_ptr Binary(BinaryOrErr.get()); + Binary &Binary = *BinaryOrErr.get().getBinary(); - if (Archive *Arc = dyn_cast(Binary.get())) + if (Archive *Arc = dyn_cast(&Binary)) dumpArchive(Arc); - else if (ObjectFile *Obj = dyn_cast(Binary.get())) + else if (ObjectFile *Obj = dyn_cast(&Binary)) dumpObject(Obj); else reportError(File, readobj_error::unrecognized_file_format); diff --git a/tools/llvm-readobj/llvm-readobj.h b/tools/llvm-readobj/llvm-readobj.h index 0413948..1c33417 100644 --- a/tools/llvm-readobj/llvm-readobj.h +++ b/tools/llvm-readobj/llvm-readobj.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_READ_OBJ_H -#define LLVM_TOOLS_READ_OBJ_H +#ifndef LLVM_TOOLS_LLVM_READOBJ_LLVM_READOBJ_H +#define LLVM_TOOLS_LLVM_READOBJ_LLVM_READOBJ_H #include "llvm/Support/CommandLine.h" #include diff --git a/tools/llvm-rtdyld/CMakeLists.txt b/tools/llvm-rtdyld/CMakeLists.txt index feb2134..e294760 100644 --- a/tools/llvm-rtdyld/CMakeLists.txt +++ b/tools/llvm-rtdyld/CMakeLists.txt @@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS DebugInfo ExecutionEngine MC + Object RuntimeDyld Support ) diff --git a/tools/llvm-rtdyld/LLVMBuild.txt b/tools/llvm-rtdyld/LLVMBuild.txt index b36d13c..c4ed49b 100644 --- a/tools/llvm-rtdyld/LLVMBuild.txt +++ b/tools/llvm-rtdyld/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Tool name = llvm-rtdyld parent = Tools -required_libraries = JIT MC Object RuntimeDyld Support all-targets +required_libraries = MC Object RuntimeDyld Support all-targets diff --git a/tools/llvm-rtdyld/Makefile b/tools/llvm-rtdyld/Makefile index fabdd68..9de753e 100644 --- a/tools/llvm-rtdyld/Makefile +++ b/tools/llvm-rtdyld/Makefile @@ -9,7 +9,7 @@ LEVEL := ../.. TOOLNAME := llvm-rtdyld -LINK_COMPONENTS := all-targets support MC object RuntimeDyld JIT debuginfo +LINK_COMPONENTS := all-targets support MC object RuntimeDyld MCJIT debuginfo # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS := 1 diff --git a/tools/llvm-rtdyld/llvm-rtdyld.cpp b/tools/llvm-rtdyld/llvm-rtdyld.cpp index 45734f4..5b6f301 100644 --- a/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -13,15 +13,13 @@ #include "llvm/ADT/StringMap.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/ExecutionEngine/ObjectBuffer.h" -#include "llvm/ExecutionEngine/ObjectImage.h" #include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/ExecutionEngine/RuntimeDyldChecker.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCDisassembler.h" -#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCInstPrinter.h" +#include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/Object/MachO.h" #include "llvm/Support/CommandLine.h" @@ -30,10 +28,11 @@ #include "llvm/Support/Memory.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/raw_ostream.h" +#include #include using namespace llvm; @@ -78,6 +77,31 @@ CheckFiles("check", cl::desc("File containing RuntimeDyld verifier checks."), cl::ZeroOrMore); +static cl::opt +TargetAddrStart("target-addr-start", + cl::desc("For -verify only: start of phony target address " + "range."), + cl::init(4096), // Start at "page 1" - no allocating at "null". + cl::Hidden); + +static cl::opt +TargetAddrEnd("target-addr-end", + cl::desc("For -verify only: end of phony target address range."), + cl::init(~0ULL), + cl::Hidden); + +static cl::opt +TargetSectionSep("target-section-sep", + cl::desc("For -verify only: Separation between sections in " + "phony target address space."), + cl::init(0), + cl::Hidden); + +static cl::list +SpecificSectionMappings("map-section", + cl::desc("Map a section to a specific address."), + cl::ZeroOrMore); + /* *** */ // A trivial memory manager that doesn't do anything fancy, just uses the @@ -181,23 +205,32 @@ static int printLineInfoForInput() { if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); - std::unique_ptr LoadedObject; + ErrorOr> MaybeObj( + ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); + + if (std::error_code EC = MaybeObj.getError()) + return Error("unable to create object file: '" + EC.message() + "'"); + + ObjectFile &Obj = **MaybeObj; + // Load the object file - LoadedObject.reset( - Dyld.loadObject(new ObjectBuffer(InputBuffer.get().release()))); - if (!LoadedObject) { + std::unique_ptr LoadedObjInfo = + Dyld.loadObject(Obj); + + if (Dyld.hasError()) return Error(Dyld.getErrorString()); - } // Resolve all the relocations we can. Dyld.resolveRelocations(); + OwningBinary DebugObj = LoadedObjInfo->getObjectForDebug(Obj); + std::unique_ptr Context( - DIContext::getDWARFContext(LoadedObject->getObjectFile())); + DIContext::getDWARFContext(*DebugObj.getBinary())); // Use symbol info to iterate functions in the object. - for (object::symbol_iterator I = LoadedObject->begin_symbols(), - E = LoadedObject->end_symbols(); + for (object::symbol_iterator I = DebugObj.getBinary()->symbol_begin(), + E = DebugObj.getBinary()->symbol_end(); I != E; ++I) { object::SymbolRef::Type SymType; if (I->getType(SymType)) continue; @@ -242,11 +275,17 @@ static int executeInput() { MemoryBuffer::getFileOrSTDIN(InputFileList[i]); if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); - std::unique_ptr LoadedObject; + ErrorOr> MaybeObj( + ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); + + if (std::error_code EC = MaybeObj.getError()) + return Error("unable to create object file: '" + EC.message() + "'"); + + ObjectFile &Obj = **MaybeObj; + // Load the object file - LoadedObject.reset( - Dyld.loadObject(new ObjectBuffer(InputBuffer.get().release()))); - if (!LoadedObject) { + Dyld.loadObject(Obj); + if (Dyld.hasError()) { return Error(Dyld.getErrorString()); } } @@ -300,6 +339,134 @@ static int checkAllExpressions(RuntimeDyldChecker &Checker) { return 0; } +std::map +applySpecificSectionMappings(RuntimeDyldChecker &Checker) { + + std::map SpecificMappings; + + for (StringRef Mapping : SpecificSectionMappings) { + + size_t EqualsIdx = Mapping.find_first_of("="); + StringRef SectionIDStr = Mapping.substr(0, EqualsIdx); + size_t ComaIdx = Mapping.find_first_of(","); + + if (ComaIdx == StringRef::npos) { + errs() << "Invalid section specification '" << Mapping + << "'. Should be ',
='\n"; + exit(1); + } + + StringRef FileName = SectionIDStr.substr(0, ComaIdx); + StringRef SectionName = SectionIDStr.substr(ComaIdx + 1); + + uint64_t OldAddrInt; + std::string ErrorMsg; + std::tie(OldAddrInt, ErrorMsg) = + Checker.getSectionAddr(FileName, SectionName, true); + + if (ErrorMsg != "") { + errs() << ErrorMsg; + exit(1); + } + + void* OldAddr = reinterpret_cast(static_cast(OldAddrInt)); + + StringRef NewAddrStr = Mapping.substr(EqualsIdx + 1); + uint64_t NewAddr; + + if (NewAddrStr.getAsInteger(0, NewAddr)) { + errs() << "Invalid section address in mapping: " << Mapping << "\n"; + exit(1); + } + + Checker.getRTDyld().mapSectionAddress(OldAddr, NewAddr); + SpecificMappings[OldAddr] = NewAddr; + } + + return SpecificMappings; +} + +// Scatter sections in all directions! +// Remaps section addresses for -verify mode. The following command line options +// can be used to customize the layout of the memory within the phony target's +// address space: +// -target-addr-start -- Specify where the phony target addres range starts. +// -target-addr-end -- Specify where the phony target address range ends. +// -target-section-sep -- Specify how big a gap should be left between the +// end of one section and the start of the next. +// Defaults to zero. Set to something big +// (e.g. 1 << 32) to stress-test stubs, GOTs, etc. +// +void remapSections(const llvm::Triple &TargetTriple, + const TrivialMemoryManager &MemMgr, + RuntimeDyldChecker &Checker) { + + // Set up a work list (section addr/size pairs). + typedef std::list> WorklistT; + WorklistT Worklist; + + for (const auto& CodeSection : MemMgr.FunctionMemory) + Worklist.push_back(std::make_pair(CodeSection.base(), CodeSection.size())); + for (const auto& DataSection : MemMgr.DataMemory) + Worklist.push_back(std::make_pair(DataSection.base(), DataSection.size())); + + // Apply any section-specific mappings that were requested on the command + // line. + typedef std::map AppliedMappingsT; + AppliedMappingsT AppliedMappings = applySpecificSectionMappings(Checker); + + // Keep an "already allocated" mapping of section target addresses to sizes. + // Sections whose address mappings aren't specified on the command line will + // allocated around the explicitly mapped sections while maintaining the + // minimum separation. + std::map AlreadyAllocated; + + // Move the previously applied mappings into the already-allocated map. + for (WorklistT::iterator I = Worklist.begin(), E = Worklist.end(); + I != E;) { + WorklistT::iterator Tmp = I; + ++I; + AppliedMappingsT::iterator AI = AppliedMappings.find(Tmp->first); + + if (AI != AppliedMappings.end()) { + AlreadyAllocated[AI->second] = Tmp->second; + Worklist.erase(Tmp); + } + } + + // If the -target-addr-end option wasn't explicitly passed, then set it to a + // sensible default based on the target triple. + if (TargetAddrEnd.getNumOccurrences() == 0) { + if (TargetTriple.isArch16Bit()) + TargetAddrEnd = (1ULL << 16) - 1; + else if (TargetTriple.isArch32Bit()) + TargetAddrEnd = (1ULL << 32) - 1; + // TargetAddrEnd already has a sensible default for 64-bit systems, so + // there's nothing to do in the 64-bit case. + } + + // Process any elements remaining in the worklist. + while (!Worklist.empty()) { + std::pair CurEntry = Worklist.front(); + Worklist.pop_front(); + + uint64_t NextSectionAddr = TargetAddrStart; + + for (const auto &Alloc : AlreadyAllocated) + if (NextSectionAddr + CurEntry.second + TargetSectionSep <= Alloc.first) + break; + else + NextSectionAddr = Alloc.first + Alloc.second + TargetSectionSep; + + AlreadyAllocated[NextSectionAddr] = CurEntry.second; + Checker.getRTDyld().mapSectionAddress(CurEntry.first, NextSectionAddr); + } + +} + +// Load and link the objects specified on the command line, but do not execute +// anything. Instead, attach a RuntimeDyldChecker instance and call it to +// verify the correctness of the linked memory. static int linkAndVerify() { // Check for missing triple. @@ -347,6 +514,9 @@ static int linkAndVerify() { // Instantiate a dynamic linker. TrivialMemoryManager MemMgr; RuntimeDyld Dyld(&MemMgr); + Dyld.setProcessAllSections(true); + RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(), + llvm::dbgs()); // If we don't have any input files, read from stdin. if (!InputFileList.size()) @@ -355,24 +525,42 @@ static int linkAndVerify() { // Load the input memory buffer. ErrorOr> InputBuffer = MemoryBuffer::getFileOrSTDIN(InputFileList[i]); + if (std::error_code EC = InputBuffer.getError()) return Error("unable to read input: '" + EC.message() + "'"); - std::unique_ptr LoadedObject; + ErrorOr> MaybeObj( + ObjectFile::createObjectFile((*InputBuffer)->getMemBufferRef())); + + if (std::error_code EC = MaybeObj.getError()) + return Error("unable to create object file: '" + EC.message() + "'"); + + ObjectFile &Obj = **MaybeObj; + // Load the object file - LoadedObject.reset( - Dyld.loadObject(new ObjectBuffer(InputBuffer.get().release()))); - if (!LoadedObject) { + Dyld.loadObject(Obj); + if (Dyld.hasError()) { return Error(Dyld.getErrorString()); } } + // Re-map the section addresses into the phony target address space. + remapSections(TheTriple, MemMgr, Checker); + // Resolve all the relocations we can. Dyld.resolveRelocations(); - RuntimeDyldChecker Checker(Dyld, Disassembler.get(), InstPrinter.get(), - llvm::dbgs()); - return checkAllExpressions(Checker); + // Register EH frames. + Dyld.registerEHFrames(); + + int ErrorCode = checkAllExpressions(Checker); + if (Dyld.hasError()) { + errs() << "RTDyld reported an error applying relocations:\n " + << Dyld.getErrorString() << "\n"; + ErrorCode = 1; + } + + return ErrorCode; } int main(int argc, char **argv) { diff --git a/tools/llvm-shlib/CMakeLists.txt b/tools/llvm-shlib/CMakeLists.txt new file mode 100644 index 0000000..a896a8a --- /dev/null +++ b/tools/llvm-shlib/CMakeLists.txt @@ -0,0 +1,100 @@ +# This tool creates a shared library from the LLVM libraries. Generating this +# library is enabled by setting LLVM_BUILD_LLVM_DYLIB=yes on the CMake +# commandline. By default the shared library only exports the LLVM C API. + + +# You can configure which libraries from LLVM you want to include in the shared +# library by setting LLVM_DYLIB_COMPONENTS to a semi-colon delimited list of +# LLVM components. All compoenent names handled by llvm-config are valid. + +if(NOT DEFINED LLVM_DYLIB_COMPONENTS) + set(LLVM_DYLIB_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + Analysis + BitReader + BitWriter + CodeGen + Core + ExecutionEngine + IPA + IPO + IRReader + InstCombine + Instrumentation + Interpreter + Linker + MCDisassembler + MCJIT + ObjCARCOpts + Object + ScalarOpts + Support + Target + TransformUtils + Vectorize + native + ) +endif() + +add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) + +set(SOURCES + libllvm.cpp + ) + +if(NOT DEFINED LLVM_EXPORTED_SYMBOL_FILE) + + if( WIN32 AND NOT CYGWIN ) + message(FATAL_ERROR "Auto-generation not implemented for Win32 without GNU utils. Please specify LLVM_EXPORTED_SYMBOL_FILE.") + endif() + + # To get the export list for a single llvm library: + # nm ${LIB_PATH} | awk "/T _LLVM/ { print $3 }" | sort -u | sed -e "s/^_//g" > ${LIB_PATH}.exports + + set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_BINARY_DIR}/libllvm.exports) + + llvm_map_components_to_libnames(LIB_NAMES ${LLVM_DYLIB_COMPONENTS}) + + foreach (lib ${LIB_NAMES}) + + set(LIB_DIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) + set(LIB_NAME ${LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}${lib}) + set(LIB_PATH ${LIB_NAME}${CMAKE_STATIC_LIBRARY_SUFFIX}) + set(LIB_EXPORTS_PATH ${LIB_NAME}.exports) + + list(APPEND LLVM_DYLIB_REQUIRED_EXPORTS ${LIB_EXPORTS_PATH}) + + add_custom_command(OUTPUT ${LIB_EXPORTS_PATH} + COMMAND nm ${LIB_PATH} | awk "/T _LLVM/ || /T LLVM/ { print $3 }" | sort -u | sed -e "s/^_//g" > ${LIB_EXPORTS_PATH} + WORKING_DIRECTORY ${LIB_DIR} + DEPENDS ${lib} + COMMENT "Generating Export list for ${lib}..." + VERBATIM ) + endforeach () + + add_custom_command(OUTPUT ${LLVM_EXPORTED_SYMBOL_FILE} + COMMAND cat ${LLVM_DYLIB_REQUIRED_EXPORTS} > ${LLVM_EXPORTED_SYMBOL_FILE} + WORKING_DIRECTORY ${LIB_DIR} + DEPENDS ${LLVM_DYLIB_REQUIRED_EXPORTS} + COMMENT "Generating combined export list...") + +endif() + +add_llvm_library(LLVM SHARED ${SOURCES}) + +if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") # FIXME: It should be "GNU ld for elf" + # GNU ld doesn't resolve symbols in the version script. + list(REMOVE_DUPLICATES LIB_NAMES) + set(LIB_NAMES -Wl,--whole-archive ${LIB_NAMES} -Wl,--no-whole-archive) +endif() + +target_link_libraries(LLVM ${cmake_2_8_12_PRIVATE} ${LIB_NAMES}) + +add_dependencies(LLVM ${LLVM_EXPORTED_SYMBOL_FILE}) + +if (APPLE) + set_property(TARGET LLVM APPEND_STRING PROPERTY + LINK_FLAGS + " -compatibility_version ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR} -current_version ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}") +endif() + diff --git a/tools/llvm-shlib/libllvm.cpp b/tools/llvm-shlib/libllvm.cpp new file mode 100644 index 0000000..8424d660 --- /dev/null +++ b/tools/llvm-shlib/libllvm.cpp @@ -0,0 +1,20 @@ +//===-libllvm.cpp - LLVM Shared Library -----------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is empty and serves only the purpose of making CMake happy because +// you can't define a target with no sources. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Config/config.h" + +#if defined(DISABLE_LLVM_DYLIB_ATEXIT) +extern "C" int __cxa_atexit(); +extern "C" int __cxa_atexit() { return 0; } +#endif diff --git a/tools/llvm-size/llvm-size.cpp b/tools/llvm-size/llvm-size.cpp index 50b5220..fc211e3 100644 --- a/tools/llvm-size/llvm-size.cpp +++ b/tools/llvm-size/llvm-size.cpp @@ -15,9 +15,9 @@ #include "llvm/ADT/APInt.h" #include "llvm/Object/Archive.h" -#include "llvm/Object/ObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/MachOUniversal.h" +#include "llvm/Object/ObjectFile.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" @@ -297,17 +297,13 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { std::size_t max_size_len = strlen("size"); std::size_t max_addr_len = strlen("addr"); for (const SectionRef &Section : Obj->sections()) { - uint64_t size = 0; - if (error(Section.getSize(size))) - return; + uint64_t size = Section.getSize(); total += size; StringRef name; - uint64_t addr = 0; if (error(Section.getName(name))) return; - if (error(Section.getAddress(addr))) - return; + uint64_t addr = Section.getAddress(); max_name_len = std::max(max_name_len, name.size()); max_size_len = std::max(max_size_len, getNumLengthAsString(size)); max_addr_len = std::max(max_addr_len, getNumLengthAsString(addr)); @@ -337,14 +333,10 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { // Print each section. for (const SectionRef &Section : Obj->sections()) { StringRef name; - uint64_t size = 0; - uint64_t addr = 0; if (error(Section.getName(name))) return; - if (error(Section.getSize(size))) - return; - if (error(Section.getAddress(addr))) - return; + uint64_t size = Section.getSize(); + uint64_t addr = Section.getAddress(); std::string namestr = name; outs() << format(fmt.str().c_str(), namestr.c_str(), size, addr); @@ -365,18 +357,10 @@ static void PrintObjectSectionSizes(ObjectFile *Obj) { // Make one pass over the section table to calculate sizes. for (const SectionRef &Section : Obj->sections()) { - uint64_t size = 0; - bool isText = false; - bool isData = false; - bool isBSS = false; - if (error(Section.getSize(size))) - return; - if (error(Section.isText(isText))) - return; - if (error(Section.isData(isData))) - return; - if (error(Section.isBSS(isBSS))) - return; + uint64_t size = Section.getSize(); + bool isText = Section.isText(); + bool isData = Section.isData(); + bool isBSS = Section.isBSS(); if (isText) total_text += size; else if (isData) @@ -444,8 +428,7 @@ static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) { static void PrintFileSectionSizes(StringRef file) { // If file is not stdin, check that it exists. if (file != "-") { - bool exists; - if (sys::fs::exists(file, exists) || !exists) { + if (!sys::fs::exists(file)) { errs() << ToolName << ": '" << file << "': " << "No such file\n"; return; @@ -453,14 +436,14 @@ static void PrintFileSectionSizes(StringRef file) { } // Attempt to open the binary. - ErrorOr BinaryOrErr = createBinary(file); + ErrorOr> BinaryOrErr = createBinary(file); if (std::error_code EC = BinaryOrErr.getError()) { errs() << ToolName << ": " << file << ": " << EC.message() << ".\n"; return; } - std::unique_ptr binary(BinaryOrErr.get()); + Binary &Bin = *BinaryOrErr.get().getBinary(); - if (Archive *a = dyn_cast(binary.get())) { + if (Archive *a = dyn_cast(&Bin)) { // This is an archive. Iterate over each member and display its sizes. for (object::Archive::child_iterator i = a->child_begin(), e = a->child_end(); @@ -488,7 +471,7 @@ static void PrintFileSectionSizes(StringRef file) { } } } else if (MachOUniversalBinary *UB = - dyn_cast(binary.get())) { + dyn_cast(&Bin)) { // If we have a list of architecture flags specified dump only those. if (!ArchAll && ArchFlags.size() != 0) { // Look for a slice in the universal binary that matches each ArchFlag. @@ -501,7 +484,6 @@ static void PrintFileSectionSizes(StringRef file) { if (ArchFlags[i] == I->getArchTypeName()) { ArchFound = true; ErrorOr> UO = I->getAsObjectFile(); - std::unique_ptr UA; if (UO) { if (ObjectFile *o = dyn_cast(&*UO.get())) { MachOObjectFile *MachO = dyn_cast(o); @@ -520,7 +502,9 @@ static void PrintFileSectionSizes(StringRef file) { outs() << "\n"; } } - } else if (!I->getAsArchive(UA)) { + } else if (ErrorOr> AOrErr = + I->getAsArchive()) { + std::unique_ptr &UA = *AOrErr; // This is an archive. Iterate over each member and display its // sizes. for (object::Archive::child_iterator i = UA->child_begin(), @@ -577,7 +561,6 @@ static void PrintFileSectionSizes(StringRef file) { I != E; ++I) { if (HostArchName == I->getArchTypeName()) { ErrorOr> UO = I->getAsObjectFile(); - std::unique_ptr UA; if (UO) { if (ObjectFile *o = dyn_cast(&*UO.get())) { MachOObjectFile *MachO = dyn_cast(o); @@ -596,7 +579,9 @@ static void PrintFileSectionSizes(StringRef file) { outs() << "\n"; } } - } else if (!I->getAsArchive(UA)) { + } else if (ErrorOr> AOrErr = + I->getAsArchive()) { + std::unique_ptr &UA = *AOrErr; // This is an archive. Iterate over each member and display its // sizes. for (object::Archive::child_iterator i = UA->child_begin(), @@ -640,7 +625,6 @@ static void PrintFileSectionSizes(StringRef file) { E = UB->end_objects(); I != E; ++I) { ErrorOr> UO = I->getAsObjectFile(); - std::unique_ptr UA; if (UO) { if (ObjectFile *o = dyn_cast(&*UO.get())) { MachOObjectFile *MachO = dyn_cast(o); @@ -660,7 +644,9 @@ static void PrintFileSectionSizes(StringRef file) { outs() << "\n"; } } - } else if (!I->getAsArchive(UA)) { + } else if (ErrorOr> AOrErr = + I->getAsArchive()) { + std::unique_ptr &UA = *AOrErr; // This is an archive. Iterate over each member and display its sizes. for (object::Archive::child_iterator i = UA->child_begin(), e = UA->child_end(); @@ -692,7 +678,7 @@ static void PrintFileSectionSizes(StringRef file) { } } } - } else if (ObjectFile *o = dyn_cast(binary.get())) { + } else if (ObjectFile *o = dyn_cast(&Bin)) { if (!checkMachOAndArchFlags(o, file)) return; if (OutputFormat == sysv) @@ -731,8 +717,7 @@ int main(int argc, char **argv) { if (ArchFlags[i] == "all") { ArchAll = true; } else { - Triple T = MachOObjectFile::getArch(ArchFlags[i]); - if (T.getArch() == Triple::UnknownArch) { + if (!MachOObjectFile::isValidArch(ArchFlags[i])) { outs() << ToolName << ": for the -arch option: Unknown architecture " << "named '" << ArchFlags[i] << "'"; return 1; diff --git a/tools/llvm-stress/llvm-stress.cpp b/tools/llvm-stress/llvm-stress.cpp index 23d3b63..21a79e3 100644 --- a/tools/llvm-stress/llvm-stress.cpp +++ b/tools/llvm-stress/llvm-stress.cpp @@ -704,11 +704,10 @@ int main(int argc, char **argv) { if (OutputFilename.empty()) OutputFilename = "-"; - std::string ErrorInfo; - Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, - sys::fs::F_None)); - if (!ErrorInfo.empty()) { - errs() << ErrorInfo << '\n'; + std::error_code EC; + Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); + if (EC) { + errs() << EC.message() << '\n'; return 1; } diff --git a/tools/llvm-symbolizer/LLVMSymbolize.cpp b/tools/llvm-symbolizer/LLVMSymbolize.cpp index c1d39ef..36061d7 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.cpp +++ b/tools/llvm-symbolizer/LLVMSymbolize.cpp @@ -45,8 +45,26 @@ getDILineInfoSpecifier(const LLVMSymbolizer::Options &Opts) { ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx) : Module(Obj), DebugInfoContext(DICtx) { + std::unique_ptr OpdExtractor; + uint64_t OpdAddress = 0; + // Find the .opd (function descriptor) section if any, for big-endian + // PowerPC64 ELF. + if (Module->getArch() == Triple::ppc64) { + for (section_iterator Section : Module->sections()) { + StringRef Name; + if (!error(Section->getName(Name)) && Name == ".opd") { + StringRef Data; + if (!error(Section->getContents(Data))) { + OpdExtractor.reset(new DataExtractor(Data, Module->isLittleEndian(), + Module->getBytesInAddress())); + OpdAddress = Section->getAddress(); + } + break; + } + } + } for (const SymbolRef &Symbol : Module->symbols()) { - addSymbol(Symbol); + addSymbol(Symbol, OpdExtractor.get(), OpdAddress); } bool NoSymbolTable = (Module->symbol_begin() == Module->symbol_end()); if (NoSymbolTable && Module->isELF()) { @@ -54,12 +72,13 @@ ModuleInfo::ModuleInfo(ObjectFile *Obj, DIContext *DICtx) std::pair IDyn = getELFDynamicSymbolIterators(Module); for (symbol_iterator si = IDyn.first, se = IDyn.second; si != se; ++si) { - addSymbol(*si); + addSymbol(*si, OpdExtractor.get(), OpdAddress); } } } -void ModuleInfo::addSymbol(const SymbolRef &Symbol) { +void ModuleInfo::addSymbol(const SymbolRef &Symbol, DataExtractor *OpdExtractor, + uint64_t OpdAddress) { SymbolRef::Type SymbolType; if (error(Symbol.getType(SymbolType))) return; @@ -69,6 +88,18 @@ void ModuleInfo::addSymbol(const SymbolRef &Symbol) { if (error(Symbol.getAddress(SymbolAddress)) || SymbolAddress == UnknownAddressOrSize) return; + if (OpdExtractor) { + // For big-endian PowerPC64 ELF, symbols in the .opd section refer to + // function descriptors. The first word of the descriptor is a pointer to + // the function's code. + // For the purposes of symbolization, pretend the symbol's address is that + // of the function's code, not the descriptor. + uint64_t OpdOffset = SymbolAddress - OpdAddress; + uint32_t OpdOffset32 = OpdOffset; + if (OpdOffset == OpdOffset32 && + OpdExtractor->isValidOffsetForAddress(OpdOffset32)) + SymbolAddress = OpdExtractor->getAddress(&OpdOffset32); + } uint64_t SymbolSize; // Getting symbol size is linear for Mach-O files, so assume that symbol // occupies the memory range up to the following symbol. @@ -85,7 +116,7 @@ void ModuleInfo::addSymbol(const SymbolRef &Symbol) { SymbolName = SymbolName.drop_front(); // FIXME: If a function has alias, there are two entries in symbol table // with same address size. Make sure we choose the correct one. - SymbolMapTy &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects; + auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects; SymbolDesc SD = { SymbolAddress, SymbolSize }; M.insert(std::make_pair(SD, SymbolName)); } @@ -93,19 +124,20 @@ void ModuleInfo::addSymbol(const SymbolRef &Symbol) { bool ModuleInfo::getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address, std::string &Name, uint64_t &Addr, uint64_t &Size) const { - const SymbolMapTy &M = Type == SymbolRef::ST_Function ? Functions : Objects; - if (M.empty()) + const auto &SymbolMap = Type == SymbolRef::ST_Function ? Functions : Objects; + if (SymbolMap.empty()) return false; SymbolDesc SD = { Address, Address }; - SymbolMapTy::const_iterator it = M.upper_bound(SD); - if (it == M.begin()) + auto SymbolIterator = SymbolMap.upper_bound(SD); + if (SymbolIterator == SymbolMap.begin()) return false; - --it; - if (it->first.Size != 0 && it->first.Addr + it->first.Size <= Address) + --SymbolIterator; + if (SymbolIterator->first.Size != 0 && + SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address) return false; - Name = it->second.str(); - Addr = it->first.Addr; - Size = it->first.Size; + Name = SymbolIterator->second.str(); + Addr = SymbolIterator->first.Addr; + Size = SymbolIterator->first.Size; return true; } @@ -206,14 +238,21 @@ std::string LLVMSymbolizer::symbolizeData(const std::string &ModuleName, void LLVMSymbolizer::flush() { DeleteContainerSeconds(Modules); - BinaryForPath.clear(); + ObjectPairForPathArch.clear(); ObjectFileForArch.clear(); } -static std::string getDarwinDWARFResourceForPath(const std::string &Path) { - StringRef Basename = sys::path::filename(Path); - const std::string &DSymDirectory = Path + ".dSYM"; - SmallString<16> ResourceName = StringRef(DSymDirectory); +// For Path="/path/to/foo" and Basename="foo" assume that debug info is in +// /path/to/foo.dSYM/Contents/Resources/DWARF/foo. +// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in +// /path/to/bar.dSYM/Contents/Resources/DWARF/foo. +static +std::string getDarwinDWARFResourceForPath( + const std::string &Path, const std::string &Basename) { + SmallString<16> ResourceName = StringRef(Path); + if (sys::path::extension(Path) != ".dSYM") { + ResourceName += ".dSYM"; + } sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); sys::path::append(ResourceName, Basename); return ResourceName.str(); @@ -264,9 +303,8 @@ static bool findDebugBinary(const std::string &OrigPath, return false; } -static bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName, +static bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName, uint32_t &CRCHash) { - const ObjectFile *Obj = dyn_cast(Bin); if (!Obj) return false; for (const SectionRef &Section : Obj->sections()) { @@ -293,60 +331,96 @@ static bool getGNUDebuglinkContents(const Binary *Bin, std::string &DebugName, return false; } -LLVMSymbolizer::BinaryPair -LLVMSymbolizer::getOrCreateBinary(const std::string &Path) { - BinaryMapTy::iterator I = BinaryForPath.find(Path); - if (I != BinaryForPath.end()) +static +bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj, + const MachOObjectFile *Obj) { + ArrayRef dbg_uuid = DbgObj->getUuid(); + ArrayRef bin_uuid = Obj->getUuid(); + if (dbg_uuid.empty() || bin_uuid.empty()) + return false; + return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size()); +} + +ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath, + const MachOObjectFile *MachExeObj, const std::string &ArchName) { + // On Darwin we may find DWARF in separate object file in + // resource directory. + std::vector DsymPaths; + StringRef Filename = sys::path::filename(ExePath); + DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename)); + for (const auto &Path : Opts.DsymHints) { + DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename)); + } + for (const auto &path : DsymPaths) { + ErrorOr> BinaryOrErr = createBinary(path); + std::error_code EC = BinaryOrErr.getError(); + if (EC != errc::no_such_file_or_directory && !error(EC)) { + OwningBinary B = std::move(BinaryOrErr.get()); + ObjectFile *DbgObj = + getObjectFileFromBinary(B.getBinary(), ArchName); + const MachOObjectFile *MachDbgObj = + dyn_cast(DbgObj); + if (!MachDbgObj) continue; + if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj)) { + addOwningBinary(std::move(B)); + return DbgObj; + } + } + } + return nullptr; +} + +LLVMSymbolizer::ObjectPair +LLVMSymbolizer::getOrCreateObjects(const std::string &Path, + const std::string &ArchName) { + const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName)); + if (I != ObjectPairForPathArch.end()) return I->second; - Binary *Bin = nullptr; - Binary *DbgBin = nullptr; - ErrorOr BinaryOrErr = createBinary(Path); + ObjectFile *Obj = nullptr; + ObjectFile *DbgObj = nullptr; + ErrorOr> BinaryOrErr = createBinary(Path); if (!error(BinaryOrErr.getError())) { - std::unique_ptr ParsedBinary(BinaryOrErr.get()); - // Check if it's a universal binary. - Bin = ParsedBinary.get(); - ParsedBinariesAndObjects.push_back(std::move(ParsedBinary)); - if (Bin->isMachO() || Bin->isMachOUniversalBinary()) { - // On Darwin we may find DWARF in separate object file in - // resource directory. - const std::string &ResourcePath = - getDarwinDWARFResourceForPath(Path); - BinaryOrErr = createBinary(ResourcePath); - std::error_code EC = BinaryOrErr.getError(); - if (EC != errc::no_such_file_or_directory && !error(EC)) { - DbgBin = BinaryOrErr.get(); - ParsedBinariesAndObjects.push_back(std::unique_ptr(DbgBin)); - } + OwningBinary &B = BinaryOrErr.get(); + Obj = getObjectFileFromBinary(B.getBinary(), ArchName); + if (!Obj) { + ObjectPair Res = std::make_pair(nullptr, nullptr); + ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; + return Res; } + addOwningBinary(std::move(B)); + if (auto MachObj = dyn_cast(Obj)) + DbgObj = lookUpDsymFile(Path, MachObj, ArchName); // Try to locate the debug binary using .gnu_debuglink section. - if (!DbgBin) { + if (!DbgObj) { std::string DebuglinkName; uint32_t CRCHash; std::string DebugBinaryPath; - if (getGNUDebuglinkContents(Bin, DebuglinkName, CRCHash) && + if (getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash) && findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath)) { BinaryOrErr = createBinary(DebugBinaryPath); if (!error(BinaryOrErr.getError())) { - DbgBin = BinaryOrErr.get(); - ParsedBinariesAndObjects.push_back(std::unique_ptr(DbgBin)); + OwningBinary B = std::move(BinaryOrErr.get()); + DbgObj = getObjectFileFromBinary(B.getBinary(), ArchName); + addOwningBinary(std::move(B)); } } } } - if (!DbgBin) - DbgBin = Bin; - BinaryPair Res = std::make_pair(Bin, DbgBin); - BinaryForPath[Path] = Res; + if (!DbgObj) + DbgObj = Obj; + ObjectPair Res = std::make_pair(Obj, DbgObj); + ObjectPairForPathArch[std::make_pair(Path, ArchName)] = Res; return Res; } ObjectFile * -LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName) { +LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, + const std::string &ArchName) { if (!Bin) return nullptr; ObjectFile *Res = nullptr; if (MachOUniversalBinary *UB = dyn_cast(Bin)) { - ObjectFileForArchMapTy::iterator I = ObjectFileForArch.find( + const auto &I = ObjectFileForArch.find( std::make_pair(UB, ArchName)); if (I != ObjectFileForArch.end()) return I->second; @@ -365,7 +439,7 @@ LLVMSymbolizer::getObjectFileFromBinary(Binary *Bin, const std::string &ArchName ModuleInfo * LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { - ModuleMapTy::iterator I = Modules.find(ModuleName); + const auto &I = Modules.find(ModuleName); if (I != Modules.end()) return I->second; std::string BinaryName = ModuleName; @@ -379,18 +453,16 @@ LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) { ArchName = ArchStr; } } - BinaryPair Binaries = getOrCreateBinary(BinaryName); - ObjectFile *Obj = getObjectFileFromBinary(Binaries.first, ArchName); - ObjectFile *DbgObj = getObjectFileFromBinary(Binaries.second, ArchName); + ObjectPair Objects = getOrCreateObjects(BinaryName, ArchName); - if (!Obj) { + if (!Objects.first) { // Failed to find valid object file. Modules.insert(make_pair(ModuleName, (ModuleInfo *)nullptr)); return nullptr; } - DIContext *Context = DIContext::getDWARFContext(DbgObj); + DIContext *Context = DIContext::getDWARFContext(*Objects.second); assert(Context); - ModuleInfo *Info = new ModuleInfo(Obj, Context); + ModuleInfo *Info = new ModuleInfo(Objects.first, Context); Modules.insert(make_pair(ModuleName, Info)); return Info; } diff --git a/tools/llvm-symbolizer/LLVMSymbolize.h b/tools/llvm-symbolizer/LLVMSymbolize.h index 45febe0..ff848fc 100644 --- a/tools/llvm-symbolizer/LLVMSymbolize.h +++ b/tools/llvm-symbolizer/LLVMSymbolize.h @@ -10,13 +10,14 @@ // Header for LLVM symbolization library. // //===----------------------------------------------------------------------===// -#ifndef LLVM_SYMBOLIZE_H -#define LLVM_SYMBOLIZE_H +#ifndef LLVM_TOOLS_LLVM_SYMBOLIZER_LLVMSYMBOLIZE_H +#define LLVM_TOOLS_LLVM_SYMBOLIZER_LLVMSYMBOLIZE_H #include "llvm/ADT/SmallVector.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/Object/MachOUniversal.h" #include "llvm/Object/ObjectFile.h" +#include "llvm/Support/DataExtractor.h" #include "llvm/Support/MemoryBuffer.h" #include #include @@ -39,13 +40,14 @@ public: bool PrintInlining : 1; bool Demangle : 1; std::string DefaultArch; + std::vector DsymHints; Options(bool UseSymbolTable = true, FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName, bool PrintInlining = true, bool Demangle = true, std::string DefaultArch = "") - : UseSymbolTable(UseSymbolTable), PrintFunctions(PrintFunctions), - PrintInlining(PrintInlining), Demangle(Demangle), - DefaultArch(DefaultArch) {} + : UseSymbolTable(UseSymbolTable), + PrintFunctions(PrintFunctions), PrintInlining(PrintInlining), + Demangle(Demangle), DefaultArch(DefaultArch) {} }; LLVMSymbolizer(const Options &Opts = Options()) : Opts(Opts) {} @@ -62,11 +64,15 @@ public: void flush(); static std::string DemangleName(const std::string &Name); private: - typedef std::pair BinaryPair; + typedef std::pair ObjectPair; ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName); - /// \brief Returns pair of pointers to binary and debug binary. - BinaryPair getOrCreateBinary(const std::string &Path); + ObjectFile *lookUpDsymFile(const std::string &Path, const MachOObjectFile *ExeObj, + const std::string &ArchName); + + /// \brief Returns pair of pointers to object and debug object. + ObjectPair getOrCreateObjects(const std::string &Path, + const std::string &ArchName); /// \brief Returns a parsed object file for a given architecture in a /// universal binary (or the binary itself if it is an object file). ObjectFile *getObjectFileFromBinary(Binary *Bin, const std::string &ArchName); @@ -75,14 +81,21 @@ private: // Owns all the parsed binaries and object files. SmallVector, 4> ParsedBinariesAndObjects; + SmallVector, 4> MemoryBuffers; + void addOwningBinary(OwningBinary OwningBin) { + std::unique_ptr Bin; + std::unique_ptr MemBuf; + std::tie(Bin, MemBuf) = OwningBin.takeBinary(); + ParsedBinariesAndObjects.push_back(std::move(Bin)); + MemoryBuffers.push_back(std::move(MemBuf)); + } + // Owns module info objects. - typedef std::map ModuleMapTy; - ModuleMapTy Modules; - typedef std::map BinaryMapTy; - BinaryMapTy BinaryForPath; - typedef std::map, ObjectFile *> - ObjectFileForArchMapTy; - ObjectFileForArchMapTy ObjectFileForArch; + std::map Modules; + std::map, ObjectFile *> + ObjectFileForArch; + std::map, ObjectPair> + ObjectPairForPathArch; Options Opts; static const char kBadString[]; @@ -103,7 +116,11 @@ private: bool getNameFromSymbolTable(SymbolRef::Type Type, uint64_t Address, std::string &Name, uint64_t &Addr, uint64_t &Size) const; - void addSymbol(const SymbolRef &Symbol); + // For big-endian PowerPC64 ELF, OpdAddress is the address of the .opd + // (function descriptor) section and OpdExtractor refers to its contents. + void addSymbol(const SymbolRef &Symbol, + DataExtractor *OpdExtractor = nullptr, + uint64_t OpdAddress = 0); ObjectFile *Module; std::unique_ptr DebugInfoContext; @@ -116,12 +133,11 @@ private: return s1.Addr < s2.Addr; } }; - typedef std::map SymbolMapTy; - SymbolMapTy Functions; - SymbolMapTy Objects; + std::map Functions; + std::map Objects; }; } // namespace symbolize } // namespace llvm -#endif // LLVM_SYMBOLIZE_H +#endif diff --git a/tools/llvm-symbolizer/llvm-symbolizer.cpp b/tools/llvm-symbolizer/llvm-symbolizer.cpp index 29db172..d554022 100644 --- a/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ b/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" @@ -61,6 +62,11 @@ ClBinaryName("obj", cl::init(""), cl::desc("Path to object file to be symbolized (if not provided, " "object file should be specified for each input line)")); +static cl::list +ClDsymHint("dsym-hint", cl::ZeroOrMore, + cl::desc("Path to .dSYM bundles to search for debug info for the " + "object files")); + static bool parseCommand(bool &IsData, std::string &ModuleName, uint64_t &ModuleOffset) { const char *kDataCmd = "DATA "; @@ -119,6 +125,14 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm-symbolizer\n"); LLVMSymbolizer::Options Opts(ClUseSymbolTable, ClPrintFunctions, ClPrintInlining, ClDemangle, ClDefaultArch); + for (const auto &hint : ClDsymHint) { + if (sys::path::extension(hint) == ".dSYM") { + Opts.DsymHints.push_back(hint); + } else { + errs() << "Warning: invalid dSYM hint: \"" << hint << + "\" (must have the '.dSYM' extension).\n"; + } + } LLVMSymbolizer Symbolizer(Opts); bool IsData = false; diff --git a/tools/llvm-vtabledump/CMakeLists.txt b/tools/llvm-vtabledump/CMakeLists.txt new file mode 100644 index 0000000..4fe205b --- /dev/null +++ b/tools/llvm-vtabledump/CMakeLists.txt @@ -0,0 +1,10 @@ +set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} + Object + Support + ) + +add_llvm_tool(llvm-vtabledump + llvm-vtabledump.cpp + Error.cpp + ) diff --git a/tools/llvm-vtabledump/Error.cpp b/tools/llvm-vtabledump/Error.cpp new file mode 100644 index 0000000..c5de895 --- /dev/null +++ b/tools/llvm-vtabledump/Error.cpp @@ -0,0 +1,43 @@ +//===- Error.cpp - system_error extensions for llvm-vtabledump --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines a new error_category for the llvm-vtabledump tool. +// +//===----------------------------------------------------------------------===// + +#include "Error.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { +class vtabledump_error_category : public std::error_category { +public: + const char *name() const LLVM_NOEXCEPT override { return "llvm.vtabledump"; } + std::string message(int ev) const override { + switch (static_cast(ev)) { + case vtabledump_error::success: + return "Success"; + case vtabledump_error::file_not_found: + return "No such file."; + case vtabledump_error::unrecognized_file_format: + return "Unrecognized file type."; + } + llvm_unreachable( + "An enumerator of vtabledump_error does not have a message defined."); + } +}; +} // namespace + +namespace llvm { +const std::error_category &vtabledump_category() { + static vtabledump_error_category o; + return o; +} +} // namespace llvm diff --git a/tools/llvm-vtabledump/Error.h b/tools/llvm-vtabledump/Error.h new file mode 100644 index 0000000..fd8bb18 --- /dev/null +++ b/tools/llvm-vtabledump/Error.h @@ -0,0 +1,39 @@ +//===- Error.h - system_error extensions for llvm-vtabledump ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This declares a new error_category for the llvm-vtabledump tool. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_VTABLEDUMP_ERROR_H +#define LLVM_TOOLS_LLVM_VTABLEDUMP_ERROR_H + +#include + +namespace llvm { +const std::error_category &vtabledump_category(); + +enum class vtabledump_error { + success = 0, + file_not_found, + unrecognized_file_format, +}; + +inline std::error_code make_error_code(vtabledump_error e) { + return std::error_code(static_cast(e), vtabledump_category()); +} + +} // namespace llvm + +namespace std { +template <> +struct is_error_code_enum : std::true_type {}; +} + +#endif diff --git a/tools/llvm-vtabledump/LLVMBuild.txt b/tools/llvm-vtabledump/LLVMBuild.txt new file mode 100644 index 0000000..6a3cbff --- /dev/null +++ b/tools/llvm-vtabledump/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-vtabledump/LLVMBuild.txt --------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-vtabledump +parent = Tools +required_libraries = all-targets BitReader Object diff --git a/tools/llvm-vtabledump/Makefile b/tools/llvm-vtabledump/Makefile new file mode 100644 index 0000000..596c64c --- /dev/null +++ b/tools/llvm-vtabledump/Makefile @@ -0,0 +1,18 @@ +##===- tools/llvm-vtabledump/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../.. +TOOLNAME := llvm-vtabledump +LINK_COMPONENTS := bitreader object all-targets + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS := 1 + +include $(LEVEL)/Makefile.common + diff --git a/tools/llvm-vtabledump/llvm-vtabledump.cpp b/tools/llvm-vtabledump/llvm-vtabledump.cpp new file mode 100644 index 0000000..a21acae --- /dev/null +++ b/tools/llvm-vtabledump/llvm-vtabledump.cpp @@ -0,0 +1,464 @@ +//===- llvm-vtabledump.cpp - Dump vtables in an Object File -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Dumps VTables resident in object files and archives. Note, it currently only +// supports MS-ABI style object files. +// +//===----------------------------------------------------------------------===// + +#include "llvm-vtabledump.h" +#include "Error.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" +#include +#include +#include + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support; + +namespace opts { +cl::list InputFilenames(cl::Positional, + cl::desc(""), + cl::ZeroOrMore); +} // namespace opts + +static int ReturnValue = EXIT_SUCCESS; + +namespace llvm { + +bool error(std::error_code EC) { + if (!EC) + return false; + + ReturnValue = EXIT_FAILURE; + outs() << "\nError reading file: " << EC.message() << ".\n"; + outs().flush(); + return true; +} + +} // namespace llvm + +static void reportError(StringRef Input, StringRef Message) { + if (Input == "-") + Input = ""; + + errs() << Input << ": " << Message << "\n"; + errs().flush(); + ReturnValue = EXIT_FAILURE; +} + +static void reportError(StringRef Input, std::error_code EC) { + reportError(Input, EC.message()); +} + +static SmallVectorImpl &getRelocSections(const ObjectFile *Obj, + const SectionRef &Sec) { + static bool MappingDone = false; + static std::map> SectionRelocMap; + if (!MappingDone) { + for (const SectionRef &Section : Obj->sections()) { + section_iterator Sec2 = Section.getRelocatedSection(); + if (Sec2 != Obj->section_end()) + SectionRelocMap[*Sec2].push_back(Section); + } + MappingDone = true; + } + return SectionRelocMap[Sec]; +} + +static bool collectRelocatedSymbols(const ObjectFile *Obj, + const SectionRef &Sec, uint64_t SecAddress, + uint64_t SymAddress, uint64_t SymSize, + StringRef *I, StringRef *E) { + uint64_t SymOffset = SymAddress - SecAddress; + uint64_t SymEnd = SymOffset + SymSize; + for (const SectionRef &SR : getRelocSections(Obj, Sec)) { + for (const object::RelocationRef &Reloc : SR.relocations()) { + if (I == E) + break; + const object::symbol_iterator RelocSymI = Reloc.getSymbol(); + if (RelocSymI == Obj->symbol_end()) + continue; + StringRef RelocSymName; + if (error(RelocSymI->getName(RelocSymName))) + return true; + uint64_t Offset; + if (error(Reloc.getOffset(Offset))) + return true; + if (Offset >= SymOffset && Offset < SymEnd) { + *I = RelocSymName; + ++I; + } + } + } + return false; +} + +static bool collectRelocationOffsets( + const ObjectFile *Obj, const SectionRef &Sec, uint64_t SecAddress, + uint64_t SymAddress, uint64_t SymSize, StringRef SymName, + std::map, StringRef> &Collection) { + uint64_t SymOffset = SymAddress - SecAddress; + uint64_t SymEnd = SymOffset + SymSize; + for (const SectionRef &SR : getRelocSections(Obj, Sec)) { + for (const object::RelocationRef &Reloc : SR.relocations()) { + const object::symbol_iterator RelocSymI = Reloc.getSymbol(); + if (RelocSymI == Obj->symbol_end()) + continue; + StringRef RelocSymName; + if (error(RelocSymI->getName(RelocSymName))) + return true; + uint64_t Offset; + if (error(Reloc.getOffset(Offset))) + return true; + if (Offset >= SymOffset && Offset < SymEnd) + Collection[std::make_pair(SymName, Offset - SymOffset)] = RelocSymName; + } + } + return false; +} + +static void dumpVTables(const ObjectFile *Obj) { + struct CompleteObjectLocator { + StringRef Symbols[2]; + ArrayRef Data; + }; + struct ClassHierarchyDescriptor { + StringRef Symbols[1]; + ArrayRef Data; + }; + struct BaseClassDescriptor { + StringRef Symbols[2]; + ArrayRef Data; + }; + struct TypeDescriptor { + StringRef Symbols[1]; + uint64_t AlwaysZero; + StringRef MangledName; + }; + std::map, StringRef> VFTableEntries; + std::map> VBTables; + std::map COLs; + std::map CHDs; + std::map, StringRef> BCAEntries; + std::map BCDs; + std::map TDs; + + std::map, StringRef> VTableSymEntries; + std::map, int64_t> VTableDataEntries; + std::map, StringRef> VTTEntries; + std::map TINames; + + uint8_t BytesInAddress = Obj->getBytesInAddress(); + + for (const object::SymbolRef &Sym : Obj->symbols()) { + StringRef SymName; + if (error(Sym.getName(SymName))) + return; + object::section_iterator SecI(Obj->section_begin()); + if (error(Sym.getSection(SecI))) + return; + // Skip external symbols. + if (SecI == Obj->section_end()) + continue; + const SectionRef &Sec = *SecI; + // Skip virtual or BSS sections. + if (Sec.isBSS() || Sec.isVirtual()) + continue; + StringRef SecContents; + if (error(Sec.getContents(SecContents))) + return; + uint64_t SymAddress, SymSize; + if (error(Sym.getAddress(SymAddress)) || error(Sym.getSize(SymSize))) + return; + uint64_t SecAddress = Sec.getAddress(); + uint64_t SecSize = Sec.getSize(); + uint64_t SymOffset = SymAddress - SecAddress; + StringRef SymContents = SecContents.substr(SymOffset, SymSize); + + // VFTables in the MS-ABI start with '??_7' and are contained within their + // own COMDAT section. We then determine the contents of the VFTable by + // looking at each relocation in the section. + if (SymName.startswith("??_7")) { + // Each relocation either names a virtual method or a thunk. We note the + // offset into the section and the symbol used for the relocation. + collectRelocationOffsets(Obj, Sec, SecAddress, SecAddress, SecSize, + SymName, VFTableEntries); + } + // VBTables in the MS-ABI start with '??_8' and are filled with 32-bit + // offsets of virtual bases. + else if (SymName.startswith("??_8")) { + ArrayRef VBTableData( + reinterpret_cast(SymContents.data()), + SymContents.size() / sizeof(little32_t)); + VBTables[SymName] = VBTableData; + } + // Complete object locators in the MS-ABI start with '??_R4' + else if (SymName.startswith("??_R4")) { + CompleteObjectLocator COL; + COL.Data = ArrayRef( + reinterpret_cast(SymContents.data()), 3); + StringRef *I = std::begin(COL.Symbols), *E = std::end(COL.Symbols); + if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, + E)) + return; + COLs[SymName] = COL; + } + // Class hierarchy descriptors in the MS-ABI start with '??_R3' + else if (SymName.startswith("??_R3")) { + ClassHierarchyDescriptor CHD; + CHD.Data = ArrayRef( + reinterpret_cast(SymContents.data()), 3); + StringRef *I = std::begin(CHD.Symbols), *E = std::end(CHD.Symbols); + if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, + E)) + return; + CHDs[SymName] = CHD; + } + // Class hierarchy descriptors in the MS-ABI start with '??_R2' + else if (SymName.startswith("??_R2")) { + // Each relocation names a base class descriptor. We note the offset into + // the section and the symbol used for the relocation. + collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, + SymName, BCAEntries); + } + // Base class descriptors in the MS-ABI start with '??_R1' + else if (SymName.startswith("??_R1")) { + BaseClassDescriptor BCD; + BCD.Data = ArrayRef( + reinterpret_cast(SymContents.data()) + 1, 5); + StringRef *I = std::begin(BCD.Symbols), *E = std::end(BCD.Symbols); + if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, + E)) + return; + BCDs[SymName] = BCD; + } + // Type descriptors in the MS-ABI start with '??_R0' + else if (SymName.startswith("??_R0")) { + const char *DataPtr = SymContents.drop_front(BytesInAddress).data(); + TypeDescriptor TD; + if (BytesInAddress == 8) + TD.AlwaysZero = *reinterpret_cast(DataPtr); + else + TD.AlwaysZero = *reinterpret_cast(DataPtr); + TD.MangledName = SymContents.drop_front(BytesInAddress * 2); + StringRef *I = std::begin(TD.Symbols), *E = std::end(TD.Symbols); + if (collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, + E)) + return; + TDs[SymName] = TD; + } + // Construction vtables in the Itanium ABI start with '_ZTT' or '__ZTT'. + else if (SymName.startswith("_ZTT") || SymName.startswith("__ZTT")) { + collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, + SymName, VTTEntries); + } + // Typeinfo names in the Itanium ABI start with '_ZTS' or '__ZTS'. + else if (SymName.startswith("_ZTS") || SymName.startswith("__ZTS")) { + TINames[SymName] = SymContents.slice(0, SymContents.find('\0')); + } + // Vtables in the Itanium ABI start with '_ZTV' or '__ZTV'. + else if (SymName.startswith("_ZTV") || SymName.startswith("__ZTV")) { + collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize, + SymName, VTableSymEntries); + for (uint64_t SymOffI = 0; SymOffI < SymSize; SymOffI += BytesInAddress) { + auto Key = std::make_pair(SymName, SymOffI); + if (VTableSymEntries.count(Key)) + continue; + const char *DataPtr = SymContents.substr(SymOffI, BytesInAddress).data(); + int64_t VData; + if (BytesInAddress == 8) + VData = *reinterpret_cast(DataPtr); + else + VData = *reinterpret_cast(DataPtr); + VTableDataEntries[Key] = VData; + } + } + // Typeinfo structures in the Itanium ABI start with '_ZTI' or '__ZTI'. + else if (SymName.startswith("_ZTI") || SymName.startswith("__ZTI")) { + // FIXME: Do something with these! + } + } + for (const std::pair, StringRef> &VFTableEntry : + VFTableEntries) { + StringRef VFTableName = VFTableEntry.first.first; + uint64_t Offset = VFTableEntry.first.second; + StringRef SymName = VFTableEntry.second; + outs() << VFTableName << '[' << Offset << "]: " << SymName << '\n'; + } + for (const std::pair> &VBTable : VBTables) { + StringRef VBTableName = VBTable.first; + uint32_t Idx = 0; + for (little32_t Offset : VBTable.second) { + outs() << VBTableName << '[' << Idx << "]: " << Offset << '\n'; + Idx += sizeof(Offset); + } + } + for (const std::pair &COLPair : COLs) { + StringRef COLName = COLPair.first; + const CompleteObjectLocator &COL = COLPair.second; + outs() << COLName << "[IsImageRelative]: " << COL.Data[0] << '\n'; + outs() << COLName << "[OffsetToTop]: " << COL.Data[1] << '\n'; + outs() << COLName << "[VFPtrOffset]: " << COL.Data[2] << '\n'; + outs() << COLName << "[TypeDescriptor]: " << COL.Symbols[0] << '\n'; + outs() << COLName << "[ClassHierarchyDescriptor]: " << COL.Symbols[1] << '\n'; + } + for (const std::pair &CHDPair : CHDs) { + StringRef CHDName = CHDPair.first; + const ClassHierarchyDescriptor &CHD = CHDPair.second; + outs() << CHDName << "[AlwaysZero]: " << CHD.Data[0] << '\n'; + outs() << CHDName << "[Flags]: " << CHD.Data[1] << '\n'; + outs() << CHDName << "[NumClasses]: " << CHD.Data[2] << '\n'; + outs() << CHDName << "[BaseClassArray]: " << CHD.Symbols[0] << '\n'; + } + for (const std::pair, StringRef> &BCAEntry : + BCAEntries) { + StringRef BCAName = BCAEntry.first.first; + uint64_t Offset = BCAEntry.first.second; + StringRef SymName = BCAEntry.second; + outs() << BCAName << '[' << Offset << "]: " << SymName << '\n'; + } + for (const std::pair &BCDPair : BCDs) { + StringRef BCDName = BCDPair.first; + const BaseClassDescriptor &BCD = BCDPair.second; + outs() << BCDName << "[TypeDescriptor]: " << BCD.Symbols[0] << '\n'; + outs() << BCDName << "[NumBases]: " << BCD.Data[0] << '\n'; + outs() << BCDName << "[OffsetInVBase]: " << BCD.Data[1] << '\n'; + outs() << BCDName << "[VBPtrOffset]: " << BCD.Data[2] << '\n'; + outs() << BCDName << "[OffsetInVBTable]: " << BCD.Data[3] << '\n'; + outs() << BCDName << "[Flags]: " << BCD.Data[4] << '\n'; + outs() << BCDName << "[ClassHierarchyDescriptor]: " << BCD.Symbols[1] << '\n'; + } + for (const std::pair &TDPair : TDs) { + StringRef TDName = TDPair.first; + const TypeDescriptor &TD = TDPair.second; + outs() << TDName << "[VFPtr]: " << TD.Symbols[0] << '\n'; + outs() << TDName << "[AlwaysZero]: " << TD.AlwaysZero << '\n'; + outs() << TDName << "[MangledName]: "; + outs().write_escaped(TD.MangledName.rtrim(StringRef("\0", 1)), + /*UseHexEscapes=*/true) + << '\n'; + } + for (const std::pair, StringRef> &VTTPair : + VTTEntries) { + StringRef VTTName = VTTPair.first.first; + uint64_t VTTOffset = VTTPair.first.second; + StringRef VTTEntry = VTTPair.second; + outs() << VTTName << '[' << VTTOffset << "]: " << VTTEntry << '\n'; + } + for (const std::pair &TIPair : TINames) { + StringRef TIName = TIPair.first; + outs() << TIName << ": " << TIPair.second << '\n'; + } + auto VTableSymI = VTableSymEntries.begin(); + auto VTableSymE = VTableSymEntries.end(); + auto VTableDataI = VTableDataEntries.begin(); + auto VTableDataE = VTableDataEntries.end(); + for (;;) { + bool SymDone = VTableSymI == VTableSymE; + bool DataDone = VTableDataI == VTableDataE; + if (SymDone && DataDone) + break; + if (!SymDone && (DataDone || VTableSymI->first < VTableDataI->first)) { + StringRef VTableName = VTableSymI->first.first; + uint64_t Offset = VTableSymI->first.second; + StringRef VTableEntry = VTableSymI->second; + outs() << VTableName << '[' << Offset << "]: "; + outs() << VTableEntry; + outs() << '\n'; + ++VTableSymI; + continue; + } + if (!DataDone && (SymDone || VTableDataI->first < VTableSymI->first)) { + StringRef VTableName = VTableDataI->first.first; + uint64_t Offset = VTableDataI->first.second; + int64_t VTableEntry = VTableDataI->second; + outs() << VTableName << '[' << Offset << "]: "; + outs() << VTableEntry; + outs() << '\n'; + ++VTableDataI; + continue; + } + } +} + +static void dumpArchive(const Archive *Arc) { + for (const Archive::Child &ArcC : Arc->children()) { + ErrorOr> ChildOrErr = ArcC.getAsBinary(); + if (std::error_code EC = ChildOrErr.getError()) { + // Ignore non-object files. + if (EC != object_error::invalid_file_type) + reportError(Arc->getFileName(), EC.message()); + continue; + } + + if (ObjectFile *Obj = dyn_cast(&*ChildOrErr.get())) + dumpVTables(Obj); + else + reportError(Arc->getFileName(), + vtabledump_error::unrecognized_file_format); + } +} + +static void dumpInput(StringRef File) { + // If file isn't stdin, check that it exists. + if (File != "-" && !sys::fs::exists(File)) { + reportError(File, vtabledump_error::file_not_found); + return; + } + + // Attempt to open the binary. + ErrorOr> BinaryOrErr = createBinary(File); + if (std::error_code EC = BinaryOrErr.getError()) { + reportError(File, EC); + return; + } + Binary &Binary = *BinaryOrErr.get().getBinary(); + + if (Archive *Arc = dyn_cast(&Binary)) + dumpArchive(Arc); + else if (ObjectFile *Obj = dyn_cast(&Binary)) + dumpVTables(Obj); + else + reportError(File, vtabledump_error::unrecognized_file_format); +} + +int main(int argc, const char *argv[]) { + sys::PrintStackTraceOnErrorSignal(); + PrettyStackTraceProgram X(argc, argv); + llvm_shutdown_obj Y; + + // Initialize targets. + llvm::InitializeAllTargetInfos(); + + // Register the target printer for --version. + cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); + + cl::ParseCommandLineOptions(argc, argv, "LLVM VTable Dumper\n"); + + // Default to stdin if no filename is specified. + if (opts::InputFilenames.size() == 0) + opts::InputFilenames.push_back("-"); + + std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(), + dumpInput); + + return ReturnValue; +} diff --git a/tools/llvm-vtabledump/llvm-vtabledump.h b/tools/llvm-vtabledump/llvm-vtabledump.h new file mode 100644 index 0000000..62f7557 --- /dev/null +++ b/tools/llvm-vtabledump/llvm-vtabledump.h @@ -0,0 +1,23 @@ +//===-- llvm-vtabledump.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_VTABLEDUMP_LLVM_VTABLEDUMP_H +#define LLVM_TOOLS_LLVM_VTABLEDUMP_LLVM_VTABLEDUMP_H + +#include "llvm/Support/CommandLine.h" +#include + +namespace opts { +extern llvm::cl::list InputFilenames; +} // namespace opts + +#define LLVM_VTABLEDUMP_ENUM_ENT(ns, enum) \ + { #enum, ns::enum } + +#endif diff --git a/tools/lto/CMakeLists.txt b/tools/lto/CMakeLists.txt index 71391b7..87f42e8 100644 --- a/tools/lto/CMakeLists.txt +++ b/tools/lto/CMakeLists.txt @@ -7,8 +7,6 @@ set(LLVM_LINK_COMPONENTS Support ) -add_definitions( -DLLVM_VERSION_INFO=\"${PACKAGE_VERSION}\" ) - set(SOURCES LTODisassembler.cpp lto.cpp diff --git a/tools/lto/Makefile b/tools/lto/Makefile index a4fe9ac..530c05a 100644 --- a/tools/lto/Makefile +++ b/tools/lto/Makefile @@ -17,10 +17,6 @@ EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/lto.exports include $(LEVEL)/Makefile.common -ifdef LLVM_VERSION_INFO -CXX.Flags += -DLLVM_VERSION_INFO='"$(LLVM_VERSION_INFO)"' -endif - ifeq ($(HOST_OS),Darwin) # Special hack to allow libLTO to have an offset version number. ifdef LLVM_LTO_VERSION_OFFSET diff --git a/tools/lto/lto.cpp b/tools/lto/lto.cpp index 5732996..ec0372e 100644 --- a/tools/lto/lto.cpp +++ b/tools/lto/lto.cpp @@ -14,6 +14,7 @@ #include "llvm-c/lto.h" #include "llvm/CodeGen/CommandFlags.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/LTO/LTOCodeGenerator.h" #include "llvm/LTO/LTOModule.h" #include "llvm/Support/MemoryBuffer.h" @@ -32,6 +33,10 @@ static cl::opt DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false), cl::desc("Do not run the GVN load PRE pass")); +static cl::opt +DisableLTOVectorization("disable-lto-vectorization", cl::init(false), + cl::desc("Do not run loop or slp vectorization during LTO")); + // Holds most recent error string. // *** Not thread safe *** static std::string sLastErrorString; @@ -146,6 +151,24 @@ lto_module_t lto_module_create_from_memory_with_path(const void* mem, LTOModule::createFromBuffer(mem, length, Options, sLastErrorString, path)); } +lto_module_t lto_module_create_in_local_context(const void *mem, size_t length, + const char *path) { + lto_initialize(); + llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); + return wrap(LTOModule::createInLocalContext(mem, length, Options, + sLastErrorString, path)); +} + +lto_module_t lto_module_create_in_codegen_context(const void *mem, + size_t length, + const char *path, + lto_code_gen_t cg) { + lto_initialize(); + llvm::TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); + return wrap(LTOModule::createInContext(mem, length, Options, sLastErrorString, + path, &unwrap(cg)->getContext())); +} + void lto_module_dispose(lto_module_t mod) { delete unwrap(mod); } const char* lto_module_get_target_triple(lto_module_t mod) { @@ -191,21 +214,31 @@ void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg, unwrap(cg)->setDiagnosticHandler(diag_handler, ctxt); } -lto_code_gen_t lto_codegen_create(void) { +static lto_code_gen_t createCodeGen(bool InLocalContext) { lto_initialize(); TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); - LTOCodeGenerator *CodeGen = new LTOCodeGenerator(); + LTOCodeGenerator *CodeGen = + InLocalContext ? new LTOCodeGenerator(make_unique()) + : new LTOCodeGenerator(); if (CodeGen) CodeGen->setTargetOptions(Options); return wrap(CodeGen); } +lto_code_gen_t lto_codegen_create(void) { + return createCodeGen(/* InLocalContext */ false); +} + +lto_code_gen_t lto_codegen_create_in_local_context(void) { + return createCodeGen(/* InLocalContext */ true); +} + void lto_codegen_dispose(lto_code_gen_t cg) { delete unwrap(cg); } bool lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod) { - return !unwrap(cg)->addModule(unwrap(mod), sLastErrorString); + return !unwrap(cg)->addModule(unwrap(mod)); } bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) { @@ -252,7 +285,8 @@ const void *lto_codegen_compile(lto_code_gen_t cg, size_t *length) { parsedOptions = true; } return unwrap(cg)->compile(length, DisableOpt, DisableInline, - DisableGVNLoadPRE, sLastErrorString); + DisableGVNLoadPRE, DisableLTOVectorization, + sLastErrorString); } bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { @@ -261,8 +295,9 @@ bool lto_codegen_compile_to_file(lto_code_gen_t cg, const char **name) { lto_add_attrs(cg); parsedOptions = true; } - return !unwrap(cg)->compile_to_file(name, DisableOpt, DisableInline, - DisableGVNLoadPRE, sLastErrorString); + return !unwrap(cg)->compile_to_file( + name, DisableOpt, DisableInline, DisableGVNLoadPRE, + DisableLTOVectorization, sLastErrorString); } void lto_codegen_debug_options(lto_code_gen_t cg, const char *opt) { diff --git a/tools/lto/lto.exports b/tools/lto/lto.exports index b10ab1a..f6ceaac 100644 --- a/tools/lto/lto.exports +++ b/tools/lto/lto.exports @@ -6,6 +6,8 @@ lto_module_create_from_fd lto_module_create_from_fd_at_offset lto_module_create_from_memory lto_module_create_from_memory_with_path +lto_module_create_in_local_context +lto_module_create_in_codegen_context lto_module_get_deplib lto_module_get_linkeropt lto_module_get_num_deplibs @@ -25,6 +27,7 @@ lto_codegen_add_module lto_codegen_add_must_preserve_symbol lto_codegen_compile lto_codegen_create +lto_codegen_create_in_local_context lto_codegen_dispose lto_codegen_set_debug_model lto_codegen_set_pic_model diff --git a/tools/macho-dump/macho-dump.cpp b/tools/macho-dump/macho-dump.cpp index 7600979..604f93a 100644 --- a/tools/macho-dump/macho-dump.cpp +++ b/tools/macho-dump/macho-dump.cpp @@ -300,12 +300,12 @@ DumpDataInCodeDataCommand(const MachOObjectFile &Obj, static int DumpLinkerOptionsCommand(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &LCI) { - MachO::linker_options_command LOLC = Obj.getLinkerOptionsLoadCommand(LCI); + MachO::linker_option_command LOLC = Obj.getLinkerOptionLoadCommand(LCI); outs() << " ('count', " << LOLC.count << ")\n" << " ('_strings', [\n"; - uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_options_command); - const char *P = LCI.Ptr + sizeof(MachO::linker_options_command); + uint64_t DataSize = LOLC.cmdsize - sizeof(MachO::linker_option_command); + const char *P = LCI.Ptr + sizeof(MachO::linker_option_command); StringRef Data(P, DataSize); for (unsigned i = 0; i != LOLC.count; ++i) { std::pair Split = Data.split('\0'); @@ -324,7 +324,7 @@ DumpVersionMin(const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &LCI) { MachO::version_min_command VMLC = Obj.getVersionMinLoadCommand(LCI); outs() << " ('version, " << VMLC.version << ")\n" - << " ('reserved, " << VMLC.reserved << ")\n"; + << " ('sdk, " << VMLC.sdk << ")\n"; return 0; } @@ -356,7 +356,7 @@ static int DumpLoadCommand(const MachOObjectFile &Obj, return DumpLinkeditDataCommand(Obj, LCI); case MachO::LC_DATA_IN_CODE: return DumpDataInCodeDataCommand(Obj, LCI); - case MachO::LC_LINKER_OPTIONS: + case MachO::LC_LINKER_OPTION: return DumpLinkerOptionsCommand(Obj, LCI); case MachO::LC_VERSION_MIN_IPHONEOS: case MachO::LC_VERSION_MIN_MACOSX: @@ -403,12 +403,12 @@ int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, "llvm Mach-O dumping tool\n"); - ErrorOr BinaryOrErr = createBinary(InputFile); + ErrorOr> BinaryOrErr = createBinary(InputFile); if (std::error_code EC = BinaryOrErr.getError()) return Error("unable to read input: '" + EC.message() + "'"); - std::unique_ptr Binary(BinaryOrErr.get()); + Binary &Binary = *BinaryOrErr.get().getBinary(); - const MachOObjectFile *InputObject = dyn_cast(Binary.get()); + const MachOObjectFile *InputObject = dyn_cast(&Binary); if (!InputObject) return Error("Not a MachO object"); diff --git a/tools/msbuild/CMakeLists.txt b/tools/msbuild/CMakeLists.txt index b7be71d..4f471e5 100644 --- a/tools/msbuild/CMakeLists.txt +++ b/tools/msbuild/CMakeLists.txt @@ -10,6 +10,8 @@ if (WIN32) set(prop_file_v110_xp "Microsoft.Cpp.${platform}.LLVM-vs2012_xp.props") set(prop_file_v120 "toolset-vs2013.props") set(prop_file_v120_xp "toolset-vs2013_xp.props") + set(prop_file_v140 "toolset-vs2014.props") + set(prop_file_v140_xp "toolset-vs2014_xp.props") if (platform STREQUAL "Win32") set(mflag "m32") @@ -29,6 +31,11 @@ if (WIN32) configure_file(${prop_file_in} ${platform}/${prop_file_v120}) set(VS_VERSION "v120_xp") configure_file(${prop_file_in} ${platform}/${prop_file_v120_xp}) + set(VS_VERSION "v140") + set(MSC_VERSION "1900") + configure_file(${prop_file_in} ${platform}/${prop_file_v140}) + set(VS_VERSION "v140_xp") + configure_file(${prop_file_in} ${platform}/${prop_file_v140_xp}) set(VS_VERSION) set(MSC_VERSION) set(mflag) @@ -38,12 +45,16 @@ if (WIN32) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v110_xp}" DESTINATION tools/msbuild/${platform}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v120}" DESTINATION tools/msbuild/${platform}) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v120_xp}" DESTINATION tools/msbuild/${platform}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v140}" DESTINATION tools/msbuild/${platform}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${platform}/${prop_file_v140_xp}" DESTINATION tools/msbuild/${platform}) install(FILES "Microsoft.Cpp.Win32.LLVM-vs2010.targets" DESTINATION "tools/msbuild/${platform}" RENAME "Microsoft.Cpp.${platform}.LLVM-vs2010.targets") install(FILES "Microsoft.Cpp.Win32.LLVM-vs2012.targets" DESTINATION "tools/msbuild/${platform}" RENAME "Microsoft.Cpp.${platform}.LLVM-vs2012.targets") install(FILES "Microsoft.Cpp.Win32.LLVM-vs2012_xp.targets" DESTINATION "tools/msbuild/${platform}" RENAME "Microsoft.Cpp.${platform}.LLVM-vs2012_xp.targets") install(FILES "toolset-vs2013.targets" DESTINATION "tools/msbuild/${platform}") install(FILES "toolset-vs2013_xp.targets" DESTINATION "tools/msbuild/${platform}") + install(FILES "toolset-vs2014.targets" DESTINATION "tools/msbuild/${platform}") + install(FILES "toolset-vs2014_xp.targets" DESTINATION "tools/msbuild/${platform}") endforeach() set(LIB_PATH_VERSION) diff --git a/tools/msbuild/install.bat b/tools/msbuild/install.bat index 9880fb2..6e321e3 100644 --- a/tools/msbuild/install.bat +++ b/tools/msbuild/install.bat @@ -6,13 +6,15 @@ set SUCCESS=0 REM Change to the directory of this batch file. cd /d %~dp0 +REM Loop over the two platforms in awkward batch file fashion. set PLATFORM=None -:START -IF %PLATFORM% == x64 GOTO LOOPEND +:PLATFORMLOOPHEAD +IF %PLATFORM% == x64 GOTO PLATFORMLOOPEND IF %PLATFORM% == Win32 SET PLATFORM=x64 IF %PLATFORM% == None SET PLATFORM=Win32 REM Search for the MSBuild toolsets directory. + SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\Platforms\%PLATFORM%\PlatformToolsets" IF EXIST %D% GOTO FOUND_V100 SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\Platforms\%PLATFORM%\PlatformToolsets" @@ -30,13 +32,24 @@ IF EXIST %D% GOTO FOUND_V120 SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V120\Platforms\%PLATFORM%\PlatformToolsets" IF EXIST %D% GOTO FOUND_V120 -:LOOPEND +:TRY_V140 +SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V140\Platforms\%PLATFORM%\PlatformToolsets" +IF EXIST %D% GOTO FOUND_V140 +SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V140\Platforms\%PLATFORM%\PlatformToolsets" +IF EXIST %D% GOTO FOUND_V140 + +:TRY_V150 + +GOTO PLATFORMLOOPHEAD + +:PLATFORMLOOPEND IF %SUCCESS% == 1 goto DONE echo Failed to find MSBuild toolsets directory. goto FAILED :FOUND_V100 +REM Routine for installing v100 toolchain. IF NOT EXIST %D%\LLVM-vs2010 mkdir %D%\LLVM-vs2010 IF NOT %ERRORLEVEL% == 0 GOTO FAILED copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2010.props %D%\LLVM-vs2010 @@ -47,6 +60,7 @@ set SUCCESS=1 GOTO TRY_V110 :FOUND_V110 +REM Routine for installing v110 toolchain. IF NOT EXIST %D%\LLVM-vs2012 mkdir %D%\LLVM-vs2012 IF NOT %ERRORLEVEL% == 0 GOTO FAILED copy %PLATFORM%\Microsoft.Cpp.%PLATFORM%.LLVM-vs2012.props %D%\LLVM-vs2012 @@ -63,6 +77,7 @@ set SUCCESS=1 GOTO TRY_V120 :FOUND_V120 +REM Routine for installing v120 toolchain. IF NOT EXIST %D%\LLVM-vs2013 mkdir %D%\LLVM-vs2013 IF NOT %ERRORLEVEL% == 0 GOTO FAILED copy %PLATFORM%\toolset-vs2013.props %D%\LLVM-vs2013\toolset.props @@ -76,7 +91,24 @@ IF NOT %ERRORLEVEL% == 0 GOTO FAILED copy %PLATFORM%\toolset-vs2013_xp.targets %D%\LLVM-vs2013_xp\toolset.targets IF NOT %ERRORLEVEL% == 0 GOTO FAILED set SUCCESS=1 -GOTO START +GOTO TRY_V140 + +:FOUND_V140 +REM Routine for installing v140 toolchain. +IF NOT EXIST %D%\LLVM-vs2014 mkdir %D%\LLVM-vs2014 +IF NOT %ERRORLEVEL% == 0 GOTO FAILED +copy %PLATFORM%\toolset-vs2014.props %D%\LLVM-vs2014\toolset.props +IF NOT %ERRORLEVEL% == 0 GOTO FAILED +copy %PLATFORM%\toolset-vs2014.targets %D%\LLVM-vs2014\toolset.targets +IF NOT %ERRORLEVEL% == 0 GOTO FAILED +IF NOT EXIST %D%\LLVM-vs2014_xp mkdir %D%\LLVM-vs2014_xp +IF NOT %ERRORLEVEL% == 0 GOTO FAILED +copy %PLATFORM%\toolset-vs2014_xp.props %D%\LLVM-vs2014_xp\toolset.props +IF NOT %ERRORLEVEL% == 0 GOTO FAILED +copy %PLATFORM%\toolset-vs2014_xp.targets %D%\LLVM-vs2014_xp\toolset.targets +IF NOT %ERRORLEVEL% == 0 GOTO FAILED +set SUCCESS=1 +GOTO TRY_V150 :DONE diff --git a/tools/msbuild/toolset-vs2014.targets b/tools/msbuild/toolset-vs2014.targets new file mode 100644 index 0000000..05b59a2 --- /dev/null +++ b/tools/msbuild/toolset-vs2014.targets @@ -0,0 +1,3 @@ + + + diff --git a/tools/msbuild/toolset-vs2014_xp.targets b/tools/msbuild/toolset-vs2014_xp.targets new file mode 100644 index 0000000..eec4f18 --- /dev/null +++ b/tools/msbuild/toolset-vs2014_xp.targets @@ -0,0 +1,21 @@ + + + + v4.0 + NoSupportCodeAnalysisXP;$(BeforeClCompileTargets) + + + + + + + + + + CheckWindowsSDK71A;$(PrepareForBuildDependsOn) + + + + + + diff --git a/tools/msbuild/uninstall.bat b/tools/msbuild/uninstall.bat index b0bc943..c1afae2 100644 --- a/tools/msbuild/uninstall.bat +++ b/tools/msbuild/uninstall.bat @@ -6,8 +6,8 @@ REM CD to the directory of this batch file. cd /d %~dp0 set PLATFORM=None -:START -IF %PLATFORM% == x64 GOTO END +:LOOPHEAD +IF %PLATFORM% == x64 GOTO LOOPEND IF %PLATFORM% == Win32 SET PLATFORM=x64 IF %PLATFORM% == None SET PLATFORM=Win32 @@ -51,8 +51,23 @@ IF EXIST %D%\LLVM-vs2013_xp del %D%\LLVM-vs2013_xp\toolset.props IF EXIST %D%\LLVM-vs2013_xp del %D%\LLVM-vs2013_xp\toolset.targets IF EXIST %D%\LLVM-vs2013_xp rmdir %D%\LLVM-vs2013_xp +SET D="%ProgramFiles%\MSBuild\Microsoft.Cpp\v4.0\V140\Platforms\%PLATFORM%\PlatformToolsets" +IF EXIST %D%\LLVM-vs2014 del %D%\LLVM-vs2014\toolset.props +IF EXIST %D%\LLVM-vs2014 del %D%\LLVM-vs2014\toolset.targets +IF EXIST %D%\LLVM-vs2014 rmdir %D%\LLVM-vs2014 +IF EXIST %D%\LLVM-vs2014_xp del %D%\LLVM-vs2014_xp\toolset.props +IF EXIST %D%\LLVM-vs2014_xp del %D%\LLVM-vs2014_xp\toolset.targets +IF EXIST %D%\LLVM-vs2014_xp rmdir %D%\LLVM-vs2014_xp +SET D="%ProgramFiles(x86)%\MSBuild\Microsoft.Cpp\v4.0\V140\Platforms\%PLATFORM%\PlatformToolsets" +IF EXIST %D%\LLVM-vs2014 del %D%\LLVM-vs2014\toolset.props +IF EXIST %D%\LLVM-vs2014 del %D%\LLVM-vs2014\toolset.targets +IF EXIST %D%\LLVM-vs2014 rmdir %D%\LLVM-vs2014 +IF EXIST %D%\LLVM-vs2014_xp del %D%\LLVM-vs2014_xp\toolset.props +IF EXIST %D%\LLVM-vs2014_xp del %D%\LLVM-vs2014_xp\toolset.targets +IF EXIST %D%\LLVM-vs2014_xp rmdir %D%\LLVM-vs2014_xp -GOTO START -:END +GOTO LOOPHEAD + +:LOOPEND echo Done! diff --git a/tools/obj2yaml/CMakeLists.txt b/tools/obj2yaml/CMakeLists.txt index f167ed5..3cdac5c 100644 --- a/tools/obj2yaml/CMakeLists.txt +++ b/tools/obj2yaml/CMakeLists.txt @@ -3,6 +3,6 @@ set(LLVM_LINK_COMPONENTS Support ) -add_llvm_utility(obj2yaml +add_llvm_tool(obj2yaml obj2yaml.cpp coff2yaml.cpp elf2yaml.cpp Error.cpp ) diff --git a/tools/obj2yaml/Error.cpp b/tools/obj2yaml/Error.cpp index 0074128..abef8af 100644 --- a/tools/obj2yaml/Error.cpp +++ b/tools/obj2yaml/Error.cpp @@ -20,7 +20,9 @@ public: }; } // namespace -const char *_obj2yaml_error_category::name() const { return "obj2yaml"; } +const char *_obj2yaml_error_category::name() const LLVM_NOEXCEPT { + return "obj2yaml"; +} std::string _obj2yaml_error_category::message(int ev) const { switch (static_cast(ev)) { diff --git a/tools/obj2yaml/Error.h b/tools/obj2yaml/Error.h index 4657f0d..982f59e 100644 --- a/tools/obj2yaml/Error.h +++ b/tools/obj2yaml/Error.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_ERROR_H -#define LLVM_TOOLS_ERROR_H +#ifndef LLVM_TOOLS_OBJ2YAML_ERROR_H +#define LLVM_TOOLS_OBJ2YAML_ERROR_H #include diff --git a/tools/obj2yaml/Makefile b/tools/obj2yaml/Makefile index 95f393d..6cbef69 100644 --- a/tools/obj2yaml/Makefile +++ b/tools/obj2yaml/Makefile @@ -14,7 +14,4 @@ LINK_COMPONENTS := object # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 -# Don't install this utility -NO_INSTALL = 1 - include $(LEVEL)/Makefile.common diff --git a/tools/obj2yaml/coff2yaml.cpp b/tools/obj2yaml/coff2yaml.cpp index fed4533..5baa644 100644 --- a/tools/obj2yaml/coff2yaml.cpp +++ b/tools/obj2yaml/coff2yaml.cpp @@ -20,7 +20,9 @@ namespace { class COFFDumper { const object::COFFObjectFile &Obj; COFFYAML::Object YAMLObj; - void dumpHeader(const object::coff_file_header *Header); + template + void dumpOptionalHeader(T OptionalHeader); + void dumpHeader(); void dumpSections(unsigned numSections); void dumpSymbols(unsigned numSymbols); @@ -31,40 +33,90 @@ public: } -static void check(std::error_code ec) { - if (ec) - report_fatal_error(ec.message()); +COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) { + const object::pe32_header *PE32Header = nullptr; + Obj.getPE32Header(PE32Header); + if (PE32Header) { + dumpOptionalHeader(PE32Header); + } else { + const object::pe32plus_header *PE32PlusHeader = nullptr; + Obj.getPE32PlusHeader(PE32PlusHeader); + if (PE32PlusHeader) { + dumpOptionalHeader(PE32PlusHeader); + } + } + dumpHeader(); + dumpSections(Obj.getNumberOfSections()); + dumpSymbols(Obj.getNumberOfSymbols()); } -COFFDumper::COFFDumper(const object::COFFObjectFile &Obj) : Obj(Obj) { - const object::coff_file_header *Header; - check(Obj.getCOFFHeader(Header)); - dumpHeader(Header); - dumpSections(Header->NumberOfSections); - dumpSymbols(Header->NumberOfSymbols); +template void COFFDumper::dumpOptionalHeader(T OptionalHeader) { + YAMLObj.OptionalHeader = COFFYAML::PEHeader(); + YAMLObj.OptionalHeader->Header.AddressOfEntryPoint = + OptionalHeader->AddressOfEntryPoint; + YAMLObj.OptionalHeader->Header.AddressOfEntryPoint = + OptionalHeader->AddressOfEntryPoint; + YAMLObj.OptionalHeader->Header.ImageBase = OptionalHeader->ImageBase; + YAMLObj.OptionalHeader->Header.SectionAlignment = + OptionalHeader->SectionAlignment; + YAMLObj.OptionalHeader->Header.FileAlignment = OptionalHeader->FileAlignment; + YAMLObj.OptionalHeader->Header.MajorOperatingSystemVersion = + OptionalHeader->MajorOperatingSystemVersion; + YAMLObj.OptionalHeader->Header.MinorOperatingSystemVersion = + OptionalHeader->MinorOperatingSystemVersion; + YAMLObj.OptionalHeader->Header.MajorImageVersion = + OptionalHeader->MajorImageVersion; + YAMLObj.OptionalHeader->Header.MinorImageVersion = + OptionalHeader->MinorImageVersion; + YAMLObj.OptionalHeader->Header.MajorSubsystemVersion = + OptionalHeader->MajorSubsystemVersion; + YAMLObj.OptionalHeader->Header.MinorSubsystemVersion = + OptionalHeader->MinorSubsystemVersion; + YAMLObj.OptionalHeader->Header.Subsystem = OptionalHeader->Subsystem; + YAMLObj.OptionalHeader->Header.DLLCharacteristics = + OptionalHeader->DLLCharacteristics; + YAMLObj.OptionalHeader->Header.SizeOfStackReserve = + OptionalHeader->SizeOfStackReserve; + YAMLObj.OptionalHeader->Header.SizeOfStackCommit = + OptionalHeader->SizeOfStackCommit; + YAMLObj.OptionalHeader->Header.SizeOfHeapReserve = + OptionalHeader->SizeOfHeapReserve; + YAMLObj.OptionalHeader->Header.SizeOfHeapCommit = + OptionalHeader->SizeOfHeapCommit; + unsigned I = 0; + for (auto &DestDD : YAMLObj.OptionalHeader->DataDirectories) { + const object::data_directory *DD; + if (Obj.getDataDirectory(I++, DD)) + continue; + DestDD = COFF::DataDirectory(); + DestDD->RelativeVirtualAddress = DD->RelativeVirtualAddress; + DestDD->Size = DD->Size; + } } -void COFFDumper::dumpHeader(const object::coff_file_header *Header) { - YAMLObj.Header.Machine = Header->Machine; - YAMLObj.Header.Characteristics = Header->Characteristics; +void COFFDumper::dumpHeader() { + YAMLObj.Header.Machine = Obj.getMachine(); + YAMLObj.Header.Characteristics = Obj.getCharacteristics(); } void COFFDumper::dumpSections(unsigned NumSections) { - std::vector &Sections = YAMLObj.Sections; - for (const auto &Section : Obj.sections()) { - const object::coff_section *Sect = Obj.getCOFFSection(Section); - COFFYAML::Section Sec; - Sec.Name = Sect->Name; // FIXME: check the null termination! - uint32_t Characteristics = Sect->Characteristics; - Sec.Header.Characteristics = Characteristics; - Sec.Alignment = 1 << (((Characteristics >> 20) & 0xf) - 1); + std::vector &YAMLSections = YAMLObj.Sections; + for (const auto &ObjSection : Obj.sections()) { + const object::coff_section *COFFSection = Obj.getCOFFSection(ObjSection); + COFFYAML::Section NewYAMLSection; + ObjSection.getName(NewYAMLSection.Name); + NewYAMLSection.Header.Characteristics = COFFSection->Characteristics; + NewYAMLSection.Header.VirtualAddress = ObjSection.getAddress(); + NewYAMLSection.Header.VirtualSize = COFFSection->VirtualSize; + NewYAMLSection.Alignment = ObjSection.getAlignment(); ArrayRef sectionData; - Obj.getSectionContents(Sect, sectionData); - Sec.SectionData = yaml::BinaryRef(sectionData); + if (!ObjSection.isBSS()) + Obj.getSectionContents(COFFSection, sectionData); + NewYAMLSection.SectionData = yaml::BinaryRef(sectionData); std::vector Relocations; - for (const auto &Reloc : Section.relocations()) { + for (const auto &Reloc : ObjSection.relocations()) { const object::coff_relocation *reloc = Obj.getCOFFRelocation(Reloc); COFFYAML::Relocation Rel; object::symbol_iterator Sym = Reloc.getSymbol(); @@ -73,8 +125,8 @@ void COFFDumper::dumpSections(unsigned NumSections) { Rel.Type = reloc->Type; Relocations.push_back(Rel); } - Sec.Relocations = Relocations; - Sections.push_back(Sec); + NewYAMLSection.Relocations = Relocations; + YAMLSections.push_back(NewYAMLSection); } } @@ -111,13 +163,15 @@ static void dumpWeakExternal(COFFYAML::Symbol *Sym, static void dumpSectionDefinition(COFFYAML::Symbol *Sym, - const object::coff_aux_section_definition *ObjSD) { + const object::coff_aux_section_definition *ObjSD, + bool IsBigObj) { COFF::AuxiliarySectionDefinition YAMLASD; + int32_t AuxNumber = ObjSD->getNumber(IsBigObj); YAMLASD.Length = ObjSD->Length; YAMLASD.NumberOfRelocations = ObjSD->NumberOfRelocations; YAMLASD.NumberOfLinenumbers = ObjSD->NumberOfLinenumbers; YAMLASD.CheckSum = ObjSD->CheckSum; - YAMLASD.Number = ObjSD->Number; + YAMLASD.Number = AuxNumber; YAMLASD.Selection = ObjSD->Selection; Sym->SectionDefinition = YAMLASD; @@ -136,63 +190,64 @@ dumpCLRTokenDefinition(COFFYAML::Symbol *Sym, void COFFDumper::dumpSymbols(unsigned NumSymbols) { std::vector &Symbols = YAMLObj.Symbols; for (const auto &S : Obj.symbols()) { - const object::coff_symbol *Symbol = Obj.getCOFFSymbol(S); + object::COFFSymbolRef Symbol = Obj.getCOFFSymbol(S); COFFYAML::Symbol Sym; Obj.getSymbolName(Symbol, Sym.Name); - Sym.SimpleType = COFF::SymbolBaseType(Symbol->getBaseType()); - Sym.ComplexType = COFF::SymbolComplexType(Symbol->getComplexType()); - Sym.Header.StorageClass = Symbol->StorageClass; - Sym.Header.Value = Symbol->Value; - Sym.Header.SectionNumber = Symbol->SectionNumber; - Sym.Header.NumberOfAuxSymbols = Symbol->NumberOfAuxSymbols; - - if (Symbol->NumberOfAuxSymbols > 0) { + Sym.SimpleType = COFF::SymbolBaseType(Symbol.getBaseType()); + Sym.ComplexType = COFF::SymbolComplexType(Symbol.getComplexType()); + Sym.Header.StorageClass = Symbol.getStorageClass(); + Sym.Header.Value = Symbol.getValue(); + Sym.Header.SectionNumber = Symbol.getSectionNumber(); + Sym.Header.NumberOfAuxSymbols = Symbol.getNumberOfAuxSymbols(); + + if (Symbol.getNumberOfAuxSymbols() > 0) { ArrayRef AuxData = Obj.getSymbolAuxData(Symbol); - if (Symbol->isFunctionDefinition()) { + if (Symbol.isFunctionDefinition()) { // This symbol represents a function definition. - assert(Symbol->NumberOfAuxSymbols == 1 && + assert(Symbol.getNumberOfAuxSymbols() == 1 && "Expected a single aux symbol to describe this function!"); const object::coff_aux_function_definition *ObjFD = reinterpret_cast( AuxData.data()); dumpFunctionDefinition(&Sym, ObjFD); - } else if (Symbol->isFunctionLineInfo()) { + } else if (Symbol.isFunctionLineInfo()) { // This symbol describes function line number information. - assert(Symbol->NumberOfAuxSymbols == 1 && - "Exepected a single aux symbol to describe this section!"); + assert(Symbol.getNumberOfAuxSymbols() == 1 && + "Expected a single aux symbol to describe this function!"); const object::coff_aux_bf_and_ef_symbol *ObjBES = reinterpret_cast( AuxData.data()); dumpbfAndEfLineInfo(&Sym, ObjBES); - } else if (Symbol->isWeakExternal()) { + } else if (Symbol.isAnyUndefined()) { // This symbol represents a weak external definition. - assert(Symbol->NumberOfAuxSymbols == 1 && - "Exepected a single aux symbol to describe this section!"); + assert(Symbol.getNumberOfAuxSymbols() == 1 && + "Expected a single aux symbol to describe this weak symbol!"); const object::coff_aux_weak_external *ObjWE = reinterpret_cast( AuxData.data()); dumpWeakExternal(&Sym, ObjWE); - } else if (Symbol->isFileRecord()) { + } else if (Symbol.isFileRecord()) { // This symbol represents a file record. Sym.File = StringRef(reinterpret_cast(AuxData.data()), - Symbol->NumberOfAuxSymbols * COFF::SymbolSize) + Symbol.getNumberOfAuxSymbols() * + Obj.getSymbolTableEntrySize()) .rtrim(StringRef("\0", /*length=*/1)); - } else if (Symbol->isSectionDefinition()) { + } else if (Symbol.isSectionDefinition()) { // This symbol represents a section definition. - assert(Symbol->NumberOfAuxSymbols == 1 && + assert(Symbol.getNumberOfAuxSymbols() == 1 && "Expected a single aux symbol to describe this section!"); const object::coff_aux_section_definition *ObjSD = reinterpret_cast( AuxData.data()); - dumpSectionDefinition(&Sym, ObjSD); - } else if (Symbol->isCLRToken()) { + dumpSectionDefinition(&Sym, ObjSD, Symbol.isBigObj()); + } else if (Symbol.isCLRToken()) { // This symbol represents a CLR token definition. - assert(Symbol->NumberOfAuxSymbols == 1 && - "Expected a single aux symbol to describe this CLR Token"); + assert(Symbol.getNumberOfAuxSymbols() == 1 && + "Expected a single aux symbol to describe this CLR Token!"); const object::coff_aux_clr_token *ObjCLRToken = reinterpret_cast( diff --git a/tools/obj2yaml/elf2yaml.cpp b/tools/obj2yaml/elf2yaml.cpp index 8b53ee7..d770ce1 100644 --- a/tools/obj2yaml/elf2yaml.cpp +++ b/tools/obj2yaml/elf2yaml.cpp @@ -133,7 +133,7 @@ std::error_code ELFDumper::dumpSymbol(Elf_Sym_Iter Sym, S.Type = Sym->getType(); S.Value = Sym->st_value; S.Size = Sym->st_size; - S.Visibility = Sym->st_other & 0x3; + S.Other = Sym->st_other; ErrorOr NameOrErr = Obj.getSymbolName(Sym); if (std::error_code EC = NameOrErr.getError()) diff --git a/tools/obj2yaml/obj2yaml.cpp b/tools/obj2yaml/obj2yaml.cpp index 944314a..b64096d7 100644 --- a/tools/obj2yaml/obj2yaml.cpp +++ b/tools/obj2yaml/obj2yaml.cpp @@ -32,13 +32,13 @@ static std::error_code dumpInput(StringRef File) { if (File != "-" && !sys::fs::exists(File)) return obj2yaml_error::file_not_found; - ErrorOr BinaryOrErr = createBinary(File); + ErrorOr> BinaryOrErr = createBinary(File); if (std::error_code EC = BinaryOrErr.getError()) return EC; - std::unique_ptr Binary(BinaryOrErr.get()); + Binary &Binary = *BinaryOrErr.get().getBinary(); // TODO: If this is an archive, then burst it and dump each entry - if (ObjectFile *Obj = dyn_cast(Binary.get())) + if (ObjectFile *Obj = dyn_cast(&Binary)) return dumpObject(*Obj); return obj2yaml_error::unrecognized_file_format; diff --git a/tools/obj2yaml/obj2yaml.h b/tools/obj2yaml/obj2yaml.h index 6d81110..643ab7b 100644 --- a/tools/obj2yaml/obj2yaml.h +++ b/tools/obj2yaml/obj2yaml.h @@ -10,8 +10,8 @@ // source file, implement it. //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OBJ2YAML_H -#define LLVM_TOOLS_OBJ2YAML_H +#ifndef LLVM_TOOLS_OBJ2YAML_OBJ2YAML_H +#define LLVM_TOOLS_OBJ2YAML_OBJ2YAML_H #include "llvm/Object/COFF.h" #include "llvm/Support/raw_ostream.h" diff --git a/tools/opt/BreakpointPrinter.cpp b/tools/opt/BreakpointPrinter.cpp index 44f4a11..3cbc0ae 100644 --- a/tools/opt/BreakpointPrinter.cpp +++ b/tools/opt/BreakpointPrinter.cpp @@ -62,7 +62,7 @@ struct BreakpointPrinter : public ModulePass { continue; getContextName(SP.getContext().resolve(TypeIdentifierMap), Name); Name = Name + SP.getDisplayName().str(); - if (!Name.empty() && Processed.insert(Name)) { + if (!Name.empty() && Processed.insert(Name).second) { Out << Name << "\n"; } } diff --git a/tools/opt/NewPMDriver.cpp b/tools/opt/NewPMDriver.cpp index 8076ff4..f215c77 100644 --- a/tools/opt/NewPMDriver.cpp +++ b/tools/opt/NewPMDriver.cpp @@ -17,8 +17,8 @@ #include "Passes.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/CGSCCPassManager.h" -#include "llvm/Analysis/LazyCallGraph.h" #include "llvm/Bitcode/BitcodeWriterPass.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -31,24 +31,21 @@ using namespace llvm; using namespace opt_tool; +static cl::opt + DebugPM("debug-pass-manager", cl::Hidden, + cl::desc("Print pass management debugging information")); + bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, tool_output_file *Out, StringRef PassPipeline, OutputKind OK, VerifierKind VK) { - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - -#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ - MAM.registerPass(CREATE_PASS); -#include "PassRegistry.def" - -#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ - CGAM.registerPass(CREATE_PASS); -#include "PassRegistry.def" + FunctionAnalysisManager FAM(DebugPM); + CGSCCAnalysisManager CGAM(DebugPM); + ModuleAnalysisManager MAM(DebugPM); -#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ - FAM.registerPass(CREATE_PASS); -#include "PassRegistry.def" + // Register all the basic analyses with the managers. + registerModuleAnalyses(MAM); + registerCGSCCAnalyses(CGAM); + registerFunctionAnalyses(FAM); // Cross register the analysis managers through their proxies. MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM)); @@ -58,11 +55,11 @@ bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, FAM.registerPass(CGSCCAnalysisManagerFunctionProxy(CGAM)); FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM)); - ModulePassManager MPM; + ModulePassManager MPM(DebugPM); if (VK > VK_NoVerifier) MPM.addPass(VerifierPass()); - if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass)) { + if (!parsePassPipeline(MPM, PassPipeline, VK == VK_VerifyEachPass, DebugPM)) { errs() << Arg0 << ": unable to parse pass pipeline description.\n"; return false; } @@ -86,7 +83,7 @@ bool llvm::runPassPipeline(StringRef Arg0, LLVMContext &Context, Module &M, cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. - MPM.run(&M, &MAM); + MPM.run(M, &MAM); // Declare success. if (OK != OK_NoOutput) diff --git a/tools/opt/NewPMDriver.h b/tools/opt/NewPMDriver.h index 3661d3e..f977bac 100644 --- a/tools/opt/NewPMDriver.h +++ b/tools/opt/NewPMDriver.h @@ -18,8 +18,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_OPT_NEW_PM_DRIVER_H -#define LLVM_TOOLS_OPT_NEW_PM_DRIVER_H +#ifndef LLVM_TOOLS_OPT_NEWPMDRIVER_H +#define LLVM_TOOLS_OPT_NEWPMDRIVER_H #include "llvm/ADT/StringRef.h" diff --git a/tools/opt/PassRegistry.def b/tools/opt/PassRegistry.def index e1e4900..c98de60 100644 --- a/tools/opt/PassRegistry.def +++ b/tools/opt/PassRegistry.def @@ -20,32 +20,46 @@ #define MODULE_ANALYSIS(NAME, CREATE_PASS) #endif MODULE_ANALYSIS("lcg", LazyCallGraphAnalysis()) +MODULE_ANALYSIS("no-op-module", NoOpModuleAnalysis()) #undef MODULE_ANALYSIS #ifndef MODULE_PASS #define MODULE_PASS(NAME, CREATE_PASS) #endif +MODULE_PASS("invalidate", InvalidateAllAnalysesPass()) +MODULE_PASS("no-op-module", NoOpModulePass()) MODULE_PASS("print", PrintModulePass(dbgs())) MODULE_PASS("print-cg", LazyCallGraphPrinterPass(dbgs())) +MODULE_PASS("verify", VerifierPass()) #undef MODULE_PASS #ifndef CGSCC_ANALYSIS #define CGSCC_ANALYSIS(NAME, CREATE_PASS) #endif +CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis()) #undef CGSCC_ANALYSIS #ifndef CGSCC_PASS #define CGSCC_PASS(NAME, CREATE_PASS) #endif +CGSCC_PASS("invalidate", InvalidateAllAnalysesPass()) +CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass()) #undef CGSCC_PASS #ifndef FUNCTION_ANALYSIS #define FUNCTION_ANALYSIS(NAME, CREATE_PASS) #endif +FUNCTION_ANALYSIS("domtree", DominatorTreeAnalysis()) +FUNCTION_ANALYSIS("no-op-function", NoOpFunctionAnalysis()) #undef FUNCTION_ANALYSIS #ifndef FUNCTION_PASS #define FUNCTION_PASS(NAME, CREATE_PASS) #endif +FUNCTION_PASS("invalidate", InvalidateAllAnalysesPass()) +FUNCTION_PASS("no-op-function", NoOpFunctionPass()) FUNCTION_PASS("print", PrintFunctionPass(dbgs())) +FUNCTION_PASS("print", DominatorTreePrinterPass(dbgs())) +FUNCTION_PASS("verify", VerifierPass()) +FUNCTION_PASS("verify", DominatorTreeVerifierPass()) #undef FUNCTION_PASS diff --git a/tools/opt/Passes.cpp b/tools/opt/Passes.cpp index a171f42..518112a 100644 --- a/tools/opt/Passes.cpp +++ b/tools/opt/Passes.cpp @@ -17,6 +17,7 @@ #include "Passes.h" #include "llvm/Analysis/CGSCCPassManager.h" #include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Verifier.h" @@ -28,96 +29,167 @@ namespace { /// \brief No-op module pass which does nothing. struct NoOpModulePass { - PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); } static StringRef name() { return "NoOpModulePass"; } }; +/// \brief No-op module analysis. +struct NoOpModuleAnalysis { + struct Result {}; + Result run(Module &) { return Result(); } + static StringRef name() { return "NoOpModuleAnalysis"; } + static void *ID() { return (void *)&PassID; } +private: + static char PassID; +}; + +char NoOpModuleAnalysis::PassID; + /// \brief No-op CGSCC pass which does nothing. struct NoOpCGSCCPass { - PreservedAnalyses run(LazyCallGraph::SCC *C) { + PreservedAnalyses run(LazyCallGraph::SCC &C) { return PreservedAnalyses::all(); } static StringRef name() { return "NoOpCGSCCPass"; } }; +/// \brief No-op CGSCC analysis. +struct NoOpCGSCCAnalysis { + struct Result {}; + Result run(LazyCallGraph::SCC &) { return Result(); } + static StringRef name() { return "NoOpCGSCCAnalysis"; } + static void *ID() { return (void *)&PassID; } +private: + static char PassID; +}; + +char NoOpCGSCCAnalysis::PassID; + /// \brief No-op function pass which does nothing. struct NoOpFunctionPass { - PreservedAnalyses run(Function *F) { return PreservedAnalyses::all(); } + PreservedAnalyses run(Function &F) { return PreservedAnalyses::all(); } static StringRef name() { return "NoOpFunctionPass"; } }; +/// \brief No-op function analysis. +struct NoOpFunctionAnalysis { + struct Result {}; + Result run(Function &) { return Result(); } + static StringRef name() { return "NoOpFunctionAnalysis"; } + static void *ID() { return (void *)&PassID; } +private: + static char PassID; +}; + +char NoOpFunctionAnalysis::PassID; + } // End anonymous namespace. -static bool isModulePassName(StringRef Name) { - if (Name == "no-op-module") return true; +void llvm::registerModuleAnalyses(ModuleAnalysisManager &MAM) { +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + MAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" +} +void llvm::registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM) { +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + CGAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" +} + +void llvm::registerFunctionAnalyses(FunctionAnalysisManager &FAM) { +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + FAM.registerPass(CREATE_PASS); +#include "PassRegistry.def" +} + +#ifndef NDEBUG +static bool isModulePassName(StringRef Name) { #define MODULE_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ + return true; #include "PassRegistry.def" return false; } +#endif static bool isCGSCCPassName(StringRef Name) { - if (Name == "no-op-cgscc") return true; - #define CGSCC_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ + return true; #include "PassRegistry.def" return false; } static bool isFunctionPassName(StringRef Name) { - if (Name == "no-op-function") return true; - #define FUNCTION_PASS(NAME, CREATE_PASS) if (Name == NAME) return true; +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \ + return true; #include "PassRegistry.def" return false; } static bool parseModulePassName(ModulePassManager &MPM, StringRef Name) { - if (Name == "no-op-module") { - MPM.addPass(NoOpModulePass()); - return true; - } - #define MODULE_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ MPM.addPass(CREATE_PASS); \ return true; \ } +#define MODULE_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">") { \ + MPM.addPass(RequireAnalysisPass()); \ + return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + MPM.addPass(InvalidateAnalysisPass()); \ + return true; \ + } #include "PassRegistry.def" return false; } static bool parseCGSCCPassName(CGSCCPassManager &CGPM, StringRef Name) { - if (Name == "no-op-cgscc") { - CGPM.addPass(NoOpCGSCCPass()); - return true; - } - #define CGSCC_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ CGPM.addPass(CREATE_PASS); \ return true; \ } +#define CGSCC_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">") { \ + CGPM.addPass(RequireAnalysisPass()); \ + return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + CGPM.addPass(InvalidateAnalysisPass()); \ + return true; \ + } #include "PassRegistry.def" return false; } static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { - if (Name == "no-op-function") { - FPM.addPass(NoOpFunctionPass()); - return true; - } - #define FUNCTION_PASS(NAME, CREATE_PASS) \ if (Name == NAME) { \ FPM.addPass(CREATE_PASS); \ return true; \ } +#define FUNCTION_ANALYSIS(NAME, CREATE_PASS) \ + if (Name == "require<" NAME ">") { \ + FPM.addPass(RequireAnalysisPass()); \ + return true; \ + } \ + if (Name == "invalidate<" NAME ">") { \ + FPM.addPass(InvalidateAnalysisPass()); \ + return true; \ + } #include "PassRegistry.def" return false; @@ -125,15 +197,16 @@ static bool parseFunctionPassName(FunctionPassManager &FPM, StringRef Name) { static bool parseFunctionPassPipeline(FunctionPassManager &FPM, StringRef &PipelineText, - bool VerifyEachPass) { + bool VerifyEachPass, bool DebugLogging) { for (;;) { // Parse nested pass managers by recursing. if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM; + FunctionPassManager NestedFPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -161,16 +234,17 @@ static bool parseFunctionPassPipeline(FunctionPassManager &FPM, } static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, - StringRef &PipelineText, - bool VerifyEachPass) { + StringRef &PipelineText, bool VerifyEachPass, + bool DebugLogging) { for (;;) { // Parse nested pass managers by recursing. if (PipelineText.startswith("cgscc(")) { - CGSCCPassManager NestedCGPM; + CGSCCPassManager NestedCGPM(DebugLogging); // Parse the inner pipeline into the nested manager. PipelineText = PipelineText.substr(strlen("cgscc(")); - if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) || + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -179,11 +253,12 @@ static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, // Add the nested pass manager with the appropriate adaptor. CGPM.addPass(std::move(NestedCGPM)); } else if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM; + FunctionPassManager NestedFPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -211,15 +286,16 @@ static bool parseCGSCCPassPipeline(CGSCCPassManager &CGPM, static bool parseModulePassPipeline(ModulePassManager &MPM, StringRef &PipelineText, - bool VerifyEachPass) { + bool VerifyEachPass, bool DebugLogging) { for (;;) { // Parse nested pass managers by recursing. if (PipelineText.startswith("module(")) { - ModulePassManager NestedMPM; + ModulePassManager NestedMPM(DebugLogging); // Parse the inner pipeline into the nested manager. PipelineText = PipelineText.substr(strlen("module(")); - if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass) || + if (!parseModulePassPipeline(NestedMPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -228,11 +304,12 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, // Now add the nested manager as a module pass. MPM.addPass(std::move(NestedMPM)); } else if (PipelineText.startswith("cgscc(")) { - CGSCCPassManager NestedCGPM; + CGSCCPassManager NestedCGPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("cgscc(")); - if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass) || + if (!parseCGSCCPassPipeline(NestedCGPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -242,11 +319,12 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, MPM.addPass( createModuleToPostOrderCGSCCPassAdaptor(std::move(NestedCGPM))); } else if (PipelineText.startswith("function(")) { - FunctionPassManager NestedFPM; + FunctionPassManager NestedFPM(DebugLogging); // Parse the inner pipeline inte the nested manager. PipelineText = PipelineText.substr(strlen("function(")); - if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass) || + if (!parseFunctionPassPipeline(NestedFPM, PipelineText, VerifyEachPass, + DebugLogging) || PipelineText.empty()) return false; assert(PipelineText[0] == ')'); @@ -277,47 +355,38 @@ static bool parseModulePassPipeline(ModulePassManager &MPM, // FIXME: Should this routine accept a TargetMachine or require the caller to // pre-populate the analysis managers with target-specific stuff? bool llvm::parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass) { - // Look at the first entry to figure out which layer to start parsing at. - if (PipelineText.startswith("module(")) - return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && - PipelineText.empty(); - if (PipelineText.startswith("cgscc(")) { - CGSCCPassManager CGPM; - if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) || - !PipelineText.empty()) - return false; - MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); - return true; - } - if (PipelineText.startswith("function(")) { - FunctionPassManager FPM; - if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || - !PipelineText.empty()) - return false; - MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); - return true; - } - - // This isn't a direct pass manager name, look for the end of a pass name. + bool VerifyEachPass, bool DebugLogging) { + // By default, try to parse the pipeline as-if it were within an implicit + // 'module(...)' pass pipeline. If this will parse at all, it needs to + // consume the entire string. + if (parseModulePassPipeline(MPM, PipelineText, VerifyEachPass, DebugLogging)) + return PipelineText.empty(); + + // This isn't parsable as a module pipeline, look for the end of a pass name + // and directly drop down to that layer. StringRef FirstName = PipelineText.substr(0, PipelineText.find_first_of(",)")); - if (isModulePassName(FirstName)) - return parseModulePassPipeline(MPM, PipelineText, VerifyEachPass) && - PipelineText.empty(); + assert(!isModulePassName(FirstName) && + "Already handled all module pipeline options."); + // If this looks like a CGSCC pass, parse the whole thing as a CGSCC + // pipeline. if (isCGSCCPassName(FirstName)) { - CGSCCPassManager CGPM; - if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass) || + CGSCCPassManager CGPM(DebugLogging); + if (!parseCGSCCPassPipeline(CGPM, PipelineText, VerifyEachPass, + DebugLogging) || !PipelineText.empty()) return false; MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM))); return true; } + // Similarly, if this looks like a Function pass, parse the whole thing as + // a Function pipelien. if (isFunctionPassName(FirstName)) { - FunctionPassManager FPM; - if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass) || + FunctionPassManager FPM(DebugLogging); + if (!parseFunctionPassPipeline(FPM, PipelineText, VerifyEachPass, + DebugLogging) || !PipelineText.empty()) return false; MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); diff --git a/tools/opt/Passes.h b/tools/opt/Passes.h index 3bd6752..623da9f 100644 --- a/tools/opt/Passes.h +++ b/tools/opt/Passes.h @@ -17,9 +17,31 @@ #define LLVM_TOOLS_OPT_PASSES_H #include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/IR/PassManager.h" namespace llvm { -class ModulePassManager; + +/// \brief Registers all available module analysis passes. +/// +/// This is an interface that can be used to populate a \c +/// ModuleAnalysisManager with all registered module analyses. Callers can +/// still manually register any additional analyses. +void registerModuleAnalyses(ModuleAnalysisManager &MAM); + +/// \brief Registers all available CGSCC analysis passes. +/// +/// This is an interface that can be used to populate a \c CGSCCAnalysisManager +/// with all registered CGSCC analyses. Callers can still manually register any +/// additional analyses. +void registerCGSCCAnalyses(CGSCCAnalysisManager &CGAM); + +/// \brief Registers all available function analysis passes. +/// +/// This is an interface that can be used to populate a \c +/// FunctionAnalysisManager with all registered function analyses. Callers can +/// still manually register any additional analyses. +void registerFunctionAnalyses(FunctionAnalysisManager &FAM); /// \brief Parse a textual pass pipeline description into a \c ModulePassManager. /// @@ -50,8 +72,7 @@ class ModulePassManager; /// an error. You cannot mix different levels implicitly, you must explicitly /// form a pass manager in which to nest passes. bool parsePassPipeline(ModulePassManager &MPM, StringRef PipelineText, - bool VerifyEachPass = true); - + bool VerifyEachPass = true, bool DebugLogging = false); } #endif diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp index 6ba6340..9867589 100644 --- a/tools/opt/opt.cpp +++ b/tools/opt/opt.cpp @@ -109,14 +109,6 @@ DisableOptimizations("disable-opt", cl::desc("Do not run any optimization passes")); static cl::opt -DisableInternalize("disable-internalize", - cl::desc("Do not mark all symbols as internal")); - -static cl::opt -StandardCompileOpts("std-compile-opts", - cl::desc("Include the standard compile time optimizations")); - -static cl::opt StandardLinkOpts("std-link-opts", cl::desc("Include the standard link time optimizations")); @@ -145,7 +137,7 @@ TargetTriple("mtriple", cl::desc("Override target triple for module")); static cl::opt UnitAtATime("funit-at-a-time", - cl::desc("Enable IPO. This is same as llvm-gcc's -funit-at-a-time"), + cl::desc("Enable IPO. This corresponds to gcc's -funit-at-a-time"), cl::init(true)); static cl::opt @@ -198,9 +190,8 @@ static inline void addPass(PassManagerBase &PM, Pass *P) { } } -/// AddOptimizationPasses - This routine adds optimization passes -/// based on selected optimization level, OptLevel. This routine -/// duplicates llvm-gcc behaviour. +/// This routine adds optimization passes based on selected optimization level, +/// OptLevel. /// /// OptLevel - Optimization Level static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM, @@ -238,41 +229,16 @@ static void AddOptimizationPasses(PassManagerBase &MPM,FunctionPassManager &FPM, Builder.populateModulePassManager(MPM); } -static void AddStandardCompilePasses(PassManagerBase &PM) { - PM.add(createVerifierPass()); // Verify that input is correct - - // If the -strip-debug command line option was specified, do it. - if (StripDebug) - addPass(PM, createStripSymbolsPass(true)); - - // Verify debug info only after it's (possibly) stripped. - PM.add(createDebugInfoVerifierPass()); - - if (DisableOptimizations) return; - - // -std-compile-opts adds the same module passes as -O3. +static void AddStandardLinkPasses(PassManagerBase &PM) { PassManagerBuilder Builder; + Builder.VerifyInput = true; + Builder.StripDebug = StripDebug; + if (DisableOptimizations) + Builder.OptLevel = 0; + if (!DisableInline) Builder.Inliner = createFunctionInliningPass(); - Builder.OptLevel = 3; - Builder.populateModulePassManager(PM); -} - -static void AddStandardLinkPasses(PassManagerBase &PM) { - PM.add(createVerifierPass()); // Verify that input is correct - - // If the -strip-debug command line option was specified, do it. - if (StripDebug) - addPass(PM, createStripSymbolsPass(true)); - - // Verify debug info only after it's (possibly) stripped. - PM.add(createDebugInfoVerifierPass()); - - if (DisableOptimizations) return; - - PassManagerBuilder Builder; - Builder.populateLTOPassManager(PM, /*Internalize=*/ !DisableInternalize, - /*RunInliner=*/ !DisableInline); + Builder.populateLTOPassManager(PM); } //===----------------------------------------------------------------------===// @@ -341,7 +307,6 @@ int main(int argc, char **argv) { // Initialize passes PassRegistry &Registry = *PassRegistry::getPassRegistry(); initializeCore(Registry); - initializeDebugIRPass(Registry); initializeScalarOpts(Registry); initializeObjCARCOpts(Registry); initializeVectorization(Registry); @@ -355,7 +320,8 @@ int main(int argc, char **argv) { // For codegen passes, only passes that do IR to IR transformation are // supported. initializeCodeGenPreparePass(Registry); - initializeAtomicExpandLoadLinkedPass(Registry); + initializeAtomicExpandPass(Registry); + initializeRewriteSymbolsPass(Registry); #ifdef LINK_POLLY_INTO_TOOLS polly::initializePollyPasses(Registry); @@ -372,10 +338,9 @@ int main(int argc, char **argv) { SMDiagnostic Err; // Load the input module... - std::unique_ptr M; - M.reset(ParseIRFile(InputFilename, Err, Context)); + std::unique_ptr M = parseIRFile(InputFilename, Err, Context); - if (!M.get()) { + if (!M) { Err.print(argv[0], errs()); return 1; } @@ -395,11 +360,10 @@ int main(int argc, char **argv) { if (OutputFilename.empty()) OutputFilename = "-"; - std::string ErrorInfo; - Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, - sys::fs::F_None)); - if (!ErrorInfo.empty()) { - errs() << ErrorInfo << '\n'; + std::error_code EC; + Out.reset(new tool_output_file(OutputFilename, EC, sys::fs::F_None)); + if (EC) { + errs() << EC.message() << '\n'; return 1; } } @@ -425,7 +389,7 @@ int main(int argc, char **argv) { // The user has asked to use the new pass manager and provided a pipeline // string. Hand off the rest of the functionality to the new code for that // layer. - return runPassPipeline(argv[0], Context, *M.get(), Out.get(), PassPipeline, + return runPassPipeline(argv[0], Context, *M, Out.get(), PassPipeline, OK, VK) ? 0 : 1; @@ -445,14 +409,14 @@ int main(int argc, char **argv) { Passes.add(TLI); // Add an appropriate DataLayout instance for this module. - const DataLayout *DL = M.get()->getDataLayout(); + const DataLayout *DL = M->getDataLayout(); if (!DL && !DefaultDataLayout.empty()) { M->setDataLayout(DefaultDataLayout); - DL = M.get()->getDataLayout(); + DL = M->getDataLayout(); } if (DL) - Passes.add(new DataLayoutPass(M.get())); + Passes.add(new DataLayoutPass()); Triple ModuleTriple(M->getTargetTriple()); TargetMachine *Machine = nullptr; @@ -461,15 +425,15 @@ int main(int argc, char **argv) { std::unique_ptr TM(Machine); // Add internal analysis passes from the target machine. - if (TM.get()) + if (TM) TM->addAnalysisPasses(Passes); std::unique_ptr FPasses; if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses.reset(new FunctionPassManager(M.get())); if (DL) - FPasses->add(new DataLayoutPass(M.get())); - if (TM.get()) + FPasses->add(new DataLayoutPass()); + if (TM) TM->addAnalysisPasses(*FPasses); } @@ -480,11 +444,11 @@ int main(int argc, char **argv) { if (OutputFilename.empty()) OutputFilename = "-"; - std::string ErrorInfo; - Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, - sys::fs::F_None)); - if (!ErrorInfo.empty()) { - errs() << ErrorInfo << '\n'; + std::error_code EC; + Out = llvm::make_unique(OutputFilename, EC, + sys::fs::F_None); + if (EC) { + errs() << EC.message() << '\n'; return 1; } } @@ -492,21 +456,12 @@ int main(int argc, char **argv) { NoOutput = true; } - // If the -strip-debug command line option was specified, add it. If - // -std-compile-opts was also specified, it will handle StripDebug. - if (StripDebug && !StandardCompileOpts) + // If the -strip-debug command line option was specified, add it. + if (StripDebug) addPass(Passes, createStripSymbolsPass(true)); // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < PassList.size(); ++i) { - // Check to see if -std-compile-opts was specified before this option. If - // so, handle it. - if (StandardCompileOpts && - StandardCompileOpts.getPosition() < PassList.getPosition(i)) { - AddStandardCompilePasses(Passes); - StandardCompileOpts = false; - } - if (StandardLinkOpts && StandardLinkOpts.getPosition() < PassList.getPosition(i)) { AddStandardLinkPasses(Passes); @@ -579,12 +534,6 @@ int main(int argc, char **argv) { Passes.add(createPrintModulePass(errs())); } - // If -std-compile-opts was specified at the end of the pass list, add them. - if (StandardCompileOpts) { - AddStandardCompilePasses(Passes); - StandardCompileOpts = false; - } - if (StandardLinkOpts) { AddStandardLinkPasses(Passes); StandardLinkOpts = false; @@ -607,8 +556,8 @@ int main(int argc, char **argv) { if (OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz || OptLevelO3) { FPasses->doInitialization(); - for (Module::iterator F = M->begin(), E = M->end(); F != E; ++F) - FPasses->run(*F); + for (Function &F : *M) + FPasses->run(F); FPasses->doFinalization(); } @@ -630,7 +579,7 @@ int main(int argc, char **argv) { cl::PrintOptionValues(); // Now that we have all of the passes ready, run them. - Passes.run(*M.get()); + Passes.run(*M); // Declare success. if (!NoOutput || PrintBreakpoints) diff --git a/tools/verify-uselistorder/CMakeLists.txt b/tools/verify-uselistorder/CMakeLists.txt new file mode 100644 index 0000000..260a95a --- /dev/null +++ b/tools/verify-uselistorder/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + AsmParser + BitReader + BitWriter + Core + IRReader + Support + ) + +add_llvm_tool(verify-uselistorder + verify-uselistorder.cpp + ) diff --git a/tools/verify-uselistorder/LLVMBuild.txt b/tools/verify-uselistorder/LLVMBuild.txt new file mode 100644 index 0000000..23957c1 --- /dev/null +++ b/tools/verify-uselistorder/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/verify-uselistorder/LLVMBuild.txt ----------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = verify-uselistorder +parent = Tools +required_libraries = IRReader BitWriter Support diff --git a/tools/verify-uselistorder/Makefile b/tools/verify-uselistorder/Makefile new file mode 100644 index 0000000..90d2aa8 --- /dev/null +++ b/tools/verify-uselistorder/Makefile @@ -0,0 +1,17 @@ +##===- tools/verify-uselistorder/Makefile ------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL := ../.. +TOOLNAME := verify-uselistorder +LINK_COMPONENTS := AsmParser BitReader BitWriter Core IRReader Support + +# This tool has no plugins, optimize startup time. +TOOL_NO_EXPORTS := 1 + +include $(LEVEL)/Makefile.common diff --git a/tools/verify-uselistorder/verify-uselistorder.cpp b/tools/verify-uselistorder/verify-uselistorder.cpp new file mode 100644 index 0000000..a653608 --- /dev/null +++ b/tools/verify-uselistorder/verify-uselistorder.cpp @@ -0,0 +1,568 @@ +//===- verify-uselistorder.cpp - The LLVM Modular Optimizer ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Verify that use-list order can be serialized correctly. After reading the +// provided IR, this tool shuffles the use-lists and then writes and reads to a +// separate Module whose use-list orders are compared to the original. +// +// The shuffles are deterministic, but guarantee that use-lists will change. +// The algorithm per iteration is as follows: +// +// 1. Seed the random number generator. The seed is different for each +// shuffle. Shuffle 0 uses default+0, shuffle 1 uses default+1, and so on. +// +// 2. Visit every Value in a deterministic order. +// +// 3. Assign a random number to each Use in the Value's use-list in order. +// +// 4. If the numbers are already in order, reassign numbers until they aren't. +// +// 5. Sort the use-list using Value::sortUseList(), which is a stable sort. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/UseListOrder.h" +#include "llvm/IR/Verifier.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/FileUtilities.h" +#include "llvm/Support/ManagedStatic.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/SystemUtils.h" +#include +#include + +using namespace llvm; + +#define DEBUG_TYPE "use-list-order" + +static cl::opt InputFilename(cl::Positional, + cl::desc(""), + cl::init("-"), + cl::value_desc("filename")); + +static cl::opt SaveTemps("save-temps", cl::desc("Save temp files"), + cl::init(false)); + +static cl::opt + NumShuffles("num-shuffles", + cl::desc("Number of times to shuffle and verify use-lists"), + cl::init(1)); + +namespace { + +struct TempFile { + std::string Filename; + FileRemover Remover; + bool init(const std::string &Ext); + bool writeBitcode(const Module &M) const; + bool writeAssembly(const Module &M) const; + std::unique_ptr readBitcode(LLVMContext &Context) const; + std::unique_ptr readAssembly(LLVMContext &Context) const; +}; + +struct ValueMapping { + DenseMap IDs; + std::vector Values; + + /// \brief Construct a value mapping for module. + /// + /// Creates mapping from every value in \c M to an ID. This mapping includes + /// un-referencable values. + /// + /// Every \a Value that gets serialized in some way should be represented + /// here. The order needs to be deterministic, but it's unnecessary to match + /// the value-ids in the bitcode writer. + /// + /// All constants that are referenced by other values are included in the + /// mapping, but others -- which wouldn't be serialized -- are not. + ValueMapping(const Module &M); + + /// \brief Map a value. + /// + /// Maps a value. If it's a constant, maps all of its operands first. + void map(const Value *V); + unsigned lookup(const Value *V) const { return IDs.lookup(V); } +}; + +} // end namespace + +bool TempFile::init(const std::string &Ext) { + SmallVector Vector; + DEBUG(dbgs() << " - create-temp-file\n"); + if (auto EC = sys::fs::createTemporaryFile("use-list-order", Ext, Vector)) { + (void)EC; + DEBUG(dbgs() << "error: " << EC.message() << "\n"); + return true; + } + assert(!Vector.empty()); + + Filename.assign(Vector.data(), Vector.data() + Vector.size()); + Remover.setFile(Filename, !SaveTemps); + DEBUG(dbgs() << " - filename = " << Filename << "\n"); + return false; +} + +bool TempFile::writeBitcode(const Module &M) const { + DEBUG(dbgs() << " - write bitcode\n"); + std::error_code EC; + raw_fd_ostream OS(Filename, EC, sys::fs::F_None); + if (EC) { + DEBUG(dbgs() << "error: " << EC.message() << "\n"); + return true; + } + + WriteBitcodeToFile(&M, OS); + return false; +} + +bool TempFile::writeAssembly(const Module &M) const { + DEBUG(dbgs() << " - write assembly\n"); + std::error_code EC; + raw_fd_ostream OS(Filename, EC, sys::fs::F_Text); + if (EC) { + DEBUG(dbgs() << "error: " << EC.message() << "\n"); + return true; + } + + OS << M; + return false; +} + +std::unique_ptr TempFile::readBitcode(LLVMContext &Context) const { + DEBUG(dbgs() << " - read bitcode\n"); + ErrorOr> BufferOr = + MemoryBuffer::getFile(Filename); + if (!BufferOr) { + DEBUG(dbgs() << "error: " << BufferOr.getError().message() << "\n"); + return nullptr; + } + + MemoryBuffer *Buffer = BufferOr.get().get(); + ErrorOr ModuleOr = + parseBitcodeFile(Buffer->getMemBufferRef(), Context); + if (!ModuleOr) { + DEBUG(dbgs() << "error: " << ModuleOr.getError().message() << "\n"); + return nullptr; + } + return std::unique_ptr(ModuleOr.get()); +} + +std::unique_ptr TempFile::readAssembly(LLVMContext &Context) const { + DEBUG(dbgs() << " - read assembly\n"); + SMDiagnostic Err; + std::unique_ptr M = parseAssemblyFile(Filename, Err, Context); + if (!M.get()) + DEBUG(dbgs() << "error: "; Err.print("verify-use-list-order", dbgs())); + return M; +} + +ValueMapping::ValueMapping(const Module &M) { + // Every value should be mapped, including things like void instructions and + // basic blocks that are kept out of the ValueEnumerator. + // + // The current mapping order makes it easier to debug the tables. It happens + // to be similar to the ID mapping when writing ValueEnumerator, but they + // aren't (and needn't be) in sync. + + // Globals. + for (const GlobalVariable &G : M.globals()) + map(&G); + for (const GlobalAlias &A : M.aliases()) + map(&A); + for (const Function &F : M) + map(&F); + + // Constants used by globals. + for (const GlobalVariable &G : M.globals()) + if (G.hasInitializer()) + map(G.getInitializer()); + for (const GlobalAlias &A : M.aliases()) + map(A.getAliasee()); + for (const Function &F : M) { + if (F.hasPrefixData()) + map(F.getPrefixData()); + if (F.hasPrologueData()) + map(F.getPrologueData()); + } + + // Function bodies. + for (const Function &F : M) { + for (const Argument &A : F.args()) + map(&A); + for (const BasicBlock &BB : F) + map(&BB); + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + map(&I); + + // Constants used by instructions. + for (const BasicBlock &BB : F) + for (const Instruction &I : BB) + for (const Value *Op : I.operands()) + if ((isa(Op) && !isa(*Op)) || + isa(Op)) + map(Op); + } +} + +void ValueMapping::map(const Value *V) { + if (IDs.lookup(V)) + return; + + if (auto *C = dyn_cast(V)) + if (!isa(C)) + for (const Value *Op : C->operands()) + map(Op); + + Values.push_back(V); + IDs[V] = Values.size(); +} + +#ifndef NDEBUG +static void dumpMapping(const ValueMapping &VM) { + dbgs() << "value-mapping (size = " << VM.Values.size() << "):\n"; + for (unsigned I = 0, E = VM.Values.size(); I != E; ++I) { + dbgs() << " - id = " << I << ", value = "; + VM.Values[I]->dump(); + } +} + +static void debugValue(const ValueMapping &M, unsigned I, StringRef Desc) { + const Value *V = M.Values[I]; + dbgs() << " - " << Desc << " value = "; + V->dump(); + for (const Use &U : V->uses()) { + dbgs() << " => use: op = " << U.getOperandNo() + << ", user-id = " << M.IDs.lookup(U.getUser()) << ", user = "; + U.getUser()->dump(); + } +} + +static void debugUserMismatch(const ValueMapping &L, const ValueMapping &R, + unsigned I) { + dbgs() << " - fail: user mismatch: ID = " << I << "\n"; + debugValue(L, I, "LHS"); + debugValue(R, I, "RHS"); + + dbgs() << "\nlhs-"; + dumpMapping(L); + dbgs() << "\nrhs-"; + dumpMapping(R); +} + +static void debugSizeMismatch(const ValueMapping &L, const ValueMapping &R) { + dbgs() << " - fail: map size: " << L.Values.size() + << " != " << R.Values.size() << "\n"; + dbgs() << "\nlhs-"; + dumpMapping(L); + dbgs() << "\nrhs-"; + dumpMapping(R); +} +#endif + +static bool matches(const ValueMapping &LM, const ValueMapping &RM) { + DEBUG(dbgs() << "compare value maps\n"); + if (LM.Values.size() != RM.Values.size()) { + DEBUG(debugSizeMismatch(LM, RM)); + return false; + } + + // This mapping doesn't include dangling constant users, since those don't + // get serialized. However, checking if users are constant and calling + // isConstantUsed() on every one is very expensive. Instead, just check if + // the user is mapped. + auto skipUnmappedUsers = + [&](Value::const_use_iterator &U, Value::const_use_iterator E, + const ValueMapping &M) { + while (U != E && !M.lookup(U->getUser())) + ++U; + }; + + // Iterate through all values, and check that both mappings have the same + // users. + for (unsigned I = 0, E = LM.Values.size(); I != E; ++I) { + const Value *L = LM.Values[I]; + const Value *R = RM.Values[I]; + auto LU = L->use_begin(), LE = L->use_end(); + auto RU = R->use_begin(), RE = R->use_end(); + skipUnmappedUsers(LU, LE, LM); + skipUnmappedUsers(RU, RE, RM); + + while (LU != LE) { + if (RU == RE) { + DEBUG(debugUserMismatch(LM, RM, I)); + return false; + } + if (LM.lookup(LU->getUser()) != RM.lookup(RU->getUser())) { + DEBUG(debugUserMismatch(LM, RM, I)); + return false; + } + if (LU->getOperandNo() != RU->getOperandNo()) { + DEBUG(debugUserMismatch(LM, RM, I)); + return false; + } + skipUnmappedUsers(++LU, LE, LM); + skipUnmappedUsers(++RU, RE, RM); + } + if (RU != RE) { + DEBUG(debugUserMismatch(LM, RM, I)); + return false; + } + } + + return true; +} + +static void verifyAfterRoundTrip(const Module &M, + std::unique_ptr OtherM) { + if (!OtherM) + report_fatal_error("parsing failed"); + if (verifyModule(*OtherM, &errs())) + report_fatal_error("verification failed"); + if (!matches(ValueMapping(M), ValueMapping(*OtherM))) + report_fatal_error("use-list order changed"); +} +static void verifyBitcodeUseListOrder(const Module &M) { + errs() << "*** verify-use-list-order: bitcode ***\n"; + TempFile F; + if (F.init("bc")) + report_fatal_error("failed to initialize bitcode file"); + + if (F.writeBitcode(M)) + report_fatal_error("failed to write bitcode"); + + LLVMContext Context; + verifyAfterRoundTrip(M, F.readBitcode(Context)); +} + +static void verifyAssemblyUseListOrder(const Module &M) { + errs() << "*** verify-use-list-order: assembly ***\n"; + TempFile F; + if (F.init("ll")) + report_fatal_error("failed to initialize assembly file"); + + if (F.writeAssembly(M)) + report_fatal_error("failed to write assembly"); + + LLVMContext Context; + verifyAfterRoundTrip(M, F.readAssembly(Context)); +} + +static void verifyUseListOrder(const Module &M) { + verifyBitcodeUseListOrder(M); + verifyAssemblyUseListOrder(M); +} + +static void shuffleValueUseLists(Value *V, std::minstd_rand0 &Gen, + DenseSet &Seen) { + if (!Seen.insert(V).second) + return; + + if (auto *C = dyn_cast(V)) + if (!isa(C)) + for (Value *Op : C->operands()) + shuffleValueUseLists(Op, Gen, Seen); + + if (V->use_empty() || std::next(V->use_begin()) == V->use_end()) + // Nothing to shuffle for 0 or 1 users. + return; + + // Generate random numbers between 10 and 99, which will line up nicely in + // debug output. We're not worried about collisons here. + DEBUG(dbgs() << "V = "; V->dump()); + std::uniform_int_distribution Dist(10, 99); + SmallDenseMap Order; + auto compareUses = + [&Order](const Use &L, const Use &R) { return Order[&L] < Order[&R]; }; + do { + for (const Use &U : V->uses()) { + auto I = Dist(Gen); + Order[&U] = I; + DEBUG(dbgs() << " - order: " << I << ", op = " << U.getOperandNo() + << ", U = "; + U.getUser()->dump()); + } + } while (std::is_sorted(V->use_begin(), V->use_end(), compareUses)); + + DEBUG(dbgs() << " => shuffle\n"); + V->sortUseList(compareUses); + + DEBUG({ + for (const Use &U : V->uses()) { + dbgs() << " - order: " << Order.lookup(&U) + << ", op = " << U.getOperandNo() << ", U = "; + U.getUser()->dump(); + } + }); +} + +static void reverseValueUseLists(Value *V, DenseSet &Seen) { + if (!Seen.insert(V).second) + return; + + if (auto *C = dyn_cast(V)) + if (!isa(C)) + for (Value *Op : C->operands()) + reverseValueUseLists(Op, Seen); + + if (V->use_empty() || std::next(V->use_begin()) == V->use_end()) + // Nothing to shuffle for 0 or 1 users. + return; + + DEBUG({ + dbgs() << "V = "; + V->dump(); + for (const Use &U : V->uses()) { + dbgs() << " - order: op = " << U.getOperandNo() << ", U = "; + U.getUser()->dump(); + } + dbgs() << " => reverse\n"; + }); + + V->reverseUseList(); + + DEBUG({ + for (const Use &U : V->uses()) { + dbgs() << " - order: op = " << U.getOperandNo() << ", U = "; + U.getUser()->dump(); + } + }); +} + +template +static void changeUseLists(Module &M, Changer changeValueUseList) { + // Visit every value that would be serialized to an IR file. + // + // Globals. + for (GlobalVariable &G : M.globals()) + changeValueUseList(&G); + for (GlobalAlias &A : M.aliases()) + changeValueUseList(&A); + for (Function &F : M) + changeValueUseList(&F); + + // Constants used by globals. + for (GlobalVariable &G : M.globals()) + if (G.hasInitializer()) + changeValueUseList(G.getInitializer()); + for (GlobalAlias &A : M.aliases()) + changeValueUseList(A.getAliasee()); + for (Function &F : M) { + if (F.hasPrefixData()) + changeValueUseList(F.getPrefixData()); + if (F.hasPrologueData()) + changeValueUseList(F.getPrologueData()); + } + + // Function bodies. + for (Function &F : M) { + for (Argument &A : F.args()) + changeValueUseList(&A); + for (BasicBlock &BB : F) + changeValueUseList(&BB); + for (BasicBlock &BB : F) + for (Instruction &I : BB) + changeValueUseList(&I); + + // Constants used by instructions. + for (BasicBlock &BB : F) + for (Instruction &I : BB) + for (Value *Op : I.operands()) + if ((isa(Op) && !isa(*Op)) || + isa(Op)) + changeValueUseList(Op); + } + + if (verifyModule(M, &errs())) + report_fatal_error("verification failed"); +} + +static void shuffleUseLists(Module &M, unsigned SeedOffset) { + errs() << "*** shuffle-use-lists ***\n"; + std::minstd_rand0 Gen(std::minstd_rand0::default_seed + SeedOffset); + DenseSet Seen; + changeUseLists(M, [&](Value *V) { shuffleValueUseLists(V, Gen, Seen); }); + DEBUG(dbgs() << "\n"); +} + +static void reverseUseLists(Module &M) { + errs() << "*** reverse-use-lists ***\n"; + DenseSet Seen; + changeUseLists(M, [&](Value *V) { reverseValueUseLists(V, Seen); }); + DEBUG(dbgs() << "\n"); +} + +int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(); + llvm::PrettyStackTraceProgram X(argc, argv); + + // Enable debug stream buffering. + EnableDebugBuffering = true; + + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + LLVMContext &Context = getGlobalContext(); + + cl::ParseCommandLineOptions(argc, argv, + "llvm tool to verify use-list order\n"); + + SMDiagnostic Err; + + // Load the input module... + std::unique_ptr M = parseIRFile(InputFilename, Err, Context); + + if (!M.get()) { + Err.print(argv[0], errs()); + return 1; + } + if (verifyModule(*M, &errs())) + report_fatal_error("verification failed"); + + errs() << "*** verify-use-list-order ***\n"; + // Can't verify if order isn't preserved. + if (!shouldPreserveBitcodeUseListOrder()) { + errs() << "warning: forcing -preserve-bc-use-list-order\n"; + setPreserveBitcodeUseListOrder(true); + } + if (!shouldPreserveAssemblyUseListOrder()) { + errs() << "warning: forcing -preserve-ll-use-list-order\n"; + setPreserveAssemblyUseListOrder(true); + } + + // Verify the use lists now and after reversing them. + verifyUseListOrder(*M); + reverseUseLists(*M); + verifyUseListOrder(*M); + + for (unsigned I = 0, E = NumShuffles; I != E; ++I) { + errs() << "*** shuffle iteration: " << I + 1 << " of " << E << " ***\n"; + + // Shuffle with a different (deterministic) seed each time. + shuffleUseLists(*M, I); + + // Verify again before and after reversing. + verifyUseListOrder(*M); + reverseUseLists(*M); + verifyUseListOrder(*M); + } + + return 0; +} diff --git a/tools/yaml2obj/CMakeLists.txt b/tools/yaml2obj/CMakeLists.txt index 78e92a0..52e9df4 100644 --- a/tools/yaml2obj/CMakeLists.txt +++ b/tools/yaml2obj/CMakeLists.txt @@ -4,7 +4,7 @@ set(LLVM_LINK_COMPONENTS Support ) -add_llvm_utility(yaml2obj +add_llvm_tool(yaml2obj yaml2obj.cpp yaml2coff.cpp yaml2elf.cpp diff --git a/tools/yaml2obj/Makefile b/tools/yaml2obj/Makefile index 8801795..912f0e3 100644 --- a/tools/yaml2obj/Makefile +++ b/tools/yaml2obj/Makefile @@ -14,7 +14,4 @@ LINK_COMPONENTS := object # This tool has no plugins, optimize startup time. TOOL_NO_EXPORTS = 1 -# Don't install this utility -NO_INSTALL = 1 - include $(LEVEL)/Makefile.common diff --git a/tools/yaml2obj/yaml2coff.cpp b/tools/yaml2obj/yaml2coff.cpp index c772db9..8322b2f 100644 --- a/tools/yaml2obj/yaml2coff.cpp +++ b/tools/yaml2obj/yaml2coff.cpp @@ -13,11 +13,12 @@ //===----------------------------------------------------------------------===// #include "yaml2obj.h" -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Object/COFF.h" #include "llvm/Object/COFFYAML.h" #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" @@ -30,12 +31,35 @@ using namespace llvm; /// This parses a yaml stream that represents a COFF object file. /// See docs/yaml2obj for the yaml scheema. struct COFFParser { - COFFParser(COFFYAML::Object &Obj) : Obj(Obj) { + COFFParser(COFFYAML::Object &Obj) + : Obj(Obj), SectionTableStart(0), SectionTableSize(0) { // A COFF string table always starts with a 4 byte size field. Offsets into // it include this size, so allocate it now. StringTable.append(4, char(0)); } + bool useBigObj() const { + return static_cast(Obj.Sections.size()) > + COFF::MaxNumberOfSections16; + } + + bool isPE() const { return Obj.OptionalHeader.hasValue(); } + bool is64Bit() const { + return Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64; + } + + uint32_t getFileAlignment() const { + return Obj.OptionalHeader->Header.FileAlignment; + } + + unsigned getHeaderSize() const { + return useBigObj() ? COFF::Header32Size : COFF::Header16Size; + } + + unsigned getSymbolSize() const { + return useBigObj() ? COFF::Symbol32Size : COFF::Symbol16Size; + } + bool parseSections() { for (std::vector::iterator i = Obj.Sections.begin(), e = Obj.Sections.end(); i != e; ++i) { @@ -111,39 +135,61 @@ struct COFFParser { StringMap StringTableMap; std::string StringTable; + uint32_t SectionTableStart; + uint32_t SectionTableSize; }; // Take a CP and assign addresses and sizes to everything. Returns false if the // layout is not valid to do. -static bool layoutCOFF(COFFParser &CP) { - uint32_t SectionTableStart = 0; - uint32_t SectionTableSize = 0; +static bool layoutOptionalHeader(COFFParser &CP) { + if (!CP.isPE()) + return true; + unsigned PEHeaderSize = CP.is64Bit() ? sizeof(object::pe32plus_header) + : sizeof(object::pe32_header); + CP.Obj.Header.SizeOfOptionalHeader = + PEHeaderSize + + sizeof(object::data_directory) * (COFF::NUM_DATA_DIRECTORIES + 1); + return true; +} + +namespace { +enum { DOSStubSize = 128 }; +} +// Take a CP and assign addresses and sizes to everything. Returns false if the +// layout is not valid to do. +static bool layoutCOFF(COFFParser &CP) { // The section table starts immediately after the header, including the // optional header. - SectionTableStart = sizeof(COFF::header) + CP.Obj.Header.SizeOfOptionalHeader; - SectionTableSize = sizeof(COFF::section) * CP.Obj.Sections.size(); + CP.SectionTableStart = + CP.getHeaderSize() + CP.Obj.Header.SizeOfOptionalHeader; + if (CP.isPE()) + CP.SectionTableStart += DOSStubSize + sizeof(COFF::PEMagic); + CP.SectionTableSize = COFF::SectionSize * CP.Obj.Sections.size(); - uint32_t CurrentSectionDataOffset = SectionTableStart + SectionTableSize; + uint32_t CurrentSectionDataOffset = + CP.SectionTableStart + CP.SectionTableSize; // Assign each section data address consecutively. - for (std::vector::iterator i = CP.Obj.Sections.begin(), - e = CP.Obj.Sections.end(); - i != e; ++i) { - if (i->SectionData.binary_size() > 0) { - i->Header.SizeOfRawData = i->SectionData.binary_size(); - i->Header.PointerToRawData = CurrentSectionDataOffset; - CurrentSectionDataOffset += i->Header.SizeOfRawData; - if (!i->Relocations.empty()) { - i->Header.PointerToRelocations = CurrentSectionDataOffset; - i->Header.NumberOfRelocations = i->Relocations.size(); - CurrentSectionDataOffset += i->Header.NumberOfRelocations * - COFF::RelocationSize; + for (COFFYAML::Section &S : CP.Obj.Sections) { + if (S.SectionData.binary_size() > 0) { + CurrentSectionDataOffset = RoundUpToAlignment( + CurrentSectionDataOffset, CP.isPE() ? CP.getFileAlignment() : 4); + S.Header.SizeOfRawData = S.SectionData.binary_size(); + if (CP.isPE()) + S.Header.SizeOfRawData = + RoundUpToAlignment(S.Header.SizeOfRawData, CP.getFileAlignment()); + S.Header.PointerToRawData = CurrentSectionDataOffset; + CurrentSectionDataOffset += S.Header.SizeOfRawData; + if (!S.Relocations.empty()) { + S.Header.PointerToRelocations = CurrentSectionDataOffset; + S.Header.NumberOfRelocations = S.Relocations.size(); + CurrentSectionDataOffset += + S.Header.NumberOfRelocations * COFF::RelocationSize; } - // TODO: Handle alignment. } else { - i->Header.SizeOfRawData = 0; - i->Header.PointerToRawData = 0; + S.Header.SizeOfRawData = 0; + S.Header.PointerToRawData = 0; } } @@ -163,7 +209,7 @@ static bool layoutCOFF(COFFParser &CP) { NumberOfAuxSymbols += 1; if (!i->File.empty()) NumberOfAuxSymbols += - (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize; + (i->File.size() + CP.getSymbolSize() - 1) / CP.getSymbolSize(); if (i->SectionDefinition) NumberOfAuxSymbols += 1; if (i->CLRToken) @@ -175,7 +221,10 @@ static bool layoutCOFF(COFFParser &CP) { // Store all the allocated start addresses in the header. CP.Obj.Header.NumberOfSections = CP.Obj.Sections.size(); CP.Obj.Header.NumberOfSymbols = NumberOfSymbols; - CP.Obj.Header.PointerToSymbolTable = SymbolTableStart; + if (NumberOfSymbols > 0 || CP.StringTable.size() > 4) + CP.Obj.Header.PointerToSymbolTable = SymbolTableStart; + else + CP.Obj.Header.PointerToSymbolTable = 0; *reinterpret_cast(&CP.StringTable[0]) = CP.StringTable.size(); @@ -222,15 +271,153 @@ zeros_impl zeros(const T &) { return zeros_impl(); } -bool writeCOFF(COFFParser &CP, raw_ostream &OS) { - OS << binary_le(CP.Obj.Header.Machine) - << binary_le(CP.Obj.Header.NumberOfSections) - << binary_le(CP.Obj.Header.TimeDateStamp) - << binary_le(CP.Obj.Header.PointerToSymbolTable) - << binary_le(CP.Obj.Header.NumberOfSymbols) - << binary_le(CP.Obj.Header.SizeOfOptionalHeader) - << binary_le(CP.Obj.Header.Characteristics); +struct num_zeros_impl { + size_t N; + num_zeros_impl(size_t N) : N(N) {} +}; + +raw_ostream &operator<<(raw_ostream &OS, const num_zeros_impl &NZI) { + for (size_t I = 0; I != NZI.N; ++I) + OS.write(0); + return OS; +} + +num_zeros_impl num_zeros(size_t N) { + num_zeros_impl NZI(N); + return NZI; +} + +template +static uint32_t initializeOptionalHeader(COFFParser &CP, uint16_t Magic, T Header) { + memset(Header, 0, sizeof(*Header)); + Header->Magic = Magic; + Header->SectionAlignment = CP.Obj.OptionalHeader->Header.SectionAlignment; + Header->FileAlignment = CP.Obj.OptionalHeader->Header.FileAlignment; + uint32_t SizeOfCode = 0, SizeOfInitializedData = 0, + SizeOfUninitializedData = 0; + uint32_t SizeOfHeaders = RoundUpToAlignment( + CP.SectionTableStart + CP.SectionTableSize, Header->FileAlignment); + uint32_t SizeOfImage = + RoundUpToAlignment(SizeOfHeaders, Header->SectionAlignment); + uint32_t BaseOfData = 0; + for (const COFFYAML::Section &S : CP.Obj.Sections) { + if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_CODE) + SizeOfCode += S.Header.SizeOfRawData; + if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) + SizeOfInitializedData += S.Header.SizeOfRawData; + if (S.Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) + SizeOfUninitializedData += S.Header.SizeOfRawData; + if (S.Name.equals(".text")) + Header->BaseOfCode = S.Header.VirtualAddress; // RVA + else if (S.Name.equals(".data")) + BaseOfData = S.Header.VirtualAddress; // RVA + if (S.Header.VirtualAddress) + SizeOfImage += + RoundUpToAlignment(S.Header.VirtualSize, Header->SectionAlignment); + } + Header->SizeOfCode = SizeOfCode; + Header->SizeOfInitializedData = SizeOfInitializedData; + Header->SizeOfUninitializedData = SizeOfUninitializedData; + Header->AddressOfEntryPoint = + CP.Obj.OptionalHeader->Header.AddressOfEntryPoint; // RVA + Header->ImageBase = CP.Obj.OptionalHeader->Header.ImageBase; + Header->MajorOperatingSystemVersion = + CP.Obj.OptionalHeader->Header.MajorOperatingSystemVersion; + Header->MinorOperatingSystemVersion = + CP.Obj.OptionalHeader->Header.MinorOperatingSystemVersion; + Header->MajorImageVersion = + CP.Obj.OptionalHeader->Header.MajorImageVersion; + Header->MinorImageVersion = + CP.Obj.OptionalHeader->Header.MinorImageVersion; + Header->MajorSubsystemVersion = + CP.Obj.OptionalHeader->Header.MajorSubsystemVersion; + Header->MinorSubsystemVersion = + CP.Obj.OptionalHeader->Header.MinorSubsystemVersion; + Header->SizeOfImage = SizeOfImage; + Header->SizeOfHeaders = SizeOfHeaders; + Header->Subsystem = CP.Obj.OptionalHeader->Header.Subsystem; + Header->DLLCharacteristics = CP.Obj.OptionalHeader->Header.DLLCharacteristics; + Header->SizeOfStackReserve = CP.Obj.OptionalHeader->Header.SizeOfStackReserve; + Header->SizeOfStackCommit = CP.Obj.OptionalHeader->Header.SizeOfStackCommit; + Header->SizeOfHeapReserve = CP.Obj.OptionalHeader->Header.SizeOfHeapReserve; + Header->SizeOfHeapCommit = CP.Obj.OptionalHeader->Header.SizeOfHeapCommit; + Header->NumberOfRvaAndSize = COFF::NUM_DATA_DIRECTORIES + 1; + return BaseOfData; +} + +static bool writeCOFF(COFFParser &CP, raw_ostream &OS) { + if (CP.isPE()) { + // PE files start with a DOS stub. + object::dos_header DH; + memset(&DH, 0, sizeof(DH)); + + // DOS EXEs start with "MZ" magic. + DH.Magic[0] = 'M'; + DH.Magic[1] = 'Z'; + // Initializing the AddressOfRelocationTable is strictly optional but + // mollifies certain tools which expect it to have a value greater than + // 0x40. + DH.AddressOfRelocationTable = sizeof(DH); + // This is the address of the PE signature. + DH.AddressOfNewExeHeader = DOSStubSize; + + // Write out our DOS stub. + OS.write(reinterpret_cast(&DH), sizeof(DH)); + // Write padding until we reach the position of where our PE signature + // should live. + OS << num_zeros(DOSStubSize - sizeof(DH)); + // Write out the PE signature. + OS.write(COFF::PEMagic, sizeof(COFF::PEMagic)); + } + if (CP.useBigObj()) { + OS << binary_le(static_cast(COFF::IMAGE_FILE_MACHINE_UNKNOWN)) + << binary_le(static_cast(0xffff)) + << binary_le(static_cast(COFF::BigObjHeader::MinBigObjectVersion)) + << binary_le(CP.Obj.Header.Machine) + << binary_le(CP.Obj.Header.TimeDateStamp); + OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)); + OS << zeros(uint32_t(0)) + << zeros(uint32_t(0)) + << zeros(uint32_t(0)) + << zeros(uint32_t(0)) + << binary_le(CP.Obj.Header.NumberOfSections) + << binary_le(CP.Obj.Header.PointerToSymbolTable) + << binary_le(CP.Obj.Header.NumberOfSymbols); + } else { + OS << binary_le(CP.Obj.Header.Machine) + << binary_le(static_cast(CP.Obj.Header.NumberOfSections)) + << binary_le(CP.Obj.Header.TimeDateStamp) + << binary_le(CP.Obj.Header.PointerToSymbolTable) + << binary_le(CP.Obj.Header.NumberOfSymbols) + << binary_le(CP.Obj.Header.SizeOfOptionalHeader) + << binary_le(CP.Obj.Header.Characteristics); + } + if (CP.isPE()) { + if (CP.is64Bit()) { + object::pe32plus_header PEH; + initializeOptionalHeader(CP, COFF::PE32Header::PE32_PLUS, &PEH); + OS.write(reinterpret_cast(&PEH), sizeof(PEH)); + } else { + object::pe32_header PEH; + uint32_t BaseOfData = initializeOptionalHeader(CP, COFF::PE32Header::PE32, &PEH); + PEH.BaseOfData = BaseOfData; + OS.write(reinterpret_cast(&PEH), sizeof(PEH)); + } + for (const Optional &DD : + CP.Obj.OptionalHeader->DataDirectories) { + if (!DD.hasValue()) { + OS << zeros(uint32_t(0)); + OS << zeros(uint32_t(0)); + } else { + OS << binary_le(DD->RelativeVirtualAddress); + OS << binary_le(DD->Size); + } + } + OS << zeros(uint32_t(0)); + OS << zeros(uint32_t(0)); + } + assert(OS.tell() == CP.SectionTableStart); // Output section table. for (std::vector::iterator i = CP.Obj.Sections.begin(), e = CP.Obj.Sections.end(); @@ -246,6 +433,7 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) { << binary_le(i->Header.NumberOfLineNumbers) << binary_le(i->Header.Characteristics); } + assert(OS.tell() == CP.SectionTableStart + CP.SectionTableSize); unsigned CurSymbol = 0; StringMap SymbolTableIndexMap; @@ -257,12 +445,15 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) { } // Output section data. - for (std::vector::iterator i = CP.Obj.Sections.begin(), - e = CP.Obj.Sections.end(); - i != e; ++i) { - i->SectionData.writeAsBinary(OS); - for (unsigned I2 = 0, E2 = i->Relocations.size(); I2 != E2; ++I2) { - const COFFYAML::Relocation &R = i->Relocations[I2]; + for (const COFFYAML::Section &S : CP.Obj.Sections) { + if (!S.Header.SizeOfRawData) + continue; + assert(S.Header.PointerToRawData >= OS.tell()); + OS << num_zeros(S.Header.PointerToRawData - OS.tell()); + S.SectionData.writeAsBinary(OS); + assert(S.Header.SizeOfRawData >= S.SectionData.binary_size()); + OS << num_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size()); + for (const COFFYAML::Relocation &R : S.Relocations) { uint32_t SymbolTableIndex = SymbolTableIndexMap[R.SymbolName]; OS << binary_le(R.VirtualAddress) << binary_le(SymbolTableIndex) @@ -276,9 +467,12 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) { e = CP.Obj.Symbols.end(); i != e; ++i) { OS.write(i->Header.Name, COFF::NameSize); - OS << binary_le(i->Header.Value) - << binary_le(i->Header.SectionNumber) - << binary_le(i->Header.Type) + OS << binary_le(i->Header.Value); + if (CP.useBigObj()) + OS << binary_le(i->Header.SectionNumber); + else + OS << binary_le(static_cast(i->Header.SectionNumber)); + OS << binary_le(i->Header.Type) << binary_le(i->Header.StorageClass) << binary_le(i->Header.NumberOfAuxSymbols); @@ -287,43 +481,50 @@ bool writeCOFF(COFFParser &CP, raw_ostream &OS) { << binary_le(i->FunctionDefinition->TotalSize) << binary_le(i->FunctionDefinition->PointerToLinenumber) << binary_le(i->FunctionDefinition->PointerToNextFunction) - << zeros(i->FunctionDefinition->unused); + << zeros(i->FunctionDefinition->unused) + << num_zeros(CP.getSymbolSize() - COFF::Symbol16Size); if (i->bfAndefSymbol) OS << zeros(i->bfAndefSymbol->unused1) << binary_le(i->bfAndefSymbol->Linenumber) << zeros(i->bfAndefSymbol->unused2) << binary_le(i->bfAndefSymbol->PointerToNextFunction) - << zeros(i->bfAndefSymbol->unused3); + << zeros(i->bfAndefSymbol->unused3) + << num_zeros(CP.getSymbolSize() - COFF::Symbol16Size); if (i->WeakExternal) OS << binary_le(i->WeakExternal->TagIndex) << binary_le(i->WeakExternal->Characteristics) - << zeros(i->WeakExternal->unused); + << zeros(i->WeakExternal->unused) + << num_zeros(CP.getSymbolSize() - COFF::Symbol16Size); if (!i->File.empty()) { + unsigned SymbolSize = CP.getSymbolSize(); uint32_t NumberOfAuxRecords = - (i->File.size() + COFF::SymbolSize - 1) / COFF::SymbolSize; - uint32_t NumberOfAuxBytes = NumberOfAuxRecords * COFF::SymbolSize; + (i->File.size() + SymbolSize - 1) / SymbolSize; + uint32_t NumberOfAuxBytes = NumberOfAuxRecords * SymbolSize; uint32_t NumZeros = NumberOfAuxBytes - i->File.size(); OS.write(i->File.data(), i->File.size()); - for (uint32_t Padding = 0; Padding < NumZeros; ++Padding) - OS.write(0); + OS << num_zeros(NumZeros); } if (i->SectionDefinition) OS << binary_le(i->SectionDefinition->Length) << binary_le(i->SectionDefinition->NumberOfRelocations) << binary_le(i->SectionDefinition->NumberOfLinenumbers) << binary_le(i->SectionDefinition->CheckSum) - << binary_le(i->SectionDefinition->Number) + << binary_le(static_cast(i->SectionDefinition->Number)) << binary_le(i->SectionDefinition->Selection) - << zeros(i->SectionDefinition->unused); + << zeros(i->SectionDefinition->unused) + << binary_le(static_cast(i->SectionDefinition->Number >> 16)) + << num_zeros(CP.getSymbolSize() - COFF::Symbol16Size); if (i->CLRToken) OS << binary_le(i->CLRToken->AuxType) << zeros(i->CLRToken->unused1) << binary_le(i->CLRToken->SymbolTableIndex) - << zeros(i->CLRToken->unused2); + << zeros(i->CLRToken->unused2) + << num_zeros(CP.getSymbolSize() - COFF::Symbol16Size); } // Output string table. - OS.write(&CP.StringTable[0], CP.StringTable.size()); + if (CP.Obj.Header.PointerToSymbolTable) + OS.write(&CP.StringTable[0], CP.StringTable.size()); return true; } @@ -341,6 +542,10 @@ int yaml2coff(yaml::Input &YIn, raw_ostream &Out) { return 1; } + if (!layoutOptionalHeader(CP)) { + errs() << "yaml2obj: Failed to layout optional header for COFF file!\n"; + return 1; + } if (!layoutCOFF(CP)) { errs() << "yaml2obj: Failed to layout COFF file!\n"; return 1; diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index 6eeecae..44c8c12 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -62,11 +62,7 @@ class NameToIdxMap { public: /// \returns true if name is already present in the map. bool addName(StringRef Name, unsigned i) { - StringMapEntry &Entry = Map.GetOrCreateValue(Name, -1); - if (Entry.getValue() != -1) - return true; - Entry.setValue((int)i); - return false; + return !Map.insert(std::make_pair(Name, (int)i)).second; } /// \returns true if name is not present in the map bool lookup(StringRef Name, unsigned &Idx) const { @@ -190,7 +186,7 @@ bool ELFState::initSectionHeaders(std::vector &SHeaders, for (const auto &Sec : Doc.Sections) DotShStrtab.add(Sec->Name); - DotShStrtab.finalize(); + DotShStrtab.finalize(StringTableBuilder::ELF); for (const auto &Sec : Doc.Sections) { zero(SHeader); @@ -261,7 +257,7 @@ void ELFState::initSymtabSectionHeader(Elf_Shdr &SHeader, DotStrtab.add(Sym.Name); for (const auto &Sym : Doc.Symbols.Weak) DotStrtab.add(Sym.Name); - DotStrtab.finalize(); + DotStrtab.finalize(StringTableBuilder::ELF); addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL); addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL); @@ -304,7 +300,7 @@ void ELFState::addSymbols(const std::vector &Symbols, Symbol.st_shndx = Index; } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier. Symbol.st_value = Sym.Value; - Symbol.st_other = Sym.Visibility; + Symbol.st_other = Sym.Other; Symbol.st_size = Sym.Size; Syms.push_back(Symbol); } diff --git a/tools/yaml2obj/yaml2obj.cpp b/tools/yaml2obj/yaml2obj.cpp index 945fad1..375cd89 100644 --- a/tools/yaml2obj/yaml2obj.cpp +++ b/tools/yaml2obj/yaml2obj.cpp @@ -83,11 +83,11 @@ int main(int argc, char **argv) { if (OutputFilename.empty()) OutputFilename = "-"; - std::string ErrorInfo; + std::error_code EC; std::unique_ptr Out( - new tool_output_file(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None)); - if (!ErrorInfo.empty()) { - errs() << ErrorInfo << '\n'; + new tool_output_file(OutputFilename, EC, sys::fs::F_None)); + if (EC) { + errs() << EC.message() << '\n'; return 1; } diff --git a/tools/yaml2obj/yaml2obj.h b/tools/yaml2obj/yaml2obj.h index 086f641..7290a9a 100644 --- a/tools/yaml2obj/yaml2obj.h +++ b/tools/yaml2obj/yaml2obj.h @@ -9,8 +9,8 @@ /// \file /// \brief Common declarations for yaml2obj //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_YAML2OBJ_H -#define LLVM_TOOLS_YAML2OBJ_H +#ifndef LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H +#define LLVM_TOOLS_YAML2OBJ_YAML2OBJ_H namespace llvm { class raw_ostream; diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 8f298cd..8b82fb2 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -474,6 +474,81 @@ TEST(APFloatTest, FMA) { f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); EXPECT_EQ(12.0f, f1.convertToFloat()); } + + // Test for correct zero sign when answer is exactly zero. + // fma(1.0, -1.0, 1.0) -> +ve 0. + { + APFloat f1(1.0); + APFloat f2(-1.0); + APFloat f3(1.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); + EXPECT_TRUE(!f1.isNegative() && f1.isZero()); + } + + // Test for correct zero sign when answer is exactly zero and rounding towards + // negative. + // fma(1.0, -1.0, 1.0) -> +ve 0. + { + APFloat f1(1.0); + APFloat f2(-1.0); + APFloat f3(1.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmTowardNegative); + EXPECT_TRUE(f1.isNegative() && f1.isZero()); + } + + // Test for correct (in this case -ve) sign when adding like signed zeros. + // Test fma(0.0, -0.0, -0.0) -> -ve 0. + { + APFloat f1(0.0); + APFloat f2(-0.0); + APFloat f3(-0.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); + EXPECT_TRUE(f1.isNegative() && f1.isZero()); + } + + // Test -ve sign preservation when small negative results underflow. + { + APFloat f1(APFloat::IEEEdouble, "-0x1p-1074"); + APFloat f2(APFloat::IEEEdouble, "+0x1p-1074"); + APFloat f3(0.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); + EXPECT_TRUE(f1.isNegative() && f1.isZero()); + } + + // Test x87 extended precision case from http://llvm.org/PR20728. + { + APFloat M1(APFloat::x87DoubleExtended, 1.0); + APFloat M2(APFloat::x87DoubleExtended, 1.0); + APFloat A(APFloat::x87DoubleExtended, 3.0); + + bool losesInfo = false; + M1.fusedMultiplyAdd(M1, A, APFloat::rmNearestTiesToEven); + M1.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_FALSE(losesInfo); + EXPECT_EQ(4.0f, M1.convertToFloat()); + } +} + +TEST(APFloatTest, MinNum) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + + EXPECT_EQ(1.0, minnum(f1, f2).convertToDouble()); + EXPECT_EQ(1.0, minnum(f2, f1).convertToDouble()); + EXPECT_EQ(1.0, minnum(f1, nan).convertToDouble()); + EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); +} + +TEST(APFloatTest, MaxNum) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + + EXPECT_EQ(2.0, maxnum(f1, f2).convertToDouble()); + EXPECT_EQ(2.0, maxnum(f2, f1).convertToDouble()); + EXPECT_EQ(1.0, maxnum(f1, nan).convertToDouble()); + EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); } TEST(APFloatTest, Denormal) { @@ -1342,6 +1417,17 @@ TEST(APFloatTest, getZero) { } } +TEST(APFloatTest, copySign) { + EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(42.0), APFloat(-1.0)))); + EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(-42.0), APFloat(1.0)))); + EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(-42.0), APFloat(-1.0)))); + EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(42.0), APFloat(1.0)))); +} + TEST(APFloatTest, convert) { bool losesInfo; APFloat test(APFloat::IEEEdouble, "1.0"); @@ -2671,4 +2757,123 @@ TEST(APFloatTest, divide) { } } +TEST(APFloatTest, operatorOverloads) { + // This is mostly testing that these operator overloads compile. + APFloat One = APFloat(APFloat::IEEEsingle, "0x1p+0"); + APFloat Two = APFloat(APFloat::IEEEsingle, "0x2p+0"); + EXPECT_TRUE(Two.bitwiseIsEqual(One + One)); + EXPECT_TRUE(One.bitwiseIsEqual(Two - One)); + EXPECT_TRUE(Two.bitwiseIsEqual(One * Two)); + EXPECT_TRUE(One.bitwiseIsEqual(Two / Two)); +} + +TEST(APFloatTest, abs) { + APFloat PInf = APFloat::getInf(APFloat::IEEEsingle, false); + APFloat MInf = APFloat::getInf(APFloat::IEEEsingle, true); + APFloat PZero = APFloat::getZero(APFloat::IEEEsingle, false); + APFloat MZero = APFloat::getZero(APFloat::IEEEsingle, true); + APFloat PQNaN = APFloat::getNaN(APFloat::IEEEsingle, false); + APFloat MQNaN = APFloat::getNaN(APFloat::IEEEsingle, true); + APFloat PSNaN = APFloat::getSNaN(APFloat::IEEEsingle, false); + APFloat MSNaN = APFloat::getSNaN(APFloat::IEEEsingle, true); + APFloat PNormalValue = APFloat(APFloat::IEEEsingle, "0x1p+0"); + APFloat MNormalValue = APFloat(APFloat::IEEEsingle, "-0x1p+0"); + APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle, false); + APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle, true); + APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, false); + APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, true); + APFloat PSmallestNormalized = + APFloat::getSmallestNormalized(APFloat::IEEEsingle, false); + APFloat MSmallestNormalized = + APFloat::getSmallestNormalized(APFloat::IEEEsingle, true); + + EXPECT_TRUE(PInf.bitwiseIsEqual(abs(PInf))); + EXPECT_TRUE(PInf.bitwiseIsEqual(abs(MInf))); + EXPECT_TRUE(PZero.bitwiseIsEqual(abs(PZero))); + EXPECT_TRUE(PZero.bitwiseIsEqual(abs(MZero))); + EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(PQNaN))); + EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(MQNaN))); + EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(PSNaN))); + EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(MSNaN))); + EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(PNormalValue))); + EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(MNormalValue))); + EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(PLargestValue))); + EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(MLargestValue))); + EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(PSmallestValue))); + EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(MSmallestValue))); + EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(PSmallestNormalized))); + EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized))); +} + +TEST(APFloatTest, ilogb) { + EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+0"))); + EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "-0x1p+0"))); + EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+42"))); + EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p-42"))); + + EXPECT_EQ(APFloat::IEK_Inf, + ilogb(APFloat::getInf(APFloat::IEEEsingle, false))); + EXPECT_EQ(APFloat::IEK_Inf, + ilogb(APFloat::getInf(APFloat::IEEEsingle, true))); + EXPECT_EQ(APFloat::IEK_Zero, + ilogb(APFloat::getZero(APFloat::IEEEsingle, false))); + EXPECT_EQ(APFloat::IEK_Zero, + ilogb(APFloat::getZero(APFloat::IEEEsingle, true))); + EXPECT_EQ(APFloat::IEK_NaN, + ilogb(APFloat::getNaN(APFloat::IEEEsingle, false))); + EXPECT_EQ(APFloat::IEK_NaN, + ilogb(APFloat::getSNaN(APFloat::IEEEsingle, false))); + + EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, false))); + EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, true))); + EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false))); + EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, true))); + EXPECT_EQ(-126, + ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, false))); + EXPECT_EQ(-126, + ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, true))); +} + +TEST(APFloatTest, scalbn) { + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p+0") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 0))); + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p+42") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 42))); + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p-42") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -42))); + + APFloat PInf = APFloat::getInf(APFloat::IEEEsingle, false); + APFloat MInf = APFloat::getInf(APFloat::IEEEsingle, true); + APFloat PZero = APFloat::getZero(APFloat::IEEEsingle, false); + APFloat MZero = APFloat::getZero(APFloat::IEEEsingle, true); + APFloat QPNaN = APFloat::getNaN(APFloat::IEEEsingle, false); + APFloat QMNaN = APFloat::getNaN(APFloat::IEEEsingle, true); + APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle, false); + + EXPECT_TRUE(PInf.bitwiseIsEqual(scalbn(PInf, 0))); + EXPECT_TRUE(MInf.bitwiseIsEqual(scalbn(MInf, 0))); + EXPECT_TRUE(PZero.bitwiseIsEqual(scalbn(PZero, 0))); + EXPECT_TRUE(MZero.bitwiseIsEqual(scalbn(MZero, 0))); + EXPECT_TRUE(QPNaN.bitwiseIsEqual(scalbn(QPNaN, 0))); + EXPECT_TRUE(QMNaN.bitwiseIsEqual(scalbn(QMNaN, 0))); + EXPECT_TRUE(SNaN.bitwiseIsEqual(scalbn(SNaN, 0))); + + EXPECT_TRUE( + PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 128))); + EXPECT_TRUE(MInf.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), 128))); + EXPECT_TRUE( + PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+127"), 1))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -127))); + EXPECT_TRUE(MZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), -127))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); +} } diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 19c47ab..3b7ac5b 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -614,7 +614,7 @@ TEST(APIntTest, arrayAccess) { 0x7E7FFA5EADD8846ULL, 0x305F341CA00B613DULL }; - APInt A2(integerPartWidth*4, ArrayRef(E2, 4)); + APInt A2(integerPartWidth*4, E2); for (unsigned i = 0; i < 4; ++i) { for (unsigned j = 0; j < integerPartWidth; ++j) { EXPECT_EQ(bool(E2[i] & (1ULL << j)), @@ -653,17 +653,17 @@ TEST(APIntTest, nearestLogBase2) { // Test round up. integerPart I4[4] = {0x0, 0xF, 0x18, 0x0}; - APInt A4(integerPartWidth*4, ArrayRef(I4, 4)); + APInt A4(integerPartWidth*4, I4); EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2()); // Test round down. integerPart I5[4] = {0x0, 0xF, 0x10, 0x0}; - APInt A5(integerPartWidth*4, ArrayRef(I5, 4)); + APInt A5(integerPartWidth*4, I5); EXPECT_EQ(A5.nearestLogBase2(), A5.logBase2()); // Test ties round up. uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18}; - APInt A6(integerPartWidth*4, ArrayRef(I6, 4)); + APInt A6(integerPartWidth*4, I6); EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2()); // Test BitWidth == 1 special cases. @@ -678,4 +678,32 @@ TEST(APIntTest, nearestLogBase2) { EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX); } +#if defined(__clang__) +// Disable the pragma warning from versions of Clang without -Wself-move +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-pragmas" +// Disable the warning that triggers on exactly what is being tested. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wself-move" +#endif +TEST(APIntTest, SelfMoveAssignment) { + APInt X(32, 0xdeadbeef); + X = std::move(X); + EXPECT_EQ(32u, X.getBitWidth()); + EXPECT_EQ(0xdeadbeefULL, X.getLimitedValue()); + + uint64_t Bits[] = {0xdeadbeefdeadbeefULL, 0xdeadbeefdeadbeefULL}; + APInt Y(128, Bits); + Y = std::move(Y); + EXPECT_EQ(128u, Y.getBitWidth()); + EXPECT_EQ(~0ULL, Y.getLimitedValue()); + const uint64_t *Raw = Y.getRawData(); + EXPECT_EQ(2u, Y.getNumWords()); + EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]); + EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]); +} +#if defined(__clang__) +#pragma clang diagnostic pop +#pragma clang diagnostic pop +#endif } diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp index 293afc6..f9c98a5 100644 --- a/unittests/ADT/ArrayRefTest.cpp +++ b/unittests/ADT/ArrayRefTest.cpp @@ -13,6 +13,23 @@ #include "gtest/gtest.h" using namespace llvm; +// Check that the ArrayRef-of-pointer converting constructor only allows adding +// cv qualifiers (not removing them, or otherwise changing the type) +static_assert( + std::is_convertible, ArrayRef>::value, + "Adding const"); +static_assert( + std::is_convertible, ArrayRef>::value, + "Adding volatile"); +static_assert(!std::is_convertible, ArrayRef>::value, + "Changing pointer of one type to a pointer of another"); +static_assert( + !std::is_convertible, ArrayRef>::value, + "Removing const"); +static_assert( + !std::is_convertible, ArrayRef>::value, + "Removing volatile"); + namespace llvm { TEST(ArrayRefTest, AllocatorCopy) { @@ -36,5 +53,41 @@ TEST(ArrayRefTest, DropBack) { EXPECT_TRUE(AR1.drop_back().equals(AR2)); } +TEST(ArrayRefTest, Equals) { + static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8}; + ArrayRef AR1(A1); + EXPECT_TRUE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 8)); + EXPECT_FALSE(AR1.equals(8, 1, 2, 4, 5, 6, 6, 7)); + EXPECT_FALSE(AR1.equals(2, 4, 5, 6, 6, 7, 8, 1)); + EXPECT_FALSE(AR1.equals(0, 1, 2, 4, 5, 6, 6, 7)); + EXPECT_FALSE(AR1.equals(1, 2, 42, 4, 5, 6, 7, 8)); + EXPECT_FALSE(AR1.equals(42, 2, 3, 4, 5, 6, 7, 8)); + EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 42)); + EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7)); + EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 8, 9)); + + ArrayRef AR1a = AR1.drop_back(); + EXPECT_TRUE(AR1a.equals(1, 2, 3, 4, 5, 6, 7)); + EXPECT_FALSE(AR1a.equals(1, 2, 3, 4, 5, 6, 7, 8)); + + ArrayRef AR1b = AR1a.slice(2, 4); + EXPECT_TRUE(AR1b.equals(3, 4, 5, 6)); + EXPECT_FALSE(AR1b.equals(2, 3, 4, 5, 6)); + EXPECT_FALSE(AR1b.equals(3, 4, 5, 6, 7)); +} + +TEST(ArrayRefTest, EmptyEquals) { + EXPECT_TRUE(ArrayRef() == ArrayRef()); +} + +TEST(ArrayRefTest, ConstConvert) { + int buf[4]; + for (int i = 0; i < 4; ++i) + buf[i] = i; + + static int *A[] = {&buf[0], &buf[1], &buf[2], &buf[3]}; + ArrayRef a((ArrayRef(A))); + a = ArrayRef(A); +} } // end anonymous namespace diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt index 0f214f3..d899852 100644 --- a/unittests/ADT/CMakeLists.txt +++ b/unittests/ADT/CMakeLists.txt @@ -13,6 +13,7 @@ set(ADTSources DenseMapTest.cpp DenseSetTest.cpp FoldingSet.cpp + FunctionRefTest.cpp HashingTest.cpp ilistTest.cpp ImmutableMapTest.cpp @@ -26,6 +27,7 @@ set(ADTSources PackedVectorTest.cpp PointerIntPairTest.cpp PointerUnionTest.cpp + PostOrderIteratorTest.cpp SCCIteratorTest.cpp SmallPtrSetTest.cpp SmallStringTest.cpp diff --git a/unittests/ADT/DenseMapTest.cpp b/unittests/ADT/DenseMapTest.cpp index 75a910a..f4979839 100644 --- a/unittests/ADT/DenseMapTest.cpp +++ b/unittests/ADT/DenseMapTest.cpp @@ -244,6 +244,11 @@ TYPED_TEST(DenseMapTest, AssignmentTest) { EXPECT_EQ(1u, copyMap.size()); EXPECT_EQ(this->getValue(), copyMap[this->getKey()]); + + // test self-assignment. + copyMap = copyMap; + EXPECT_EQ(1u, copyMap.size()); + EXPECT_EQ(this->getValue(), copyMap[this->getKey()]); } // Test swap method diff --git a/unittests/ADT/DenseSetTest.cpp b/unittests/ADT/DenseSetTest.cpp index 154c589..5952353 100644 --- a/unittests/ADT/DenseSetTest.cpp +++ b/unittests/ADT/DenseSetTest.cpp @@ -27,4 +27,42 @@ TEST_F(DenseSetTest, DoubleEntrySetTest) { EXPECT_EQ(0u, set.count(2)); } +struct TestDenseSetInfo { + static inline unsigned getEmptyKey() { return ~0; } + static inline unsigned getTombstoneKey() { return ~0U - 1; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } + static unsigned getHashValue(const char* Val) { + return (unsigned)(Val[0] - 'a') * 37U; + } + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { + return LHS == RHS; + } + static bool isEqual(const char* LHS, const unsigned& RHS) { + return (unsigned)(LHS[0] - 'a') == RHS; + } +}; + +TEST(DenseSetCustomTest, FindAsTest) { + DenseSet set; + set.insert(0); + set.insert(1); + set.insert(2); + + // Size tests + EXPECT_EQ(3u, set.size()); + + // Normal lookup tests + EXPECT_EQ(1u, set.count(1)); + EXPECT_EQ(0u, *set.find(0)); + EXPECT_EQ(1u, *set.find(1)); + EXPECT_EQ(2u, *set.find(2)); + EXPECT_TRUE(set.find(3) == set.end()); + + // find_as() tests + EXPECT_EQ(0u, *set.find_as("a")); + EXPECT_EQ(1u, *set.find_as("b")); + EXPECT_EQ(2u, *set.find_as("c")); + EXPECT_TRUE(set.find_as("d") == set.end()); +} + } diff --git a/unittests/ADT/FunctionRefTest.cpp b/unittests/ADT/FunctionRefTest.cpp new file mode 100644 index 0000000..075d9a0 --- /dev/null +++ b/unittests/ADT/FunctionRefTest.cpp @@ -0,0 +1,28 @@ +//===- llvm/unittest/ADT/MakeUniqueTest.cpp - make_unique unit tests ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +// Ensure that copies of a function_ref copy the underlying state rather than +// causing one function_ref to chain to the next. +TEST(FunctionRefTest, Copy) { + auto A = [] { return 1; }; + auto B = [] { return 2; }; + function_ref X = A; + function_ref Y = X; + X = B; + EXPECT_EQ(1, Y()); +} + +} diff --git a/unittests/ADT/MapVectorTest.cpp b/unittests/ADT/MapVectorTest.cpp index 92f0dc4..2caa8c7 100644 --- a/unittests/ADT/MapVectorTest.cpp +++ b/unittests/ADT/MapVectorTest.cpp @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/iterator_range.h" #include using namespace llvm; @@ -67,6 +68,14 @@ TEST(MapVectorTest, erase) { ASSERT_EQ(MV.find(1), MV.end()); ASSERT_EQ(MV[3], 4); ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(3), 1u); + ASSERT_EQ(MV.size(), 1u); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(79), 0u); + ASSERT_EQ(MV.size(), 1u); } TEST(MapVectorTest, remove_if) { @@ -89,3 +98,245 @@ TEST(MapVectorTest, remove_if) { ASSERT_EQ(MV[4], 14); ASSERT_EQ(MV[6], 16); } + +TEST(MapVectorTest, iteration_test) { + MapVector MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + int count = 1; + for (auto P : make_range(MV.begin(), MV.end())) { + ASSERT_EQ(P.first, count); + count++; + } + + count = 6; + for (auto P : make_range(MV.rbegin(), MV.rend())) { + ASSERT_EQ(P.first, count); + count--; + } +} + +TEST(SmallMapVectorSmallTest, insert_pop) { + SmallMapVector MV; + std::pair::iterator, bool> R; + + R = MV.insert(std::make_pair(1, 2)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_TRUE(R.second); + + R = MV.insert(std::make_pair(1, 3)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_FALSE(R.second); + + R = MV.insert(std::make_pair(4, 5)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 5); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 5); + + MV.pop_back(); + EXPECT_EQ(MV.size(), 1u); + EXPECT_EQ(MV[1], 2); + + R = MV.insert(std::make_pair(4, 7)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 7); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 7); +} + +TEST(SmallMapVectorSmallTest, erase) { + SmallMapVector MV; + + MV.insert(std::make_pair(1, 2)); + MV.insert(std::make_pair(3, 4)); + MV.insert(std::make_pair(5, 6)); + ASSERT_EQ(MV.size(), 3u); + + MV.erase(MV.find(1)); + ASSERT_EQ(MV.size(), 2u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV[3], 4); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(3), 1u); + ASSERT_EQ(MV.size(), 1u); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(79), 0u); + ASSERT_EQ(MV.size(), 1u); +} + +TEST(SmallMapVectorSmallTest, remove_if) { + SmallMapVector MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + MV.remove_if([](const std::pair &Val) { return Val.second % 2; }); + ASSERT_EQ(MV.size(), 3u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV.find(5), MV.end()); + ASSERT_EQ(MV[2], 12); + ASSERT_EQ(MV[4], 14); + ASSERT_EQ(MV[6], 16); +} + +TEST(SmallMapVectorSmallTest, iteration_test) { + SmallMapVector MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + int count = 1; + for (auto P : make_range(MV.begin(), MV.end())) { + ASSERT_EQ(P.first, count); + count++; + } + + count = 6; + for (auto P : make_range(MV.rbegin(), MV.rend())) { + ASSERT_EQ(P.first, count); + count--; + } +} + +TEST(SmallMapVectorLargeTest, insert_pop) { + SmallMapVector MV; + std::pair::iterator, bool> R; + + R = MV.insert(std::make_pair(1, 2)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_TRUE(R.second); + + R = MV.insert(std::make_pair(1, 3)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_FALSE(R.second); + + R = MV.insert(std::make_pair(4, 5)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 5); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 5); + + MV.pop_back(); + EXPECT_EQ(MV.size(), 1u); + EXPECT_EQ(MV[1], 2); + + R = MV.insert(std::make_pair(4, 7)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 7); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 7); +} + +TEST(SmallMapVectorLargeTest, erase) { + SmallMapVector MV; + + MV.insert(std::make_pair(1, 2)); + MV.insert(std::make_pair(3, 4)); + MV.insert(std::make_pair(5, 6)); + ASSERT_EQ(MV.size(), 3u); + + MV.erase(MV.find(1)); + ASSERT_EQ(MV.size(), 2u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV[3], 4); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(3), 1u); + ASSERT_EQ(MV.size(), 1u); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(79), 0u); + ASSERT_EQ(MV.size(), 1u); +} + +TEST(SmallMapVectorLargeTest, remove_if) { + SmallMapVector MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + MV.remove_if([](const std::pair &Val) { return Val.second % 2; }); + ASSERT_EQ(MV.size(), 3u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV.find(5), MV.end()); + ASSERT_EQ(MV[2], 12); + ASSERT_EQ(MV[4], 14); + ASSERT_EQ(MV[6], 16); +} + +TEST(SmallMapVectorLargeTest, iteration_test) { + SmallMapVector MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + int count = 1; + for (auto P : make_range(MV.begin(), MV.end())) { + ASSERT_EQ(P.first, count); + count++; + } + + count = 6; + for (auto P : make_range(MV.rbegin(), MV.rend())) { + ASSERT_EQ(P.first, count); + count--; + } +} diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index 2da408c..cadadce 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -169,6 +169,52 @@ TEST_F(OptionalTest, NullCopyConstructionTest) { EXPECT_EQ(0u, NonDefaultConstructible::Destructions); } +TEST_F(OptionalTest, GetValueOr) { + Optional A; + EXPECT_EQ(42, A.getValueOr(42)); + + A = 5; + EXPECT_EQ(5, A.getValueOr(42)); +} + +struct MultiArgConstructor { + int x, y; + MultiArgConstructor(int x, int y) : x(x), y(y) {} + explicit MultiArgConstructor(int x, bool positive) + : x(x), y(positive ? x : -x) {} + + MultiArgConstructor(const MultiArgConstructor &) LLVM_DELETED_FUNCTION; + MultiArgConstructor(MultiArgConstructor &&) LLVM_DELETED_FUNCTION; + MultiArgConstructor &operator=(const MultiArgConstructor &) LLVM_DELETED_FUNCTION; + MultiArgConstructor &operator=(MultiArgConstructor &&) LLVM_DELETED_FUNCTION; + + static unsigned Destructions; + ~MultiArgConstructor() { + ++Destructions; + } + static void ResetCounts() { + Destructions = 0; + } +}; +unsigned MultiArgConstructor::Destructions = 0; + +TEST_F(OptionalTest, Emplace) { + MultiArgConstructor::ResetCounts(); + Optional A; + + A.emplace(1, 2); + EXPECT_TRUE(A.hasValue()); + EXPECT_EQ(1, A->x); + EXPECT_EQ(2, A->y); + EXPECT_EQ(0u, MultiArgConstructor::Destructions); + + A.emplace(5, false); + EXPECT_TRUE(A.hasValue()); + EXPECT_EQ(5, A->x); + EXPECT_EQ(-5, A->y); + EXPECT_EQ(1u, MultiArgConstructor::Destructions); +} + struct MoveOnly { static unsigned MoveConstructions; static unsigned Destructions; @@ -278,5 +324,58 @@ TEST_F(OptionalTest, MoveOnlyAssigningAssignment) { EXPECT_EQ(1u, MoveOnly::Destructions); } +struct Immovable { + static unsigned Constructions; + static unsigned Destructions; + int val; + explicit Immovable(int val) : val(val) { + ++Constructions; + } + ~Immovable() { + ++Destructions; + } + static void ResetCounts() { + Constructions = 0; + Destructions = 0; + } +private: + // This should disable all move/copy operations. + Immovable(Immovable&& other) LLVM_DELETED_FUNCTION; +}; + +unsigned Immovable::Constructions = 0; +unsigned Immovable::Destructions = 0; + +TEST_F(OptionalTest, ImmovableEmplace) { + Optional A; + Immovable::ResetCounts(); + A.emplace(4); + EXPECT_TRUE((bool)A); + EXPECT_EQ(4, A->val); + EXPECT_EQ(1u, Immovable::Constructions); + EXPECT_EQ(0u, Immovable::Destructions); +} + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + +TEST_F(OptionalTest, MoveGetValueOr) { + Optional A; + + MoveOnly::ResetCounts(); + EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val); + EXPECT_EQ(1u, MoveOnly::MoveConstructions); + EXPECT_EQ(0u, MoveOnly::MoveAssignments); + EXPECT_EQ(2u, MoveOnly::Destructions); + + A = MoveOnly(5); + MoveOnly::ResetCounts(); + EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val); + EXPECT_EQ(1u, MoveOnly::MoveConstructions); + EXPECT_EQ(0u, MoveOnly::MoveAssignments); + EXPECT_EQ(2u, MoveOnly::Destructions); +} + +#endif // LLVM_HAS_RVALUE_REFERENCE_THIS + } // end anonymous namespace diff --git a/unittests/ADT/PostOrderIteratorTest.cpp b/unittests/ADT/PostOrderIteratorTest.cpp new file mode 100644 index 0000000..1da1078 --- /dev/null +++ b/unittests/ADT/PostOrderIteratorTest.cpp @@ -0,0 +1,37 @@ +//===- PostOrderIteratorTest.cpp - PostOrderIterator unit tests -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "gtest/gtest.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" +using namespace llvm; + +namespace { + +// Whether we're able to compile +TEST(PostOrderIteratorTest, Compiles) { + typedef SmallPtrSet ExtSetTy; + + // Tests that template specializations are kept up to date + void *Null = nullptr; + po_iterator_storage, false> PIS; + PIS.insertEdge(Null, Null); + ExtSetTy Ext; + po_iterator_storage PISExt(Ext); + PIS.insertEdge(Null, Null); + + // Test above, but going through po_iterator (which inherits from template + // base) + BasicBlock *NullBB = nullptr; + auto PI = po_end(NullBB); + PI.insertEdge(NullBB, NullBB); + auto PIExt = po_ext_end(NullBB, Ext); + PIExt.insertEdge(NullBB, NullBB); +} +} diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp index 95bf33e..ba6c395 100644 --- a/unittests/ADT/SmallVectorTest.cpp +++ b/unittests/ADT/SmallVectorTest.cpp @@ -699,4 +699,134 @@ TEST(SmallVectorTest, MidInsert) { EXPECT_TRUE(m.hasValue); } +enum EmplaceableArgState { + EAS_Defaulted, + EAS_Arg, + EAS_LValue, + EAS_RValue, + EAS_Failure +}; +template struct EmplaceableArg { + EmplaceableArgState State; + EmplaceableArg() : State(EAS_Defaulted) {} + EmplaceableArg(EmplaceableArg &&X) + : State(X.State == EAS_Arg ? EAS_RValue : EAS_Failure) {} + EmplaceableArg(EmplaceableArg &X) + : State(X.State == EAS_Arg ? EAS_LValue : EAS_Failure) {} + + explicit EmplaceableArg(bool) : State(EAS_Arg) {} + +private: + EmplaceableArg &operator=(EmplaceableArg &&) LLVM_DELETED_FUNCTION; + EmplaceableArg &operator=(const EmplaceableArg &) LLVM_DELETED_FUNCTION; +}; + +enum EmplaceableState { ES_Emplaced, ES_Moved }; +struct Emplaceable { + EmplaceableArg<0> A0; + EmplaceableArg<1> A1; + EmplaceableArg<2> A2; + EmplaceableArg<3> A3; + EmplaceableState State; + + Emplaceable() : State(ES_Emplaced) {} + + template + explicit Emplaceable(A0Ty &&A0) + : A0(std::forward(A0)), State(ES_Emplaced) {} + + template + Emplaceable(A0Ty &&A0, A1Ty &&A1) + : A0(std::forward(A0)), A1(std::forward(A1)), + State(ES_Emplaced) {} + + template + Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2) + : A0(std::forward(A0)), A1(std::forward(A1)), + A2(std::forward(A2)), State(ES_Emplaced) {} + + template + Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2, A3Ty &&A3) + : A0(std::forward(A0)), A1(std::forward(A1)), + A2(std::forward(A2)), A3(std::forward(A3)), + State(ES_Emplaced) {} + + Emplaceable(Emplaceable &&) : State(ES_Moved) {} + Emplaceable &operator=(Emplaceable &&) { + State = ES_Moved; + return *this; + } + +private: + Emplaceable(const Emplaceable &) LLVM_DELETED_FUNCTION; + Emplaceable &operator=(const Emplaceable &) LLVM_DELETED_FUNCTION; +}; + +TEST(SmallVectorTest, EmplaceBack) { + EmplaceableArg<0> A0(true); + EmplaceableArg<1> A1(true); + EmplaceableArg<2> A2(true); + EmplaceableArg<3> A3(true); + { + SmallVector V; + V.emplace_back(); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A1.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector V; + V.emplace_back(std::move(A0)); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_RValue); + EXPECT_TRUE(V.back().A1.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector V; + V.emplace_back(A0); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_LValue); + EXPECT_TRUE(V.back().A1.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector V; + V.emplace_back(A0, A1); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_LValue); + EXPECT_TRUE(V.back().A1.State == EAS_LValue); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector V; + V.emplace_back(std::move(A0), std::move(A1)); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_RValue); + EXPECT_TRUE(V.back().A1.State == EAS_RValue); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector V; + V.emplace_back(std::move(A0), A1, std::move(A2), A3); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_RValue); + EXPECT_TRUE(V.back().A1.State == EAS_LValue); + EXPECT_TRUE(V.back().A2.State == EAS_RValue); + EXPECT_TRUE(V.back().A3.State == EAS_LValue); + } } + +} // end namespace diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index 028375d..33d668f 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -250,15 +250,21 @@ struct StringMapTestStruct { TEST_F(StringMapTest, NonDefaultConstructable) { StringMap t; - t.GetOrCreateValue("Test", StringMapTestStruct(123)); + t.insert(std::make_pair("Test", StringMapTestStruct(123))); StringMap::iterator iter = t.find("Test"); ASSERT_NE(iter, t.end()); ASSERT_EQ(iter->second.i, 123); } +struct Immovable { + Immovable() {} + Immovable(Immovable&&) LLVM_DELETED_FUNCTION; // will disable the other special members +}; + struct MoveOnly { int i; MoveOnly(int i) : i(i) {} + MoveOnly(const Immovable&) : i(0) {} MoveOnly(MoveOnly &&RHS) : i(RHS.i) {} MoveOnly &operator=(MoveOnly &&RHS) { i = RHS.i; @@ -270,17 +276,23 @@ private: MoveOnly &operator=(const MoveOnly &) LLVM_DELETED_FUNCTION; }; -TEST_F(StringMapTest, MoveOnlyKey) { +TEST_F(StringMapTest, MoveOnly) { StringMap t; - t.GetOrCreateValue("Test", MoveOnly(42)); + t.insert(std::make_pair("Test", MoveOnly(42))); StringRef Key = "Test"; StringMapEntry::Create(Key, MoveOnly(42)) ->Destroy(); } +TEST_F(StringMapTest, CtorArg) { + StringRef Key = "Test"; + StringMapEntry::Create(Key, Immovable()) + ->Destroy(); +} + TEST_F(StringMapTest, MoveConstruct) { StringMap A; - A.GetOrCreateValue("x", 42); + A["x"] = 42; StringMap B = std::move(A); ASSERT_EQ(A.size(), 0u); ASSERT_EQ(B.size(), 1u); @@ -325,7 +337,7 @@ struct Countable { TEST_F(StringMapTest, MoveDtor) { int InstanceCount = 0; StringMap A; - A.GetOrCreateValue("x", Countable(42, InstanceCount)); + A.insert(std::make_pair("x", Countable(42, InstanceCount))); ASSERT_EQ(InstanceCount, 1); auto I = A.find("x"); ASSERT_NE(I, A.end()); diff --git a/unittests/ADT/TinyPtrVectorTest.cpp b/unittests/ADT/TinyPtrVectorTest.cpp index ec868d4..a402e8b 100644 --- a/unittests/ADT/TinyPtrVectorTest.cpp +++ b/unittests/ADT/TinyPtrVectorTest.cpp @@ -412,3 +412,29 @@ TYPED_TEST(TinyPtrVectorTest, InsertRange) { } } + +TEST(TinyPtrVectorTest, SingleEltCtorTest) { + int v = 55; + TinyPtrVector V(&v); + + EXPECT_TRUE(V.size() == 1); + EXPECT_FALSE(V.empty()); + EXPECT_TRUE(V.front() == &v); +} + +TEST(TinyPtrVectorTest, ArrayRefCtorTest) { + int data_array[128]; + std::vector data; + + for (unsigned i = 0, e = 128; i != e; ++i) { + data_array[i] = 324 - int(i); + data.push_back(&data_array[i]); + } + + TinyPtrVector V(data); + EXPECT_TRUE(V.size() == 128); + EXPECT_FALSE(V.empty()); + for (unsigned i = 0, e = 128; i != e; ++i) { + EXPECT_TRUE(V[i] == data[i]); + } +} diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index dfc9983..cacbde6 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -129,6 +129,36 @@ TEST(TripleTest, ParsedIDs) { EXPECT_EQ(Triple::UnknownOS, T.getOS()); EXPECT_EQ(Triple::EABI, T.getEnvironment()); + T = Triple("amdil-unknown-unknown"); + EXPECT_EQ(Triple::amdil, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("amdil64-unknown-unknown"); + EXPECT_EQ(Triple::amdil64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("hsail-unknown-unknown"); + EXPECT_EQ(Triple::hsail, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("hsail64-unknown-unknown"); + EXPECT_EQ(Triple::hsail64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("spir-unknown-unknown"); + EXPECT_EQ(Triple::spir, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("spir64-unknown-unknown"); + EXPECT_EQ(Triple::spir64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + T = Triple("huh"); EXPECT_EQ(Triple::UnknownArch, T.getArch()); } @@ -190,7 +220,7 @@ TEST(TripleTest, Normalization) { ++Vendor) { C[1] = Triple::getVendorTypeName(Triple::VendorType(Vendor)); for (int OS = 1+Triple::UnknownOS; OS <= Triple::Minix; ++OS) { - if (OS == Triple::Cygwin || OS == Triple::MinGW32 || OS == Triple::Win32) + if (OS == Triple::Win32) continue; C[2] = Triple::getOSTypeName(Triple::OSType(OS)); @@ -341,6 +371,36 @@ TEST(TripleTest, BitWidthPredicates) { EXPECT_FALSE(T.isArch16Bit()); EXPECT_FALSE(T.isArch32Bit()); EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::amdil); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::amdil64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::hsail); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::hsail64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::spir); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::spir64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); } TEST(TripleTest, BitWidthArchVariants) { @@ -399,6 +459,30 @@ TEST(TripleTest, BitWidthArchVariants) { T.setArch(Triple::x86_64); EXPECT_EQ(Triple::x86, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::x86_64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::amdil); + EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::amdil64); + EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::hsail); + EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::hsail64); + EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::spir); + EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::spir64); + EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch()); } TEST(TripleTest, getOSVersion) { @@ -567,6 +651,10 @@ TEST(TripleTest, NormalizeWindows) { TEST(TripleTest, getARMCPUForArch) { { + llvm::Triple Triple("armv6-unknown-freebsd"); + EXPECT_STREQ("arm1176jzf-s", Triple.getARMCPUForArch()); + } + { llvm::Triple Triple("armv7s-apple-ios7"); EXPECT_STREQ("swift", Triple.getARMCPUForArch()); } diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index ac5e710..dba9d49 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -30,20 +30,16 @@ namespace { class IsPotentiallyReachableTest : public testing::Test { protected: void ParseAssembly(const char *Assembly) { - M.reset(new Module("Module", getGlobalContext())); - SMDiagnostic Error; - bool Parsed = ParseAssemblyString(Assembly, M.get(), - Error, M->getContext()) == M.get(); + M = parseAssemblyString(Assembly, Error, getGlobalContext()); std::string errMsg; raw_string_ostream os(errMsg); Error.print("", os); - if (!Parsed) { - // A failure here means that the test itself is buggy. + // A failure here means that the test itself is buggy. + if (!M) report_fatal_error(os.str().c_str()); - } Function *F = M->getFunction("test"); if (F == nullptr) diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index 8454860..baf0c28 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + IPA Analysis AsmParser Core @@ -6,6 +7,7 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_unittest(AnalysisTests + CallGraphTest.cpp CFGTest.cpp LazyCallGraphTest.cpp ScalarEvolutionTest.cpp diff --git a/unittests/Analysis/CallGraphTest.cpp b/unittests/Analysis/CallGraphTest.cpp new file mode 100644 index 0000000..777907a --- /dev/null +++ b/unittests/Analysis/CallGraphTest.cpp @@ -0,0 +1,59 @@ +//=======- CallGraphTest.cpp - Unit tests for the CG analysis -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +template void canSpecializeGraphTraitsIterators(Ty *G) { + typedef typename GraphTraits::NodeType NodeTy; + + auto I = GraphTraits::nodes_begin(G); + auto E = GraphTraits::nodes_end(G); + auto X = ++I; + + // Should be able to iterate over all nodes of the graph. + static_assert(std::is_same::value, + "Node type does not match"); + static_assert(std::is_same::value, + "Node type does not match"); + static_assert(std::is_same::value, + "Node type does not match"); + + NodeTy *N = GraphTraits::getEntryNode(G); + + auto S = GraphTraits::child_begin(N); + auto F = GraphTraits::child_end(N); + + // Should be able to iterate over immediate successors of a node. + static_assert(std::is_same::value, + "Node type does not match"); + static_assert(std::is_same::value, + "Node type does not match"); +} + +TEST(CallGraphTest, GraphTraitsSpecialization) { + Module M("", getGlobalContext()); + CallGraph CG(M); + + canSpecializeGraphTraitsIterators(&CG); +} + +TEST(CallGraphTest, GraphTraitsConstSpecialization) { + Module M("", getGlobalContext()); + CallGraph CG(M); + + canSpecializeGraphTraitsIterators(const_cast(&CG)); +} +} diff --git a/unittests/Analysis/LazyCallGraphTest.cpp b/unittests/Analysis/LazyCallGraphTest.cpp index 7eb87dc..6caccb8 100644 --- a/unittests/Analysis/LazyCallGraphTest.cpp +++ b/unittests/Analysis/LazyCallGraphTest.cpp @@ -22,18 +22,16 @@ using namespace llvm; namespace { std::unique_ptr parseAssembly(const char *Assembly) { - auto M = make_unique("Module", getGlobalContext()); - SMDiagnostic Error; - bool Parsed = - ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get(); + std::unique_ptr M = + parseAssemblyString(Assembly, Error, getGlobalContext()); std::string ErrMsg; raw_string_ostream OS(ErrMsg); Error.print("", OS); // A failure here means that the test itself is buggy. - if (!Parsed) + if (!M) report_fatal_error(OS.str().c_str()); return M; diff --git a/unittests/Analysis/Makefile b/unittests/Analysis/Makefile index 527f452..52296e7 100644 --- a/unittests/Analysis/Makefile +++ b/unittests/Analysis/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = Analysis -LINK_COMPONENTS := analysis asmparser +LINK_COMPONENTS := ipa analysis asmparser include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Analysis/MixedTBAATest.cpp b/unittests/Analysis/MixedTBAATest.cpp index 142e047..d7935e3 100644 --- a/unittests/Analysis/MixedTBAATest.cpp +++ b/unittests/Analysis/MixedTBAATest.cpp @@ -65,7 +65,7 @@ TEST_F(MixedTBAATest, MixedTBAA) { // Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA. // The order of the metadata (path-aware vs non-path-aware) is important, // because the AA eval pass only runs one test per store-pair. - const char* args[] = { "MixedTBAATest", "-evaluate-tbaa" }; + const char* args[] = { "MixedTBAATest", "-evaluate-aa-metadata" }; cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args); PM.add(createTypeBasedAliasAnalysisPass()); PM.add(createAAEvalPass()); diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index b6a3e9a..1f28ec6 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallString.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/IR/Constants.h" @@ -15,53 +16,152 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" -namespace llvm { -namespace { - -static Module *makeLLVMModule() { - Module* Mod = new Module("test-mem", getGlobalContext()); +using namespace llvm; - FunctionType* FuncTy = - FunctionType::get(Type::getVoidTy(Mod->getContext()), false); - Function* Func = Function::Create(FuncTy,GlobalValue::ExternalLinkage, - "func", Mod); +namespace { - BasicBlock* Entry = BasicBlock::Create(Mod->getContext(), "entry", Func); - new UnreachableInst(Mod->getContext(), Entry); +std::unique_ptr parseAssembly(const char *Assembly) { + SMDiagnostic Error; + std::unique_ptr M = + parseAssemblyString(Assembly, Error, getGlobalContext()); - BasicBlock* BB = BasicBlock::Create(Mod->getContext(), "bb", Func); - new UnreachableInst(Mod->getContext(), BB); + std::string ErrMsg; + raw_string_ostream OS(ErrMsg); + Error.print("", OS); - PointerType* Int8Ptr = Type::getInt8PtrTy(Mod->getContext()); - new GlobalVariable(*Mod, Int8Ptr, /*isConstant=*/true, - GlobalValue::ExternalLinkage, - BlockAddress::get(BB), "table"); + // A failure here means that the test itself is buggy. + if (!M) + report_fatal_error(OS.str().c_str()); - return Mod; + return M; } -static void writeModuleToBuffer(SmallVectorImpl &Buffer) { - std::unique_ptr Mod(makeLLVMModule()); +static void writeModuleToBuffer(std::unique_ptr Mod, + SmallVectorImpl &Buffer) { raw_svector_ostream OS(Buffer); WriteBitcodeToFile(Mod.get(), OS); } +static std::unique_ptr getLazyModuleFromAssembly(LLVMContext &Context, + SmallString<1024> &Mem, + const char *Assembly) { + writeModuleToBuffer(parseAssembly(Assembly), Mem); + std::unique_ptr Buffer = + MemoryBuffer::getMemBuffer(Mem.str(), "test", false); + ErrorOr ModuleOrErr = + getLazyBitcodeModule(std::move(Buffer), Context); + return std::unique_ptr(ModuleOrErr.get()); +} + +TEST(BitReaderTest, DematerializeFunctionPreservesLinkageType) { + SmallString<1024> Mem; + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "define internal i32 @func() {\n" + "ret i32 0\n" + "}\n"); + + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + M->getFunction("func")->materialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("func")->getLinkage() == + GlobalValue::InternalLinkage); + + // Check that the linkage type is preserved after dematerialization. + M->getFunction("func")->Dematerialize(); + EXPECT_TRUE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("func")->getLinkage() == + GlobalValue::InternalLinkage); + EXPECT_FALSE(verifyModule(*M, &dbgs())); +} + TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 SmallString<1024> Mem; - writeModuleToBuffer(Mem); - MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Mem.str(), "test", false); - ErrorOr ModuleOrErr = - getLazyBitcodeModule(Buffer, getGlobalContext()); - std::unique_ptr m(ModuleOrErr.get()); - PassManager passes; - passes.add(createVerifierPass()); - passes.add(createDebugInfoVerifierPass()); - passes.run(*m); + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" + "define void @func() {\n" + " unreachable\n" + "bb:\n" + " unreachable\n" + "}\n"); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Try (and fail) to dematerialize @func. + M->getFunction("func")->Dematerialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); } +TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { + SmallString<1024> Mem; + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "define i8* @before() {\n" + " ret i8* blockaddress(@func, %bb)\n" + "}\n" + "define void @other() {\n" + " unreachable\n" + "}\n" + "define void @func() {\n" + " unreachable\n" + "bb:\n" + " unreachable\n" + "}\n"); + EXPECT_TRUE(M->getFunction("before")->empty()); + EXPECT_TRUE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Materialize @before, pulling in @func. + EXPECT_FALSE(M->getFunction("before")->materialize()); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("other")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Try (and fail) to dematerialize @func. + M->getFunction("func")->Dematerialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); } + +TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { + SmallString<1024> Mem; + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "define void @func() {\n" + " unreachable\n" + "bb:\n" + " unreachable\n" + "}\n" + "define void @other() {\n" + " unreachable\n" + "}\n" + "define i8* @after() {\n" + " ret i8* blockaddress(@func, %bb)\n" + "}\n"); + EXPECT_TRUE(M->getFunction("after")->empty()); + EXPECT_TRUE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Materialize @after, pulling in @func. + EXPECT_FALSE(M->getFunction("after")->materialize()); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("other")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Try (and fail) to dematerialize @func. + M->getFunction("func")->Dematerialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); } + +} // end namespace diff --git a/unittests/Bitcode/BitstreamReaderTest.cpp b/unittests/Bitcode/BitstreamReaderTest.cpp new file mode 100644 index 0000000..b11d7fd --- /dev/null +++ b/unittests/Bitcode/BitstreamReaderTest.cpp @@ -0,0 +1,56 @@ +//===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/BitstreamReader.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(BitstreamReaderTest, AtEndOfStream) { + uint8_t Bytes[4] = { + 0x00, 0x01, 0x02, 0x03 + }; + BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamCursor Cursor(Reader); + + EXPECT_FALSE(Cursor.AtEndOfStream()); + (void)Cursor.Read(8); + EXPECT_FALSE(Cursor.AtEndOfStream()); + (void)Cursor.Read(24); + EXPECT_TRUE(Cursor.AtEndOfStream()); + + Cursor.JumpToBit(0); + EXPECT_FALSE(Cursor.AtEndOfStream()); + + Cursor.JumpToBit(32); + EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +TEST(BitstreamReaderTest, AtEndOfStreamJump) { + uint8_t Bytes[4] = { + 0x00, 0x01, 0x02, 0x03 + }; + BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamCursor Cursor(Reader); + + Cursor.JumpToBit(32); + EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +TEST(BitstreamReaderTest, AtEndOfStreamEmpty) { + uint8_t Dummy = 0xFF; + BitstreamReader Reader(&Dummy, &Dummy); + BitstreamCursor Cursor(Reader); + + EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +} // end anonymous namespace diff --git a/unittests/Bitcode/CMakeLists.txt b/unittests/Bitcode/CMakeLists.txt index 743ab18..09cbcdc 100644 --- a/unittests/Bitcode/CMakeLists.txt +++ b/unittests/Bitcode/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + AsmParser BitReader BitWriter Core @@ -7,4 +8,5 @@ set(LLVM_LINK_COMPONENTS add_llvm_unittest(BitcodeTests BitReaderTest.cpp + BitstreamReaderTest.cpp ) diff --git a/unittests/Bitcode/Makefile b/unittests/Bitcode/Makefile index fcec879..33b09b9 100644 --- a/unittests/Bitcode/Makefile +++ b/unittests/Bitcode/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = Bitcode -LINK_COMPONENTS := bitreader bitwriter +LINK_COMPONENTS := AsmParser BitReader BitWriter Core Support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 65930b5..19c2d24 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -4,7 +4,7 @@ set_target_properties(UnitTests PROPERTIES FOLDER "Tests") if (APPLE) set(CMAKE_INSTALL_RPATH "@executable_path/../../lib") else(UNIX) - set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../lib") + set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../lib${LLVM_LIBDIR_SUFFIX}") endif() function(add_llvm_unittest test_dirname) diff --git a/unittests/CodeGen/DIEHashTest.cpp b/unittests/CodeGen/DIEHashTest.cpp index 04c5a8a..efb0920 100644 --- a/unittests/CodeGen/DIEHashTest.cpp +++ b/unittests/CodeGen/DIEHashTest.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "../lib/CodeGen/AsmPrinter/DIE.h" +#include "llvm/CodeGen/DIE.h" #include "../lib/CodeGen/AsmPrinter/DIEHash.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" -#include "llvm/ADT/STLExtras.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt index 5e46222..783c9b5 100644 --- a/unittests/ExecutionEngine/CMakeLists.txt +++ b/unittests/ExecutionEngine/CMakeLists.txt @@ -10,10 +10,9 @@ add_llvm_unittest(ExecutionEngineTests ExecutionEngineTest.cpp ) -# Include JIT/MCJIT tests only if native arch is a built JIT target. +# Include MCJIT tests only if native arch is a built JIT target. list(FIND LLVM_TARGETS_TO_BUILD "${LLVM_NATIVE_ARCH}" build_idx) list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" jit_idx) if (NOT build_idx LESS 0 AND NOT jit_idx LESS 0) - add_subdirectory(JIT) add_subdirectory(MCJIT) endif() diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp index f23745c..19917a4 100644 --- a/unittests/ExecutionEngine/ExecutionEngineTest.cpp +++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp @@ -8,10 +8,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ManagedStatic.h" #include "gtest/gtest.h" using namespace llvm; @@ -19,10 +22,14 @@ using namespace llvm; namespace { class ExecutionEngineTest : public testing::Test { +private: + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + protected: - ExecutionEngineTest() - : M(new Module("
", getGlobalContext())), Error(""), - Engine(EngineBuilder(M).setErrorStr(&Error).create()) { + ExecutionEngineTest() { + auto Owner = make_unique("
", getGlobalContext()); + M = Owner.get(); + Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create()); } virtual void SetUp() { @@ -35,9 +42,9 @@ protected: GlobalValue::ExternalLinkage, nullptr, Name); } - Module *const M; std::string Error; - const std::unique_ptr Engine; + Module *M; // Owned by ExecutionEngine. + std::unique_ptr Engine; }; TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { @@ -127,4 +134,35 @@ TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) { EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); } +TEST_F(ExecutionEngineTest, LookupWithMangledName) { + int x; + llvm::sys::DynamicLibrary::AddSymbol("x", &x); + + // Demonstrate that getSymbolAddress accepts mangled names and always strips + // the leading underscore. + EXPECT_EQ(reinterpret_cast(&x), + RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + +TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) { + int x; + int _x; + llvm::sys::DynamicLibrary::AddSymbol("x", &x); + llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); + + // Lookup the demangled name first, even if there's a demangled symbol that + // matches the input already. + EXPECT_EQ(reinterpret_cast(&x), + RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + +TEST_F(ExecutionEngineTest, LookupwithDemangledName) { + int _x; + llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); + + // But do fallback to looking up a demangled name if there's no ambiguity + EXPECT_EQ(reinterpret_cast(&_x), + RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + } diff --git a/unittests/ExecutionEngine/JIT/CMakeLists.txt b/unittests/ExecutionEngine/JIT/CMakeLists.txt deleted file mode 100644 index 5ace1c6..0000000 --- a/unittests/ExecutionEngine/JIT/CMakeLists.txt +++ /dev/null @@ -1,65 +0,0 @@ -set(LLVM_LINK_COMPONENTS - AsmParser - BitReader - BitWriter - Core - ExecutionEngine - JIT - MC - Support - nativecodegen - ) - -# HACK: Declare a couple of source files as optionally compiled to satisfy the -# missing-file-checker in LLVM's weird CMake build. -set(LLVM_OPTIONAL_SOURCES - IntelJITEventListenerTest.cpp - OProfileJITEventListenerTest.cpp - ) - -if( LLVM_USE_INTEL_JITEVENTS ) - set(ProfileTestSources - IntelJITEventListenerTest.cpp - ) - set(LLVM_LINK_COMPONENTS - ${LLVM_LINK_COMPONENTS} - DebugInfo - IntelJITEvents - Object - ) -endif( LLVM_USE_INTEL_JITEVENTS ) - -if( LLVM_USE_OPROFILE ) - set(ProfileTestSources - ${ProfileTestSources} - OProfileJITEventListenerTest.cpp - ) - set(LLVM_LINK_COMPONENTS - ${LLVM_LINK_COMPONENTS} - OProfileJIT - ) -endif( LLVM_USE_OPROFILE ) - -set(JITTestsSources - JITEventListenerTest.cpp - JITMemoryManagerTest.cpp - JITTest.cpp - MultiJITTest.cpp - ${ProfileTestSources} - ) - -if(MSVC) - list(APPEND JITTestsSources JITTests.def) -endif() - -# The JIT tests need to dlopen things. -set(LLVM_NO_DEAD_STRIP 1) - -add_llvm_unittest(JITTests - ${JITTestsSources} - ) - -if(MINGW OR CYGWIN) - set_property(TARGET JITTests PROPERTY LINK_FLAGS -Wl,--export-all-symbols) -endif() -set_target_properties(JITTests PROPERTIES ENABLE_EXPORTS 1) diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp deleted file mode 100644 index db90887..0000000 --- a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//===- JITEventListenerTest.cpp - Tests for Intel JITEventListener --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "JITEventListenerTestCommon.h" - -using namespace llvm; - -// Because we want to keep the implementation details of the Intel API used to -// communicate with Amplifier out of the public header files, the header below -// is included from the source tree instead. -#include "../../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h" - -#include -#include - -namespace { - -// map of function ("method") IDs to source locations -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of Intel JIT API jitprofiling library -namespace test_jitprofiling { - -int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { - switch (EventType) { - case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { - EXPECT_TRUE(0 != EventSpecificData); - iJIT_Method_Load* msg = static_cast(EventSpecificData); - - ReportedDebugFuncs[msg->method_id]; - - for(unsigned int i = 0; i < msg->line_number_size; ++i) { - EXPECT_TRUE(0 != msg->line_number_table); - std::pair loc( - std::string(msg->source_file_name), - msg->line_number_table[i].LineNumber); - ReportedDebugFuncs[msg->method_id].push_back(loc); - } - } - break; - case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { - EXPECT_TRUE(0 != EventSpecificData); - unsigned int UnloadId - = *reinterpret_cast(EventSpecificData); - EXPECT_TRUE(1 == ReportedDebugFuncs.erase(UnloadId)); - } - default: - break; - } - return 0; -} - -iJIT_IsProfilingActiveFlags IsProfilingActive(void) { - // for testing, pretend we have an Intel Parallel Amplifier XE 2011 - // instance attached - return iJIT_SAMPLING_ON; -} - -unsigned int GetNewMethodID(void) { - static unsigned int id = 0; - return ++id; -} - -} //namespace test_jitprofiling - -class IntelJITEventListenerTest - : public JITEventListenerTestBase { -public: - IntelJITEventListenerTest() - : JITEventListenerTestBase( - new IntelJITEventsWrapper(test_jitprofiling::NotifyEvent, 0, - test_jitprofiling::IsProfilingActive, 0, 0, - test_jitprofiling::GetNewMethodID)) - { - EXPECT_TRUE(0 != MockWrapper); - - Listener.reset(JITEventListener::createIntelJITEventListener( - MockWrapper.release())); - EXPECT_TRUE(0 != Listener); - EE->RegisterJITEventListener(Listener.get()); - } -}; - -TEST_F(IntelJITEventListenerTest, NoDebugInfo) { - TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, SingleLine) { - TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, MultipleLines) { - TestMultipleLines(ReportedDebugFuncs); -} - -// This testcase is disabled because the Intel JIT API does not support a single -// JITted function with source lines associated with multiple files -/* -TEST_F(IntelJITEventListenerTest, MultipleFiles) { - TestMultipleFiles(ReportedDebugFuncs); -} -*/ - -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp deleted file mode 100644 index 175b9fb..0000000 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ /dev/null @@ -1,237 +0,0 @@ -//===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -namespace { - -struct FunctionEmittedEvent { - // Indices are local to the RecordingJITEventListener, since the - // JITEventListener interface makes no guarantees about the order of - // calls between Listeners. - unsigned Index; - const Function *F; - void *Code; - size_t Size; - JITEvent_EmittedFunctionDetails Details; -}; -struct FunctionFreedEvent { - unsigned Index; - void *Code; -}; - -struct RecordingJITEventListener : public JITEventListener { - std::vector EmittedEvents; - std::vector FreedEvents; - - unsigned NextIndex; - - RecordingJITEventListener() : NextIndex(0) {} - - virtual void NotifyFunctionEmitted(const Function &F, - void *Code, size_t Size, - const EmittedFunctionDetails &Details) { - FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details}; - EmittedEvents.push_back(Event); - } - - virtual void NotifyFreeingMachineCode(void *OldPtr) { - FunctionFreedEvent Event = {NextIndex++, OldPtr}; - FreedEvents.push_back(Event); - } -}; - -class JITEventListenerTest : public testing::Test { - protected: - JITEventListenerTest() - : M(new Module("module", getGlobalContext())), - EE(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .create()) { - } - - Module *M; - const std::unique_ptr EE; -}; - -// Tests on SystemZ disabled as we're running the old JIT -#if !defined(__s390__) && !defined(__aarch64__) -Function *buildFunction(Module *M) { - Function *Result = Function::Create( - TypeBuilder::get(getGlobalContext()), - GlobalValue::ExternalLinkage, "id", M); - Value *Arg = Result->arg_begin(); - BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); - ReturnInst::Create(M->getContext(), Arg, BB); - return Result; -} - -// Tests that a single JITEventListener follows JIT events accurately. -TEST_F(JITEventListenerTest, Simple) { - RecordingJITEventListener Listener; - EE->RegisterJITEventListener(&Listener); - Function *F1 = buildFunction(M); - Function *F2 = buildFunction(M); - - void *F1_addr = EE->getPointerToFunction(F1); - void *F2_addr = EE->getPointerToFunction(F2); - EE->getPointerToFunction(F1); // Should do nothing. - EE->freeMachineCodeForFunction(F1); - EE->freeMachineCodeForFunction(F2); - - ASSERT_EQ(2U, Listener.EmittedEvents.size()); - ASSERT_EQ(2U, Listener.FreedEvents.size()); - - EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); - EXPECT_EQ(F1, Listener.EmittedEvents[0].F); - EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener.EmittedEvents[1].Index); - EXPECT_EQ(F2, Listener.EmittedEvents[1].F); - EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code); - EXPECT_LT(0U, Listener.EmittedEvents[1].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(2U, Listener.FreedEvents[0].Index); - EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code); - - EXPECT_EQ(3U, Listener.FreedEvents[1].Index); - EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code); - - F1->eraseFromParent(); - F2->eraseFromParent(); -} - -// Tests that a single JITEventListener follows JIT events accurately. -TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) { - RecordingJITEventListener Listener1; - RecordingJITEventListener Listener2; - RecordingJITEventListener Listener3; - Function *F1 = buildFunction(M); - Function *F2 = buildFunction(M); - - EE->RegisterJITEventListener(&Listener1); - EE->RegisterJITEventListener(&Listener2); - void *F1_addr = EE->getPointerToFunction(F1); - EE->RegisterJITEventListener(&Listener3); - EE->UnregisterJITEventListener(&Listener1); - void *F2_addr = EE->getPointerToFunction(F2); - EE->UnregisterJITEventListener(&Listener2); - EE->UnregisterJITEventListener(&Listener3); - EE->freeMachineCodeForFunction(F1); - EE->RegisterJITEventListener(&Listener2); - EE->RegisterJITEventListener(&Listener3); - EE->RegisterJITEventListener(&Listener1); - EE->freeMachineCodeForFunction(F2); - EE->UnregisterJITEventListener(&Listener1); - EE->UnregisterJITEventListener(&Listener2); - EE->UnregisterJITEventListener(&Listener3); - - // Listener 1. - ASSERT_EQ(1U, Listener1.EmittedEvents.size()); - ASSERT_EQ(1U, Listener1.FreedEvents.size()); - - EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index); - EXPECT_EQ(F1, Listener1.EmittedEvents[0].F); - EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener1.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener1.FreedEvents[0].Index); - EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code); - - // Listener 2. - ASSERT_EQ(2U, Listener2.EmittedEvents.size()); - ASSERT_EQ(1U, Listener2.FreedEvents.size()); - - EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index); - EXPECT_EQ(F1, Listener2.EmittedEvents[0].F); - EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener2.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index); - EXPECT_EQ(F2, Listener2.EmittedEvents[1].F); - EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code); - EXPECT_LT(0U, Listener2.EmittedEvents[1].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(2U, Listener2.FreedEvents[0].Index); - EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code); - - // Listener 3. - ASSERT_EQ(1U, Listener3.EmittedEvents.size()); - ASSERT_EQ(1U, Listener3.FreedEvents.size()); - - EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index); - EXPECT_EQ(F2, Listener3.EmittedEvents[0].F); - EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener3.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener3.FreedEvents[0].Index); - EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code); - - F1->eraseFromParent(); - F2->eraseFromParent(); -} - -TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) { - RecordingJITEventListener Listener; - MachineCodeInfo MCI; - Function *F = buildFunction(M); - - EE->RegisterJITEventListener(&Listener); - EE->runJITOnFunction(F, &MCI); - void *F_addr = EE->getPointerToFunction(F); - EE->freeMachineCodeForFunction(F); - - ASSERT_EQ(1U, Listener.EmittedEvents.size()); - ASSERT_EQ(1U, Listener.FreedEvents.size()); - - EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); - EXPECT_EQ(F, Listener.EmittedEvents[0].F); - EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code); - EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code); - EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size); - - EXPECT_EQ(1U, Listener.FreedEvents[0].Index); - EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code); -} -#endif - -class JITEnvironment : public testing::Environment { - virtual void SetUp() { - // Required to create a JIT. - InitializeNativeTarget(); - } -}; -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); - -} // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h deleted file mode 100644 index 61220f5..0000000 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h +++ /dev/null @@ -1,207 +0,0 @@ -//===- JITEventListenerTestCommon.h - Helper for JITEventListener tests ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===-------------------------------------------------------------------------------===// - -#ifndef JIT_EVENT_LISTENER_TEST_COMMON_H -#define JIT_EVENT_LISTENER_TEST_COMMON_H - -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/Config/config.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include -#include -#include - -typedef std::vector > SourceLocations; -typedef std::map NativeCodeMap; - -class JITEnvironment : public testing::Environment { - virtual void SetUp() { - // Required to create a JIT. - llvm::InitializeNativeTarget(); - } -}; - -inline unsigned int getLine() { - return 12; -} - -inline unsigned int getCol() { - return 0; -} - -inline const char* getFilename() { - return "mock_source_file.cpp"; -} - -// Test fixture shared by tests for listener implementations -template -class JITEventListenerTestBase : public testing::Test { -protected: - std::unique_ptr MockWrapper; - std::unique_ptr Listener; - -public: - llvm::Module* M; - llvm::MDNode* Scope; - llvm::ExecutionEngine* EE; - llvm::DIBuilder* DebugBuilder; - llvm::IRBuilder<> Builder; - - JITEventListenerTestBase(WrapperT* w) - : MockWrapper(w) - , M(new llvm::Module("module", llvm::getGlobalContext())) - , EE(llvm::EngineBuilder(M) - .setEngineKind(llvm::EngineKind::JIT) - .setOptLevel(llvm::CodeGenOpt::None) - .create()) - , DebugBuilder(new llvm::DIBuilder(*M)) - , Builder(llvm::getGlobalContext()) - { - DebugBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus, - "JIT", - "JIT", - "JIT", - true, - "", - 1); - - Scope = DebugBuilder->createFile(getFilename(), "."); - } - - llvm::Function *buildFunction(const SourceLocations& DebugLocations) { - using namespace llvm; - - LLVMContext& GlobalContext = getGlobalContext(); - - SourceLocations::const_iterator CurrentDebugLocation - = DebugLocations.begin(); - - if (CurrentDebugLocation != DebugLocations.end()) { - DebugLoc DebugLocation = DebugLoc::get(getLine(), getCol(), - DebugBuilder->createFile(CurrentDebugLocation->first, ".")); - Builder.SetCurrentDebugLocation(DebugLocation); - CurrentDebugLocation++; - } - - Function *Result = Function::Create( - TypeBuilder::get(GlobalContext), - GlobalValue::ExternalLinkage, "id", M); - Value *Arg = Result->arg_begin(); - BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); - Builder.SetInsertPoint(BB); - Value* one = ConstantInt::get(GlobalContext, APInt(32, 1)); - for(; CurrentDebugLocation != DebugLocations.end(); - ++CurrentDebugLocation) { - Arg = Builder.CreateMul(Arg, Builder.CreateAdd(Arg, one)); - Builder.SetCurrentDebugLocation( - DebugLoc::get(CurrentDebugLocation->second, 0, - DebugBuilder->createFile(CurrentDebugLocation->first, "."))); - } - Builder.CreateRet(Arg); - return Result; - } - - void TestNoDebugInfo(NativeCodeMap& ReportedDebugFuncs) { - SourceLocations DebugLocations; - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - //Cause JITting and callbacks to our listener - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestSingleLine(NativeCodeMap& ReportedDebugFuncs) { - SourceLocations DebugLocations; - DebugLocations.push_back(std::make_pair(std::string(getFilename()), - getLine())); - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - EXPECT_STREQ(ReportedDebugFuncs.begin()->second.begin()->first.c_str(), - getFilename()); - EXPECT_EQ(ReportedDebugFuncs.begin()->second.begin()->second, getLine()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestMultipleLines(NativeCodeMap& ReportedDebugFuncs) { - using namespace std; - - SourceLocations DebugLocations; - unsigned int c = 5; - for(unsigned int i = 0; i < c; ++i) { - DebugLocations.push_back(make_pair(string(getFilename()), getLine() + i)); - } - - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; - EXPECT_EQ(c, FunctionInfo.size()); - - int VerifyCount = 0; - for(SourceLocations::iterator i = FunctionInfo.begin(); - i != FunctionInfo.end(); - ++i) { - EXPECT_STREQ(i->first.c_str(), getFilename()); - EXPECT_EQ(i->second, getLine() + VerifyCount); - VerifyCount++; - } - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestMultipleFiles(NativeCodeMap& ReportedDebugFuncs) { - - std::string secondFilename("another_file.cpp"); - - SourceLocations DebugLocations; - DebugLocations.push_back(std::make_pair(std::string(getFilename()), - getLine())); - DebugLocations.push_back(std::make_pair(secondFilename, getLine())); - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; - EXPECT_TRUE(2 == FunctionInfo.size()); - - EXPECT_STREQ(FunctionInfo.at(0).first.c_str(), getFilename()); - EXPECT_STREQ(FunctionInfo.at(1).first.c_str(), secondFilename.c_str()); - - EXPECT_EQ(FunctionInfo.at(0).second, getLine()); - EXPECT_EQ(FunctionInfo.at(1).second, getLine()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } -}; - -#endif //JIT_EVENT_LISTENER_TEST_COMMON_H diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp deleted file mode 100644 index 296838d..0000000 --- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +++ /dev/null @@ -1,302 +0,0 @@ -//===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/LLVMContext.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -Function *makeFakeFunction() { - std::vector params; - FunctionType *FTy = - FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false); - return Function::Create(FTy, GlobalValue::ExternalLinkage); -} - -// Allocate three simple functions that fit in the initial slab. This exercises -// the code in the case that we don't have to allocate more memory to store the -// function bodies. -TEST(JITMemoryManagerTest, NoAllocations) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uintptr_t size; - std::string Error; - - // Allocate the functions. - std::unique_ptr F1(makeFakeFunction()); - size = 1024; - uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); - memset(FunctionBody1, 0xFF, 1024); - MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F2(makeFakeFunction()); - size = 1024; - uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); - memset(FunctionBody2, 0xFF, 1024); - MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F3(makeFakeFunction()); - size = 1024; - uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); - memset(FunctionBody3, 0xFF, 1024); - MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Deallocate them out of order, in case that matters. - MemMgr->deallocateFunctionBody(FunctionBody2); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody1); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody3); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Make three large functions that take up most of the space in the slab. Then -// try allocating three smaller functions that don't require additional slabs. -TEST(JITMemoryManagerTest, TestCodeAllocation) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uintptr_t size; - std::string Error; - - // Big functions are a little less than the largest block size. - const uintptr_t smallFuncSize = 1024; - const uintptr_t bigFuncSize = (MemMgr->GetDefaultCodeSlabSize() - - smallFuncSize * 2); - - // Allocate big functions - std::unique_ptr F1(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody1, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F2(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody2, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F3(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody3, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Check that each large function took it's own slab. - EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - - // Allocate small functions - std::unique_ptr F4(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody4, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F4.get(), FunctionBody4, - FunctionBody4 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F5(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody5, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F5.get(), FunctionBody5, - FunctionBody5 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F6(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody6, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F6.get(), FunctionBody6, - FunctionBody6 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Check that the small functions didn't allocate any new slabs. - EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - - // Deallocate them out of order, in case that matters. - MemMgr->deallocateFunctionBody(FunctionBody2); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody1); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody4); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody3); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody5); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody6); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Allocate five global ints of varying widths and alignment, and check their -// alignment and overlap. -TEST(JITMemoryManagerTest, TestSmallGlobalInts) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uint8_t *a = (uint8_t *)MemMgr->allocateGlobal(8, 0); - uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2); - uint32_t *c = (uint32_t*)MemMgr->allocateGlobal(32, 4); - uint64_t *d = (uint64_t*)MemMgr->allocateGlobal(64, 8); - - // Check the alignment. - EXPECT_EQ(0U, ((uintptr_t)b) & 0x1); - EXPECT_EQ(0U, ((uintptr_t)c) & 0x3); - EXPECT_EQ(0U, ((uintptr_t)d) & 0x7); - - // Initialize them each one at a time and make sure they don't overlap. - *a = 0xff; - *b = 0U; - *c = 0U; - *d = 0U; - EXPECT_EQ(0xffU, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0U, *d); - *a = 0U; - *b = 0xffffU; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0xffffU, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0U, *d); - *b = 0U; - *c = 0xffffffffU; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0xffffffffU, *c); - EXPECT_EQ(0U, *d); - *c = 0U; - *d = 0xffffffffffffffffULL; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0xffffffffffffffffULL, *d); - - // Make sure we didn't allocate any extra slabs for this tiny amount of data. - EXPECT_EQ(1U, MemMgr->GetNumDataSlabs()); -} - -// Allocate a small global, a big global, and a third global, and make sure we -// only use two slabs for that. -TEST(JITMemoryManagerTest, TestLargeGlobalArray) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t Size = 4 * MemMgr->GetDefaultDataSlabSize(); - uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8); - uint8_t *g = MemMgr->allocateGlobal(Size, 8); - uint64_t *b = (uint64_t*)MemMgr->allocateGlobal(64, 8); - - // Check the alignment. - EXPECT_EQ(0U, ((uintptr_t)a) & 0x7); - EXPECT_EQ(0U, ((uintptr_t)g) & 0x7); - EXPECT_EQ(0U, ((uintptr_t)b) & 0x7); - - // Initialize them to make sure we don't segfault and make sure they don't - // overlap. - memset(a, 0x1, 8); - memset(g, 0x2, Size); - memset(b, 0x3, 8); - EXPECT_EQ(0x0101010101010101ULL, *a); - // Just check the edges. - EXPECT_EQ(0x02U, g[0]); - EXPECT_EQ(0x02U, g[Size - 1]); - EXPECT_EQ(0x0303030303030303ULL, *b); - - // Check the number of slabs. - EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of medium globals so that we can test moving the bump allocator -// to a new slab. -TEST(JITMemoryManagerTest, TestManyGlobals) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); - size_t Size = 128; - int Iters = (SlabSize / Size) + 1; - - // We should start with no slabs. - EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - - // After allocating a bunch of globals, we should have two. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateGlobal(Size, 8); - EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); - - // And after much more, we should have three. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateGlobal(Size, 8); - EXPECT_EQ(3U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of function stubs so that we can test moving the stub bump -// allocator to a new slab. -TEST(JITMemoryManagerTest, TestManyStubs) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); - size_t Size = 128; - int Iters = (SlabSize / Size) + 1; - - // We should start with no slabs. - EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - - // After allocating a bunch of stubs, we should have two. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(nullptr, Size, 8); - EXPECT_EQ(2U, MemMgr->GetNumStubSlabs()); - - // And after much more, we should have three. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(nullptr, Size, 8); - EXPECT_EQ(3U, MemMgr->GetNumStubSlabs()); -} - -// Check section allocation and alignment -TEST(JITMemoryManagerTest, AllocateSection) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, StringRef()); - uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, StringRef(), true); - uint8_t *code2 = MemMgr->allocateCodeSection(257, 32, 3, StringRef()); - uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, StringRef(), false); - uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5, StringRef()); - - EXPECT_NE((uint8_t*)nullptr, code1); - EXPECT_NE((uint8_t*)nullptr, code2); - EXPECT_NE((uint8_t*)nullptr, data1); - EXPECT_NE((uint8_t*)nullptr, data2); - - // Check alignment - EXPECT_EQ((uint64_t)code1 & 0xf, 0u); - EXPECT_EQ((uint64_t)code2 & 0x1f, 0u); - EXPECT_EQ((uint64_t)code3 & 0x3f, 0u); - EXPECT_EQ((uint64_t)data1 & 0xf, 0u); - EXPECT_EQ((uint64_t)data2 & 0x3f, 0u); -} - -} diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp deleted file mode 100644 index 817d207..0000000 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ /dev/null @@ -1,728 +0,0 @@ -//===- JITTest.cpp - Unit tests for the JIT -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -// This variable is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition. Note that this variable must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyGlobal; -int32_t JITTest_AvailableExternallyGlobal LLVM_ATTRIBUTE_USED = 42; - -// This function is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition. Note that this function must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyFunction() LLVM_ATTRIBUTE_USED; -extern "C" int32_t JITTest_AvailableExternallyFunction() { - return 42; -} - -namespace { - -// Tests on ARM, PowerPC and SystemZ disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ - && !defined(__aarch64__) - -Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { - std::vector params; - FunctionType *FTy = FunctionType::get(G->getType()->getElementType(), - params, false); - Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M); - BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F); - IRBuilder<> builder(Entry); - Value *Load = builder.CreateLoad(G); - Type *GTy = G->getType()->getElementType(); - Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL)); - builder.CreateStore(Add, G); - builder.CreateRet(Add); - return F; -} - -std::string DumpFunction(const Function *F) { - std::string Result; - raw_string_ostream(Result) << "" << *F; - return Result; -} - -class RecordingJITMemoryManager : public JITMemoryManager { - const std::unique_ptr Base; - -public: - RecordingJITMemoryManager() - : Base(JITMemoryManager::CreateDefaultMemManager()) { - stubsAllocated = 0; - } - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - return Base->getPointerToNamedFunction(Name, AbortOnFailure); - } - - virtual void setMemoryWritable() { Base->setMemoryWritable(); } - virtual void setMemoryExecutable() { Base->setMemoryExecutable(); } - virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); } - virtual void AllocateGOT() { Base->AllocateGOT(); } - virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); } - struct StartFunctionBodyCall { - StartFunctionBodyCall(uint8_t *Result, const Function *F, - uintptr_t ActualSize, uintptr_t ActualSizeResult) - : Result(Result), F(F), F_dump(DumpFunction(F)), - ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {} - uint8_t *Result; - const Function *F; - std::string F_dump; - uintptr_t ActualSize; - uintptr_t ActualSizeResult; - }; - std::vector startFunctionBodyCalls; - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize) { - uintptr_t InitialActualSize = ActualSize; - uint8_t *Result = Base->startFunctionBody(F, ActualSize); - startFunctionBodyCalls.push_back( - StartFunctionBodyCall(Result, F, InitialActualSize, ActualSize)); - return Result; - } - int stubsAllocated; - uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, - unsigned Alignment) override { - stubsAllocated++; - return Base->allocateStub(F, StubSize, Alignment); - } - struct EndFunctionBodyCall { - EndFunctionBodyCall(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) - : F(F), F_dump(DumpFunction(F)), - FunctionStart(FunctionStart), FunctionEnd(FunctionEnd) {} - const Function *F; - std::string F_dump; - uint8_t *FunctionStart; - uint8_t *FunctionEnd; - }; - std::vector endFunctionBodyCalls; - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - endFunctionBodyCalls.push_back( - EndFunctionBodyCall(F, FunctionStart, FunctionEnd)); - Base->endFunctionBody(F, FunctionStart, FunctionEnd); - } - virtual uint8_t *allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName, bool IsReadOnly) { - return Base->allocateDataSection( - Size, Alignment, SectionID, SectionName, IsReadOnly); - } - virtual uint8_t *allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName) { - return Base->allocateCodeSection( - Size, Alignment, SectionID, SectionName); - } - virtual bool finalizeMemory(std::string *ErrMsg) { return false; } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - return Base->allocateSpace(Size, Alignment); - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - return Base->allocateGlobal(Size, Alignment); - } - struct DeallocateFunctionBodyCall { - DeallocateFunctionBodyCall(const void *Body) : Body(Body) {} - const void *Body; - }; - std::vector deallocateFunctionBodyCalls; - virtual void deallocateFunctionBody(void *Body) { - deallocateFunctionBodyCalls.push_back(DeallocateFunctionBodyCall(Body)); - Base->deallocateFunctionBody(Body); - } -}; - -bool LoadAssemblyInto(Module *M, const char *assembly) { - SMDiagnostic Error; - bool success = - nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); - std::string errMsg; - raw_string_ostream os(errMsg); - Error.print("", os); - EXPECT_TRUE(success) << os.str(); - return success; -} - -class JITTest : public testing::Test { - protected: - virtual RecordingJITMemoryManager *createMemoryManager() { - return new RecordingJITMemoryManager; - } - - virtual void SetUp() { - M = new Module("
", Context); - RJMM = createMemoryManager(); - RJMM->setPoisonMemory(true); - std::string Error; - TargetOptions Options; - TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT) - .setJITMemoryManager(RJMM) - .setErrorStr(&Error) - .setTargetOptions(Options).create()); - ASSERT_TRUE(TheJIT.get() != nullptr) << Error; - } - - void LoadAssembly(const char *assembly) { - LoadAssemblyInto(M, assembly); - } - - LLVMContext Context; - Module *M; // Owned by ExecutionEngine. - RecordingJITMemoryManager *RJMM; - std::unique_ptr TheJIT; -}; - -// Regression test for a bug. The JIT used to allocate globals inside the same -// memory block used for the function, and when the function code was freed, -// the global was left in the same place. This test allocates a function -// that uses and global, deallocates it, and then makes sure that the global -// stays alive after that. -TEST(JIT, GlobalInFunction) { - LLVMContext context; - Module *M = new Module("
", context); - - JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager(); - // Tell the memory manager to poison freed memory so that accessing freed - // memory is more easily tested. - MemMgr->setPoisonMemory(true); - std::string Error; - std::unique_ptr JIT(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setJITMemoryManager(MemMgr) - // The next line enables the fix: - .setAllocateGVsWithCode(false) - .create()); - ASSERT_EQ(Error, ""); - - // Create a global variable. - Type *GTy = Type::getInt32Ty(context); - GlobalVariable *G = new GlobalVariable( - *M, - GTy, - false, // Not constant. - GlobalValue::InternalLinkage, - Constant::getNullValue(GTy), - "myglobal"); - - // Make a function that points to a global. - Function *F1 = makeReturnGlobal("F1", G, M); - - // Get the pointer to the native code to force it to JIT the function and - // allocate space for the global. - void (*F1Ptr)() = - reinterpret_cast((intptr_t)JIT->getPointerToFunction(F1)); - - // Since F1 was codegen'd, a pointer to G should be available. - int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G); - ASSERT_NE((int32_t*)nullptr, GPtr); - EXPECT_EQ(0, *GPtr); - - // F1() should increment G. - F1Ptr(); - EXPECT_EQ(1, *GPtr); - - // Make a second function identical to the first, referring to the same - // global. - Function *F2 = makeReturnGlobal("F2", G, M); - void (*F2Ptr)() = - reinterpret_cast((intptr_t)JIT->getPointerToFunction(F2)); - - // F2() should increment G. - F2Ptr(); - EXPECT_EQ(2, *GPtr); - - // Deallocate F1. - JIT->freeMachineCodeForFunction(F1); - - // F2() should *still* increment G. - F2Ptr(); - EXPECT_EQ(3, *GPtr); -} - -int PlusOne(int arg) { - return arg + 1; -} - -TEST_F(JITTest, FarCallToKnownFunction) { - // x86-64 can only make direct calls to functions within 32 bits of - // the current PC. To call anything farther away, we have to load - // the address into a register and call through the register. The - // current JIT does this by allocating a stub for any far call. - // There was a bug in which the JIT tried to emit a direct call when - // the target was already in the JIT's global mappings and lazy - // compilation was disabled. - - Function *KnownFunction = Function::Create( - TypeBuilder::get(Context), - GlobalValue::ExternalLinkage, "known", M); - TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne); - - // int test() { return known(7); } - Function *TestFunction = Function::Create( - TypeBuilder::get(Context), - GlobalValue::ExternalLinkage, "test", M); - BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction); - IRBuilder<> Builder(Entry); - Value *result = Builder.CreateCall( - KnownFunction, - ConstantInt::get(TypeBuilder::get(Context), 7)); - Builder.CreateRet(result); - - TheJIT->DisableLazyCompilation(true); - int (*TestFunctionPtr)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(TestFunction)); - // This used to crash in trying to call PlusOne(). - EXPECT_EQ(8, TestFunctionPtr()); -} - -// Test a function C which calls A and B which call each other. -TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) { - TheJIT->DisableLazyCompilation(true); - - FunctionType *Func1Ty = - cast(TypeBuilder::get(Context)); - std::vector arg_types; - arg_types.push_back(Type::getInt1Ty(Context)); - FunctionType *FuncTy = FunctionType::get( - Type::getVoidTy(Context), arg_types, false); - Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage, - "func1", M); - Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, - "func2", M); - Function *Func3 = Function::Create(FuncTy, Function::InternalLinkage, - "func3", M); - BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); - BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); - BasicBlock *True2 = BasicBlock::Create(Context, "cond_true", Func2); - BasicBlock *False2 = BasicBlock::Create(Context, "cond_false", Func2); - BasicBlock *Block3 = BasicBlock::Create(Context, "block3", Func3); - BasicBlock *True3 = BasicBlock::Create(Context, "cond_true", Func3); - BasicBlock *False3 = BasicBlock::Create(Context, "cond_false", Func3); - - // Make Func1 call Func2(0) and Func3(0). - IRBuilder<> Builder(Block1); - Builder.CreateCall(Func2, ConstantInt::getTrue(Context)); - Builder.CreateCall(Func3, ConstantInt::getTrue(Context)); - Builder.CreateRetVoid(); - - // void Func2(bool b) { if (b) { Func3(false); return; } return; } - Builder.SetInsertPoint(Block2); - Builder.CreateCondBr(Func2->arg_begin(), True2, False2); - Builder.SetInsertPoint(True2); - Builder.CreateCall(Func3, ConstantInt::getFalse(Context)); - Builder.CreateRetVoid(); - Builder.SetInsertPoint(False2); - Builder.CreateRetVoid(); - - // void Func3(bool b) { if (b) { Func2(false); return; } return; } - Builder.SetInsertPoint(Block3); - Builder.CreateCondBr(Func3->arg_begin(), True3, False3); - Builder.SetInsertPoint(True3); - Builder.CreateCall(Func2, ConstantInt::getFalse(Context)); - Builder.CreateRetVoid(); - Builder.SetInsertPoint(False3); - Builder.CreateRetVoid(); - - // Compile the function to native code - void (*F1Ptr)() = - reinterpret_cast((intptr_t)TheJIT->getPointerToFunction(Func1)); - - F1Ptr(); -} - -// Regression test for PR5162. This used to trigger an AssertingVH inside the -// JIT's Function to stub mapping. -TEST_F(JITTest, NonLazyLeaksNoStubs) { - TheJIT->DisableLazyCompilation(true); - - // Create two functions with a single basic block each. - FunctionType *FuncTy = - cast(TypeBuilder::get(Context)); - Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage, - "func1", M); - Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, - "func2", M); - BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); - BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); - - // The first function calls the second and returns the result - IRBuilder<> Builder(Block1); - Value *Result = Builder.CreateCall(Func2); - Builder.CreateRet(Result); - - // The second function just returns a constant - Builder.SetInsertPoint(Block2); - Builder.CreateRet(ConstantInt::get(TypeBuilder::get(Context),42)); - - // Compile the function to native code - (void)TheJIT->getPointerToFunction(Func1); - - // Free the JIT state for the functions - TheJIT->freeMachineCodeForFunction(Func1); - TheJIT->freeMachineCodeForFunction(Func2); - - // Delete the first function (and show that is has no users) - EXPECT_EQ(Func1->getNumUses(), 0u); - Func1->eraseFromParent(); - - // Delete the second function (and show that it has no users - it had one, - // func1 but that's gone now) - EXPECT_EQ(Func2->getNumUses(), 0u); - Func2->eraseFromParent(); -} - -TEST_F(JITTest, ModuleDeletion) { - TheJIT->DisableLazyCompilation(false); - LoadAssembly("define void @main() { " - " call i32 @computeVal() " - " ret void " - "} " - " " - "define internal i32 @computeVal() { " - " ret i32 0 " - "} "); - Function *func = M->getFunction("main"); - TheJIT->getPointerToFunction(func); - TheJIT->removeModule(M); - delete M; - - SmallPtrSet FunctionsDeallocated; - for (unsigned i = 0, e = RJMM->deallocateFunctionBodyCalls.size(); - i != e; ++i) { - FunctionsDeallocated.insert(RJMM->deallocateFunctionBodyCalls[i].Body); - } - for (unsigned i = 0, e = RJMM->startFunctionBodyCalls.size(); i != e; ++i) { - EXPECT_TRUE(FunctionsDeallocated.count( - RJMM->startFunctionBodyCalls[i].Result)) - << "Function leaked: \n" << RJMM->startFunctionBodyCalls[i].F_dump; - } - EXPECT_EQ(RJMM->startFunctionBodyCalls.size(), - RJMM->deallocateFunctionBodyCalls.size()); -} - -// ARM, MIPS and PPC still emit stubs for calls since the target may be -// too far away to call directly. This #if can probably be removed when -// http://llvm.org/PR5201 is fixed. -#if !defined(__arm__) && !defined(__mips__) && \ - !defined(__powerpc__) && !defined(__ppc__) && !defined(__aarch64__) -typedef int (*FooPtr) (); - -TEST_F(JITTest, NoStubs) { - LoadAssembly("define void @bar() {" - "entry: " - "ret void" - "}" - " " - "define i32 @foo() {" - "entry:" - "call void @bar()" - "ret i32 undef" - "}" - " " - "define i32 @main() {" - "entry:" - "%0 = call i32 @foo()" - "call void @bar()" - "ret i32 undef" - "}"); - Function *foo = M->getFunction("foo"); - uintptr_t tmp = (uintptr_t)(TheJIT->getPointerToFunction(foo)); - FooPtr ptr = (FooPtr)(tmp); - - (ptr)(); - - // We should now allocate no more stubs, we have the code to foo - // and the existing stub for bar. - int stubsBefore = RJMM->stubsAllocated; - Function *func = M->getFunction("main"); - TheJIT->getPointerToFunction(func); - - Function *bar = M->getFunction("bar"); - TheJIT->getPointerToFunction(bar); - - ASSERT_EQ(stubsBefore, RJMM->stubsAllocated); -} -#endif // !ARM && !PPC - -TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("define i8()* @get_foo_addr() { " - " ret i8()* @foo " - "} " - " " - "define i8 @foo() { " - " ret i8 42 " - "} "); - Function *F_get_foo_addr = M->getFunction("get_foo_addr"); - - typedef char(*fooT)(); - fooT (*get_foo_addr)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(F_get_foo_addr)); - fooT foo_addr = get_foo_addr(); - - // Now free get_foo_addr. This should not free the machine code for foo or - // any call stub returned as foo's canonical address. - TheJIT->freeMachineCodeForFunction(F_get_foo_addr); - - // Check by calling the reported address of foo. - EXPECT_EQ(42, foo_addr()); - - // The reported address should also be the same as the result of a subsequent - // getPointerToFunction(foo). -#if 0 - // Fails until PR5126 is fixed: - Function *F_foo = M->getFunction("foo"); - fooT foo = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(F_foo)); - EXPECT_EQ((intptr_t)foo, (intptr_t)foo_addr); -#endif -} - -// ARM does not have an implementation of replaceMachineCodeForFunction(), -// so recompileAndRelinkFunction doesn't work. -#if !defined(__arm__) && !defined(__aarch64__) -TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { - Function *F = Function::Create(TypeBuilder::get(Context), - GlobalValue::ExternalLinkage, "test", M); - BasicBlock *Entry = BasicBlock::Create(Context, "entry", F); - IRBuilder<> Builder(Entry); - Value *Val = ConstantInt::get(TypeBuilder::get(Context), 1); - Builder.CreateRet(Val); - - TheJIT->DisableLazyCompilation(true); - // Compile the function once, and make sure it works. - int (*OrigFPtr)() = reinterpret_cast( - (intptr_t)TheJIT->recompileAndRelinkFunction(F)); - EXPECT_EQ(1, OrigFPtr()); - - // Now change the function to return a different value. - Entry->eraseFromParent(); - BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F); - Builder.SetInsertPoint(NewEntry); - Val = ConstantInt::get(TypeBuilder::get(Context), 2); - Builder.CreateRet(Val); - // Recompile it, which should produce a new function pointer _and_ update the - // old one. - int (*NewFPtr)() = reinterpret_cast( - (intptr_t)TheJIT->recompileAndRelinkFunction(F)); - - EXPECT_EQ(2, NewFPtr()) - << "The new pointer should call the new version of the function"; - EXPECT_EQ(2, OrigFPtr()) - << "The old pointer's target should now jump to the new version"; -} -#endif // !defined(__arm__) - -TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("@JITTest_AvailableExternallyGlobal = " - " available_externally global i32 7 " - " " - "define i32 @loader() { " - " %result = load i32* @JITTest_AvailableExternallyGlobal " - " ret i32 %result " - "} "); - Function *loaderIR = M->getFunction("loader"); - - int32_t (*loader)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(loaderIR)); - EXPECT_EQ(42, loader()) << "func should return 42 from the external global," - << " not 7 from the IR version."; -} - -TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("define available_externally i32 " - " @JITTest_AvailableExternallyFunction() { " - " ret i32 7 " - "} " - " " - "define i32 @func() { " - " %result = tail call i32 " - " @JITTest_AvailableExternallyFunction() " - " ret i32 %result " - "} "); - Function *funcIR = M->getFunction("func"); - - int32_t (*func)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(funcIR)); - EXPECT_EQ(42, func()) << "func should return 42 from the static version," - << " not 7 from the IR version."; -} - -TEST_F(JITTest, EscapedLazyStubStillCallable) { - TheJIT->DisableLazyCompilation(false); - LoadAssembly("define internal i32 @stubbed() { " - " ret i32 42 " - "} " - " " - "define i32()* @get_stub() { " - " ret i32()* @stubbed " - "} "); - typedef int32_t(*StubTy)(); - - // Call get_stub() to get the address of @stubbed without actually JITting it. - Function *get_stubIR = M->getFunction("get_stub"); - StubTy (*get_stub)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(get_stubIR)); - StubTy stubbed = get_stub(); - // Now get_stubIR is the only reference to stubbed's stub. - get_stubIR->eraseFromParent(); - // Now there are no references inside the JIT, but we've got a pointer outside - // it. The stub should be callable and return the right value. - EXPECT_EQ(42, stubbed()); -} - -// Converts the LLVM assembly to bitcode and returns it in a std::string. An -// empty string indicates an error. -std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) { - Module TempModule("TempModule", Context); - if (!LoadAssemblyInto(&TempModule, Assembly)) { - return ""; - } - - std::string Result; - raw_string_ostream OS(Result); - WriteBitcodeToFile(&TempModule, OS); - OS.flush(); - return Result; -} - -// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode' -// lazily. The associated Module (owned by the ExecutionEngine) is returned in -// M. Both will be NULL on an error. Bitcode must live at least as long as the -// ExecutionEngine. -ExecutionEngine *getJITFromBitcode( - LLVMContext &Context, const std::string &Bitcode, Module *&M) { - // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. - MemoryBuffer *BitcodeBuffer = - MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test"); - ErrorOr ModuleOrErr = getLazyBitcodeModule(BitcodeBuffer, Context); - if (std::error_code EC = ModuleOrErr.getError()) { - ADD_FAILURE() << EC.message(); - delete BitcodeBuffer; - return nullptr; - } - M = ModuleOrErr.get(); - std::string errMsg; - ExecutionEngine *TheJIT = EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&errMsg) - .create(); - if (TheJIT == nullptr) { - ADD_FAILURE() << errMsg; - delete M; - M = nullptr; - return nullptr; - } - return TheJIT; -} - -TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) { - LLVMContext Context; - const std::string Bitcode = - AssembleToBitcode(Context, - "define available_externally i32 " - " @JITTest_AvailableExternallyFunction() { " - " ret i32 7 " - "} " - " " - "define i32 @func() { " - " %result = tail call i32 " - " @JITTest_AvailableExternallyFunction() " - " ret i32 %result " - "} "); - ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; - Module *M; - std::unique_ptr TheJIT( - getJITFromBitcode(Context, Bitcode, M)); - ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; - TheJIT->DisableLazyCompilation(true); - - Function *funcIR = M->getFunction("func"); - Function *availableFunctionIR = - M->getFunction("JITTest_AvailableExternallyFunction"); - - // Double-check that the available_externally function is still unmaterialized - // when getPointerToFunction needs to find out if it's available_externally. - EXPECT_TRUE(availableFunctionIR->isMaterializable()); - - int32_t (*func)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(funcIR)); - EXPECT_EQ(42, func()) << "func should return 42 from the static version," - << " not 7 from the IR version."; -} - -TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { - LLVMContext Context; - const std::string Bitcode = - AssembleToBitcode(Context, - "define i32 @recur1(i32 %a) { " - " %zero = icmp eq i32 %a, 0 " - " br i1 %zero, label %done, label %notdone " - "done: " - " ret i32 3 " - "notdone: " - " %am1 = sub i32 %a, 1 " - " %result = call i32 @recur2(i32 %am1) " - " ret i32 %result " - "} " - " " - "define i32 @recur2(i32 %b) { " - " %result = call i32 @recur1(i32 %b) " - " ret i32 %result " - "} "); - ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; - Module *M; - std::unique_ptr TheJIT( - getJITFromBitcode(Context, Bitcode, M)); - ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; - TheJIT->DisableLazyCompilation(true); - - Function *recur1IR = M->getFunction("recur1"); - Function *recur2IR = M->getFunction("recur2"); - EXPECT_TRUE(recur1IR->isMaterializable()); - EXPECT_TRUE(recur2IR->isMaterializable()); - - int32_t (*recur1)(int32_t) = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(recur1IR)); - EXPECT_EQ(3, recur1(4)); -} -#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -} diff --git a/unittests/ExecutionEngine/JIT/JITTests.def b/unittests/ExecutionEngine/JIT/JITTests.def deleted file mode 100644 index 17c91e8..0000000 --- a/unittests/ExecutionEngine/JIT/JITTests.def +++ /dev/null @@ -1,4 +0,0 @@ -EXPORTS -getPointerToNamedFunction -JITTest_AvailableExternallyFunction -JITTest_AvailableExternallyGlobal diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile deleted file mode 100644 index d86c03b..0000000 --- a/unittests/ExecutionEngine/JIT/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -##===- unittests/ExecutionEngine/JIT/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -TESTNAME = JIT -LINK_COMPONENTS := asmparser bitreader bitwriter jit native - -# The JIT tests need to dlopen things. -NO_DEAD_STRIP := 1 - -include $(LEVEL)/Makefile.config - -SOURCES := JITEventListenerTest.cpp JITMemoryManagerTest.cpp JITTest.cpp MultiJITTest.cpp - - -ifeq ($(USE_INTEL_JITEVENTS), 1) - # Build the Intel JIT Events interface tests - SOURCES += IntelJITEventListenerTest.cpp - - # Add the Intel JIT Events include directory - CPPFLAGS += -I$(INTEL_JITEVENTS_INCDIR) - - # Link against the LLVM Intel JIT Evens interface library - LINK_COMPONENTS += debuginfo inteljitevents object -endif - -ifeq ($(USE_OPROFILE), 1) - # Build the OProfile JIT interface tests - SOURCES += OProfileJITEventListenerTest.cpp - - # Link against the LLVM oprofile interface library - LINK_COMPONENTS += oprofilejit -endif - -EXPORTED_SYMBOL_FILE = $(PROJ_OBJ_DIR)/JITTests.exports - -include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest - -# Permit these tests to use the JIT's symbolic lookup. -LD.Flags += $(RDYNAMIC) - -# Symbol exports are necessary (at least for now) when building with LTO. -$(LLVMUnitTestExe): $(NativeExportsFile) -$(PROJ_OBJ_DIR)/JITTests.exports: $(PROJ_SRC_DIR)/JITTests.def $(PROJ_OBJ_DIR)/.dir - tail -n +2 $< > $@ - diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp deleted file mode 100644 index f530e0d..0000000 --- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp +++ /dev/null @@ -1,190 +0,0 @@ -//===- MultiJITTest.cpp - Unit tests for instantiating multiple JITs ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/SourceMgr.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -namespace { - -// ARM, PowerPC and SystemZ tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ - && !defined(__aarch64__) - -bool LoadAssemblyInto(Module *M, const char *assembly) { - SMDiagnostic Error; - bool success = - nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); - std::string errMsg; - raw_string_ostream os(errMsg); - Error.print("", os); - EXPECT_TRUE(success) << os.str(); - return success; -} - -void createModule1(LLVMContext &Context1, Module *&M1, Function *&FooF1) { - M1 = new Module("test1", Context1); - LoadAssemblyInto(M1, - "define i32 @add1(i32 %ArgX1) { " - "entry: " - " %addresult = add i32 1, %ArgX1 " - " ret i32 %addresult " - "} " - " " - "define i32 @foo1() { " - "entry: " - " %add1 = call i32 @add1(i32 10) " - " ret i32 %add1 " - "} "); - FooF1 = M1->getFunction("foo1"); -} - -void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) { - M2 = new Module("test2", Context2); - LoadAssemblyInto(M2, - "define i32 @add2(i32 %ArgX2) { " - "entry: " - " %addresult = add i32 2, %ArgX2 " - " ret i32 %addresult " - "} " - " " - "define i32 @foo2() { " - "entry: " - " %add2 = call i32 @add2(i32 10) " - " ret i32 %add2 " - "} "); - FooF2 = M2->getFunction("foo2"); -} - -TEST(MultiJitTest, EagerMode) { - LLVMContext Context1; - Module *M1 = nullptr; - Function *FooF1 = nullptr; - createModule1(Context1, M1, FooF1); - - LLVMContext Context2; - Module *M2 = nullptr; - Function *FooF2 = nullptr; - createModule2(Context2, M2, FooF2); - - // Now we create the JIT in eager mode - std::unique_ptr EE1(EngineBuilder(M1).create()); - EE1->DisableLazyCompilation(true); - std::unique_ptr EE2(EngineBuilder(M2).create()); - EE2->DisableLazyCompilation(true); - - // Call the `foo' function with no arguments: - std::vector noargs; - GenericValue gv1 = EE1->runFunction(FooF1, noargs); - GenericValue gv2 = EE2->runFunction(FooF2, noargs); - - // Import result of execution: - EXPECT_EQ(gv1.IntVal, 11); - EXPECT_EQ(gv2.IntVal, 12); - - EE1->freeMachineCodeForFunction(FooF1); - EE2->freeMachineCodeForFunction(FooF2); -} - -TEST(MultiJitTest, LazyMode) { - LLVMContext Context1; - Module *M1 = nullptr; - Function *FooF1 = nullptr; - createModule1(Context1, M1, FooF1); - - LLVMContext Context2; - Module *M2 = nullptr; - Function *FooF2 = nullptr; - createModule2(Context2, M2, FooF2); - - // Now we create the JIT in lazy mode - std::unique_ptr EE1(EngineBuilder(M1).create()); - EE1->DisableLazyCompilation(false); - std::unique_ptr EE2(EngineBuilder(M2).create()); - EE2->DisableLazyCompilation(false); - - // Call the `foo' function with no arguments: - std::vector noargs; - GenericValue gv1 = EE1->runFunction(FooF1, noargs); - GenericValue gv2 = EE2->runFunction(FooF2, noargs); - - // Import result of execution: - EXPECT_EQ(gv1.IntVal, 11); - EXPECT_EQ(gv2.IntVal, 12); - - EE1->freeMachineCodeForFunction(FooF1); - EE2->freeMachineCodeForFunction(FooF2); -} - -extern "C" { - extern void *getPointerToNamedFunction(const char *Name); -} - -TEST(MultiJitTest, JitPool) { - LLVMContext Context1; - Module *M1 = nullptr; - Function *FooF1 = nullptr; - createModule1(Context1, M1, FooF1); - - LLVMContext Context2; - Module *M2 = nullptr; - Function *FooF2 = nullptr; - createModule2(Context2, M2, FooF2); - - // Now we create two JITs - std::unique_ptr EE1(EngineBuilder(M1).create()); - std::unique_ptr EE2(EngineBuilder(M2).create()); - - Function *F1 = EE1->FindFunctionNamed("foo1"); - void *foo1 = EE1->getPointerToFunction(F1); - - Function *F2 = EE2->FindFunctionNamed("foo2"); - void *foo2 = EE2->getPointerToFunction(F2); - - // Function in M1 - EXPECT_EQ(getPointerToNamedFunction("foo1"), foo1); - - // Function in M2 - EXPECT_EQ(getPointerToNamedFunction("foo2"), foo2); - - // Symbol search - intptr_t - sa = (intptr_t)getPointerToNamedFunction("getPointerToNamedFunction"); - EXPECT_TRUE(sa != 0); - intptr_t fa = (intptr_t)&getPointerToNamedFunction; - EXPECT_TRUE(fa != 0); -#ifdef __i386__ - // getPointerToNamedFunction might be indirect jump on Win32 --enable-shared. - // FF 25 : jmp *(pointer to IAT) - if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { - fa = *(intptr_t *)(fa + 2); // Address to IAT - EXPECT_TRUE(fa != 0); - fa = *(intptr_t *)fa; // Bound value of IAT - } -#elif defined(__x86_64__) - // getPointerToNamedFunction might be indirect jump - // on Win32 x64 --enable-shared. - // FF 25 : jmp *(RIP + pointer to IAT) - if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { - fa += *(int32_t *)(fa + 2) + 6; // Address to IAT(RIP) - fa = *(intptr_t *)fa; // Bound value of IAT - } -#endif - EXPECT_TRUE(sa == fa); -} -#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -} // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp deleted file mode 100644 index 7057fca..0000000 --- a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp +++ /dev/null @@ -1,165 +0,0 @@ -//===- OProfileJITEventListenerTest.cpp - Unit tests for OProfileJITEventsListener --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/OProfileWrapper.h" -#include "JITEventListenerTestCommon.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include -#include - -using namespace llvm; - -namespace { - -struct OprofileNativeFunction { - const char* Name; - uint64_t Addr; - const void* CodePtr; - unsigned int CodeSize; - - OprofileNativeFunction(const char* name, - uint64_t addr, - const void* code, - unsigned int size) - : Name(name) - , Addr(addr) - , CodePtr(code) - , CodeSize(size) { - } -}; - -typedef std::list NativeFunctionList; -typedef std::list NativeDebugList; -NativeFunctionList NativeFunctions; - -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of opagent library -namespace test_opagent { - -op_agent_t globalAgent = reinterpret_cast(42); - -op_agent_t open_agent() -{ - // return non-null op_agent_t - return globalAgent; -} - -int close_agent(op_agent_t agent) -{ - EXPECT_EQ(globalAgent, agent); - return 0; -} - -int write_native_code(op_agent_t agent, - const char* name, - uint64_t addr, - void const* code, - unsigned int size) -{ - EXPECT_EQ(globalAgent, agent); - OprofileNativeFunction func(name, addr, code, size); - NativeFunctions.push_back(func); - - // Verify no other registration has take place for the same address - EXPECT_TRUE(ReportedDebugFuncs.find(addr) == ReportedDebugFuncs.end()); - - ReportedDebugFuncs[addr]; - return 0; -} - -int write_debug_line_info(op_agent_t agent, - void const* code, - size_t num_entries, - struct debug_line_info const* info) -{ - EXPECT_EQ(globalAgent, agent); - - //verify code has been loaded first - uint64_t addr = reinterpret_cast(code); - NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); - EXPECT_TRUE(i != ReportedDebugFuncs.end()); - - NativeDebugList NativeInfo(info, info + num_entries); - - SourceLocations locs; - for(NativeDebugList::iterator i = NativeInfo.begin(); - i != NativeInfo.end(); - ++i) { - locs.push_back(std::make_pair(std::string(i->filename), i->lineno)); - } - ReportedDebugFuncs[addr] = locs; - - return 0; -} - -int unload_native_code(op_agent_t agent, uint64_t addr) { - EXPECT_EQ(globalAgent, agent); - - //verify that something for the given JIT addr has been loaded first - NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); - EXPECT_TRUE(i != ReportedDebugFuncs.end()); - ReportedDebugFuncs.erase(i); - return 0; -} - -int version() { - return 1; -} - -bool is_oprofile_running() { - return true; -} - -} //namespace test_opagent - -class OProfileJITEventListenerTest -: public JITEventListenerTestBase -{ -public: - OProfileJITEventListenerTest() - : JITEventListenerTestBase( - new OProfileWrapper(test_opagent::open_agent, - test_opagent::close_agent, - test_opagent::write_native_code, - test_opagent::write_debug_line_info, - test_opagent::unload_native_code, - test_opagent::version, - test_opagent::version, - test_opagent::is_oprofile_running)) - { - EXPECT_TRUE(0 != MockWrapper); - - Listener.reset(JITEventListener::createOProfileJITEventListener( - MockWrapper.get())); - EXPECT_TRUE(0 != Listener); - EE->RegisterJITEventListener(Listener.get()); - } -}; - -TEST_F(OProfileJITEventListenerTest, NoDebugInfo) { - TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, SingleLine) { - TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleLines) { - TestMultipleLines(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleFiles) { - TestMultipleFiles(ReportedDebugFuncs); -} - -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index cbd08fe..b10cbb4 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -3,7 +3,6 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine IPO - JIT MC MCJIT ScalarOpts diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index d03de89..62967bd 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -139,8 +139,6 @@ protected: // The operating systems below are known to be sufficiently incompatible // that they will fail the MCJIT C API tests. - UnsupportedOSs.push_back(Triple::Cygwin); - UnsupportedEnvironments.push_back(Triple::Cygnus); } @@ -349,6 +347,44 @@ TEST_F(MCJITCAPITest, simple_function) { EXPECT_EQ(42, functionPointer.usable()); } +TEST_F(MCJITCAPITest, gva) { + SKIP_UNSUPPORTED_PLATFORM; + + Module = LLVMModuleCreateWithName("simple_module"); + LLVMSetTarget(Module, HostTriple.c_str()); + LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "simple_value"); + LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + buildMCJITOptions(); + buildMCJITEngine(); + buildAndRunPasses(); + + union { + uint64_t raw; + int32_t *usable; + } valuePointer; + valuePointer.raw = LLVMGetGlobalValueAddress(Engine, "simple_value"); + + EXPECT_EQ(42, *valuePointer.usable); +} + +TEST_F(MCJITCAPITest, gfa) { + SKIP_UNSUPPORTED_PLATFORM; + + buildSimpleFunction(); + buildMCJITOptions(); + buildMCJITEngine(); + buildAndRunPasses(); + + union { + uint64_t raw; + int (*usable)(); + } functionPointer; + functionPointer.raw = LLVMGetFunctionAddress(Engine, "simple_function"); + + EXPECT_EQ(42, functionPointer.usable()); +} + TEST_F(MCJITCAPITest, custom_memory_manager) { SKIP_UNSUPPORTED_PLATFORM; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp index 98587f7..0582c92 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/ExecutionEngine/JIT.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp index c5ca36e..b0d1bb3 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp @@ -94,8 +94,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_case) { Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -114,8 +114,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) { Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -135,8 +135,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) { Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -156,8 +156,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_case) { Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -177,8 +177,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) { createTwoModuleExternCase(A, FA1, B, FB); FA2 = insertSimpleCallFunction(A.get(), FA1); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -213,8 +213,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) { FB = startFunction(B.get(), "FB"); endFunctionWithRet(FB, Builder.CreateLoad(GVB)); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -241,9 +241,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case) { Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -266,9 +266,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -291,9 +291,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -316,9 +316,9 @@ TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -341,8 +341,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAccumulate(ptr); @@ -362,8 +362,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); checkAccumulate(ptr); @@ -383,8 +383,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) { Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); checkAccumulate(ptr); diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp index fbbab42..2e38dd8 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -11,7 +11,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -25,17 +24,7 @@ class TestObjectCache : public ObjectCache { public: TestObjectCache() : DuplicateInserted(false) { } - virtual ~TestObjectCache() { - // Free any buffers we've allocated. - SmallVectorImpl::iterator it, end; - end = AllocatedBuffers.end(); - for (it = AllocatedBuffers.begin(); it != end; ++it) { - delete *it; - } - AllocatedBuffers.clear(); - } - - virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { + void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override { // If we've seen this module before, note that. const std::string ModuleID = M->getModuleIdentifier(); if (ObjMap.find(ModuleID) != ObjMap.end()) @@ -44,7 +33,7 @@ public: ObjMap[ModuleID] = copyBuffer(Obj); } - virtual MemoryBuffer* getObject(const Module* M) { + virtual std::unique_ptr getObject(const Module* M) override { const MemoryBuffer* BufferFound = getObjectInternal(M); ModulesLookedUp.insert(M->getModuleIdentifier()); if (!BufferFound) @@ -72,16 +61,18 @@ public: } private: - MemoryBuffer *copyBuffer(const MemoryBuffer *Buf) { + MemoryBuffer *copyBuffer(MemoryBufferRef Buf) { // Create a local copy of the buffer. - MemoryBuffer *NewBuffer = MemoryBuffer::getMemBufferCopy(Buf->getBuffer()); - AllocatedBuffers.push_back(NewBuffer); - return NewBuffer; + std::unique_ptr NewBuffer = + MemoryBuffer::getMemBufferCopy(Buf.getBuffer()); + MemoryBuffer *Ret = NewBuffer.get(); + AllocatedBuffers.push_back(std::move(NewBuffer)); + return Ret; } StringMap ObjMap; StringSet<> ModulesLookedUp; - SmallVector AllocatedBuffers; + SmallVector, 2> AllocatedBuffers; bool DuplicateInserted; }; @@ -121,7 +112,7 @@ protected: TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { SKIP_UNSUPPORTED_PLATFORM; - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(nullptr); @@ -137,7 +128,7 @@ TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { // Save a copy of the module pointer before handing it off to MCJIT. const Module * SavedModulePointer = M.get(); - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); @@ -164,7 +155,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { std::unique_ptr Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -172,7 +163,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { TheJIT.reset(); // Create a new memory manager. - MM = new SectionMemoryManager; + MM.reset(new SectionMemoryManager()); // Create a new module and save it. Use a different return code so we can // tell if MCJIT compiled this module or used the cache. @@ -181,7 +172,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); compileAndRun(); @@ -198,7 +189,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { std::unique_ptr Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -206,7 +197,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { TheJIT.reset(); // Create a new memory manager. - MM = new SectionMemoryManager; + MM.reset(new SectionMemoryManager()); // Create a new module and save it. Use a different return code so we can // tell if MCJIT compiled this module or used the cache. Note that we use @@ -216,7 +207,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); // Verify that our object cache does not contain the module yet. diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp index c37c1d1..64d8c2f 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp @@ -49,7 +49,7 @@ TEST_F(MCJITTest, global_variable) { int initialValue = 5; GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue); - createJIT(M.release()); + createJIT(std::move(M)); void *globalPtr = TheJIT->getPointerToGlobal(Global); EXPECT_TRUE(nullptr != globalPtr) << "Unable to get pointer to global value from JIT"; @@ -62,7 +62,7 @@ TEST_F(MCJITTest, add_function) { SKIP_UNSUPPORTED_PLATFORM; Function *F = insertAddFunction(M.get()); - createJIT(M.release()); + createJIT(std::move(M)); uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str()); EXPECT_TRUE(0 != addPtr) << "Unable to get pointer to function from JIT"; @@ -83,7 +83,7 @@ TEST_F(MCJITTest, run_main) { int rc = 6; Function *Main = insertMainFunction(M.get(), 6); - createJIT(M.release()); + createJIT(std::move(M)); uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to main() from JIT"; @@ -104,7 +104,7 @@ TEST_F(MCJITTest, return_global) { Value *ReadGlobal = Builder.CreateLoad(GV); endFunctionWithRet(ReturnGlobal, ReadGlobal); - createJIT(M.release()); + createJIT(std::move(M)); uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str()); EXPECT_TRUE(0 != rgvPtr); @@ -175,7 +175,7 @@ TEST_F(MCJITTest, multiple_functions) { Inner = Outer; } - createJIT(M.release()); + createJIT(std::move(M)); uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to outer function from JIT"; @@ -187,4 +187,16 @@ TEST_F(MCJITTest, multiple_functions) { #endif /*!defined(__arm__)*/ +TEST_F(MCJITTest, multiple_decl_lookups) { + SKIP_UNSUPPORTED_PLATFORM; + + Function *Foo = insertExternalReferenceToFunction(M.get(), "_exit"); + createJIT(std::move(M)); + void *A = TheJIT->getPointerToFunction(Foo); + void *B = TheJIT->getPointerToFunction(Foo); + + EXPECT_TRUE(A != 0) << "Failed lookup - test not correctly configured."; + EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail."; +} + } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h index a48c071..7d704de 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MCJIT_TEST_API_COMMON_H -#define MCJIT_TEST_API_COMMON_H +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" @@ -93,5 +93,5 @@ protected: } // namespace llvm -#endif // MCJIT_TEST_API_COMMON_H +#endif diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index 25de312..35af417 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -14,8 +14,8 @@ //===----------------------------------------------------------------------===// -#ifndef MCJIT_TEST_BASE_H -#define MCJIT_TEST_BASE_H +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H #include "MCJITTestAPICommon.h" #include "llvm/Config/config.h" @@ -107,6 +107,15 @@ protected: return Result; } + // Inserts a declaration to a function defined elsewhere + template + Function *insertExternalReferenceToFunction(Module *M, StringRef Name) { + Function *Result = Function::Create( + TypeBuilder::get(Context), + GlobalValue::ExternalLinkage, Name, M); + return Result; + } + // Inserts an declaration to a function defined elsewhere Function *insertExternalReferenceToFunction(Module *M, StringRef Name, FunctionType *FuncTy) { @@ -302,26 +311,23 @@ protected: // The operating systems below are known to be incompatible with MCJIT as // they are copied from the test/ExecutionEngine/MCJIT/lit.local.cfg and // should be kept in sync. - UnsupportedOSs.push_back(Triple::Cygwin); UnsupportedOSs.push_back(Triple::Darwin); UnsupportedEnvironments.push_back(Triple::Cygnus); } - void createJIT(Module *M) { + void createJIT(std::unique_ptr M) { // Due to the EngineBuilder constructor, it is required to have a Module // in order to construct an ExecutionEngine (i.e. MCJIT) assert(M != 0 && "a non-null Module must be provided to create MCJIT"); - EngineBuilder EB(M); + EngineBuilder EB(std::move(M)); std::string Error; TheJIT.reset(EB.setEngineKind(EngineKind::JIT) - .setUseMCJIT(true) /* can this be folded into the EngineKind enum? */ - .setMCJITMemoryManager(MM) + .setMCJITMemoryManager(std::move(MM)) .setErrorStr(&Error) .setOptLevel(CodeGenOpt::None) - .setAllocateGVsWithCode(false) /*does this do anything?*/ .setCodeModel(CodeModel::JITDefault) .setRelocationModel(Reloc::Default) .setMArch(MArch) @@ -338,11 +344,11 @@ protected: StringRef MArch; SmallVector MAttrs; std::unique_ptr TheJIT; - RTDyldMemoryManager *MM; + std::unique_ptr MM; std::unique_ptr M; }; } // namespace llvm -#endif // MCJIT_TEST_H +#endif diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile index c4dd740..2822b20 100644 --- a/unittests/ExecutionEngine/MCJIT/Makefile +++ b/unittests/ExecutionEngine/MCJIT/Makefile @@ -9,7 +9,7 @@ LEVEL = ../../.. TESTNAME = MCJIT -LINK_COMPONENTS := core ipo jit mcjit native support +LINK_COMPONENTS := core ipo mcjit native support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index 38e667f..8ecb883 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -14,7 +14,7 @@ LINK_COMPONENTS :=interpreter include $(LEVEL)/Makefile.config ifeq ($(TARGET_HAS_JIT),1) - PARALLEL_DIRS = JIT MCJIT + PARALLEL_DIRS = MCJIT endif include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index b439d59..0c29796 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -10,10 +10,10 @@ set(IRSources AttributesTest.cpp ConstantRangeTest.cpp ConstantsTest.cpp + DebugInfoTest.cpp DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp - LeakDetectorTest.cpp LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp @@ -21,6 +21,7 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + UseTest.cpp UserTest.cpp ValueHandleTest.cpp ValueMapTest.cpp diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 0cd8549..5414b25 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -274,5 +274,78 @@ TEST(ConstantsTest, ReplaceWithConstantTest) { #undef CHECK +TEST(ConstantsTest, ConstantArrayReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt8Ty(Context); + ArrayType *ArrayTy = ArrayType::get(IntTy, 2); + Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0), + ConstantInt::get(IntTy, 1)}; + Constant *A01 = ConstantArray::get(ArrayTy, A01Vals); + + Constant *Global = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy); + Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt}; + Constant *A0G = ConstantArray::get(ArrayTy, A0GVals); + ASSERT_NE(A01, A0G); + + GlobalVariable *RefArray = + new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G); + ASSERT_EQ(A0G, RefArray->getInitializer()); + + GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1)); + ASSERT_EQ(A01, RefArray->getInitializer()); +} + +TEST(ConstantsTest, ConstantExprReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt8Ty(Context); + Constant *G1 = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + Constant *G2 = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + ASSERT_NE(G1, G2); + + Constant *Int1 = ConstantExpr::getPtrToInt(G1, IntTy); + Constant *Int2 = ConstantExpr::getPtrToInt(G2, IntTy); + ASSERT_NE(Int1, Int2); + + GlobalVariable *Ref = + new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, Int1); + ASSERT_EQ(Int1, Ref->getInitializer()); + + G1->replaceAllUsesWith(G2); + ASSERT_EQ(Int2, Ref->getInitializer()); +} + +TEST(ConstantsTest, GEPReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt32Ty(Context); + Type *PtrTy = PointerType::get(IntTy, 0); + auto *C1 = ConstantInt::get(IntTy, 1); + auto *Placeholder = new GlobalVariable( + *M, IntTy, false, GlobalValue::ExternalWeakLinkage, nullptr); + auto *GEP = ConstantExpr::getGetElementPtr(Placeholder, C1); + ASSERT_EQ(GEP->getOperand(0), Placeholder); + + auto *Ref = + new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP); + ASSERT_EQ(GEP, Ref->getInitializer()); + + auto *Global = new GlobalVariable(*M, PtrTy, false, + GlobalValue::ExternalLinkage, nullptr); + auto *Alias = GlobalAlias::create(IntTy, 0, GlobalValue::ExternalLinkage, + "alias", Global, M.get()); + Placeholder->replaceAllUsesWith(Alias); + ASSERT_EQ(GEP, Ref->getInitializer()); + ASSERT_EQ(GEP->getOperand(0), Alias); +} + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/IR/DebugInfoTest.cpp b/unittests/IR/DebugInfoTest.cpp new file mode 100644 index 0000000..1fa851e --- /dev/null +++ b/unittests/IR/DebugInfoTest.cpp @@ -0,0 +1,68 @@ +//===- llvm/unittest/IR/DebugInfo.cpp - DebugInfo tests -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DebugInfo.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace llvm { + +static void PrintTo(const StringRef &S, ::std::ostream *os) { + *os << "(" << (const void *)S.data() << "," << S.size() << ") = '"; + for (auto C : S) + if (C) + *os << C; + else + *os << "\\00"; + *os << "'"; +} +static void PrintTo(const DIHeaderFieldIterator &I, ::std::ostream *os) { + PrintTo(I.getCurrent(), os); + *os << " in "; + PrintTo(I.getHeader(), os); +} + +} // end namespace llvm + +namespace { + +#define MAKE_FIELD_ITERATOR(S) \ + DIHeaderFieldIterator(StringRef(S, sizeof(S) - 1)) +TEST(DebugInfoTest, DIHeaderFieldIterator) { + ASSERT_EQ(DIHeaderFieldIterator(), DIHeaderFieldIterator()); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("")); + ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("")); + ASSERT_EQ("", *DIHeaderFieldIterator("")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff")); + ASSERT_EQ("stuff", *DIHeaderFieldIterator("stuff")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ("st", *MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ("uff", *++MAKE_FIELD_ITERATOR("st\0uff")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ("stuff", *MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ("", *++MAKE_FIELD_ITERATOR("stuff\0")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ("", *MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ("stuff", *++MAKE_FIELD_ITERATOR("\0stuff")); +} + +} // end namespace diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index ab43d1c..6c43d6f 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -186,8 +186,7 @@ namespace llvm { }; char DPass::ID = 0; - - Module* makeLLVMModule(DPass *P) { + std::unique_ptr makeLLVMModule(DPass *P) { const char *ModuleStrig = "declare i32 @g()\n" \ "define void @f(i32 %x) {\n" \ @@ -213,12 +212,12 @@ namespace llvm { "}\n"; LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(ModuleStrig, nullptr, Err, C); + return parseAssemblyString(ModuleStrig, Err, C); } TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); - std::unique_ptr M(makeLLVMModule(P)); + std::unique_ptr M = makeLLVMModule(P); PassManager Passes; Passes.add(P); Passes.run(*M); diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 2108575..df5c840 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -189,12 +189,16 @@ TEST_F(IRBuilderTest, FastMathFlags) { Builder.clearFastMathFlags(); + // To test a copy, make sure that a '0' and a '1' change state. F = Builder.CreateFDiv(F, F); ASSERT_TRUE(isa(F)); FDiv = cast(F); EXPECT_FALSE(FDiv->getFastMathFlags().any()); + FDiv->setHasAllowReciprocal(true); + FAdd->setHasAllowReciprocal(false); FDiv->copyFastMathFlags(FAdd); EXPECT_TRUE(FDiv->hasNoNaNs()); + EXPECT_FALSE(FDiv->hasAllowReciprocal()); } diff --git a/unittests/IR/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp deleted file mode 100644 index 94eed4c..0000000 --- a/unittests/IR/LeakDetectorTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- LeakDetectorTest.cpp -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/LeakDetector.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -#ifdef GTEST_HAS_DEATH_TEST -#ifndef NDEBUG -TEST(LeakDetector, Death1) { - LeakDetector::addGarbageObject((void*) 1); - LeakDetector::addGarbageObject((void*) 2); - - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), - ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), - "Cache != o && \"Object already in set!\""); -} -#endif -#endif - -} diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 9c2a835..4efc2f5 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -54,11 +54,11 @@ namespace llvm { static char run; static char ID; ModuleNDNM() : ModulePass(ID) { } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } }; @@ -70,7 +70,7 @@ namespace llvm { static char run; static char ID; ModuleNDM() : ModulePass(ID) {} - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return true; } @@ -83,7 +83,7 @@ namespace llvm { static char run; static char ID; ModuleNDM2() : ModulePass(ID) {} - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return true; } @@ -98,12 +98,12 @@ namespace llvm { ModuleDNM() : ModulePass(ID) { initializeModuleNDMPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { EXPECT_TRUE(getAnalysisIfAvailable()); run++; return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.setPreservesAll(); } @@ -139,7 +139,7 @@ namespace llvm { runc = 0; } - virtual void releaseMemory() { + void releaseMemory() override { EXPECT_GT(runc, 0); EXPECT_GT(allocated, 0); allocated--; @@ -157,12 +157,12 @@ namespace llvm { using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; #endif - virtual bool doInitialization(T &t) { + bool doInitialization(T &t) override { EXPECT_FALSE(PassTestBase

::initialized); PassTestBase

::initialized = true; return false; } - virtual bool doFinalization(T &t) { + bool doFinalization(T &t) override { EXPECT_FALSE(PassTestBase

::finalized); PassTestBase

::finalized = true; EXPECT_EQ(0, PassTestBase

::allocated); @@ -175,7 +175,7 @@ namespace llvm { CGPass() { initializeCGPassPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnSCC(CallGraphSCC &SCMM) { + bool runOnSCC(CallGraphSCC &SCMM) override { EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; @@ -184,7 +184,7 @@ namespace llvm { struct FPass : public PassTest { public: - virtual bool runOnFunction(Function &F) { + bool runOnFunction(Function &F) override { // FIXME: PR4112 // EXPECT_TRUE(getAnalysisIfAvailable()); run(); @@ -209,17 +209,17 @@ namespace llvm { } using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; - virtual bool doInitialization(Loop* L, LPPassManager &LPM) { + bool doInitialization(Loop* L, LPPassManager &LPM) override { initialized = true; initcount++; return false; } - virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { + bool runOnLoop(Loop *L, LPPassManager &LPM) override { EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; } - virtual bool doFinalization() { + bool doFinalization() override { fincount++; finalized = true; return false; @@ -242,25 +242,25 @@ namespace llvm { inited = 0; fin = 0; } - virtual bool doInitialization(Module &M) { + bool doInitialization(Module &M) override { EXPECT_FALSE(initialized); initialized = true; return false; } - virtual bool doInitialization(Function &F) { + bool doInitialization(Function &F) override { inited++; return false; } - virtual bool runOnBasicBlock(BasicBlock &BB) { + bool runOnBasicBlock(BasicBlock &BB) override { EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; } - virtual bool doFinalization(Function &F) { + bool doFinalization(Function &F) override { fin++; return false; } - virtual bool doFinalization(Module &M) { + bool doFinalization(Module &M) override { EXPECT_FALSE(finalized); finalized = true; EXPECT_EQ(0, allocated); @@ -276,7 +276,7 @@ namespace llvm { OnTheFlyTest() : ModulePass(ID) { initializeFPassPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { EXPECT_TRUE(getAnalysisIfAvailable()); for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { Function &F = *I; @@ -287,7 +287,7 @@ namespace llvm { } return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); } }; @@ -303,7 +303,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayoutPass(&M)); + Passes.add(new DataLayoutPass()); Passes.add(mNDM2); Passes.add(mNDM); Passes.add(mNDNM); @@ -327,7 +327,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayoutPass(&M)); + Passes.add(new DataLayoutPass()); Passes.add(mNDM); Passes.add(mNDNM); Passes.add(mNDM2);// invalidates mNDM needed by mDNM @@ -349,7 +349,7 @@ namespace llvm { std::unique_ptr M(makeLLVMModule()); T *P = new T(); PassManager Passes; - Passes.add(new DataLayoutPass(M.get())); + Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); T::finishedOK(run); @@ -360,7 +360,7 @@ namespace llvm { Module *M = makeLLVMModule(); T *P = new T(); PassManager Passes; - Passes.add(new DataLayoutPass(M)); + Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); T::finishedOK(run, N); @@ -398,7 +398,7 @@ namespace llvm { SCOPED_TRACE("Running OnTheFlyTest"); struct OnTheFlyTest *O = new OnTheFlyTest(); PassManager Passes; - Passes.add(new DataLayoutPass(M)); + Passes.add(new DataLayoutPass()); Passes.add(O); Passes.run(*M); diff --git a/unittests/IR/MDBuilderTest.cpp b/unittests/IR/MDBuilderTest.cpp index fc4674e..ab2d34e 100644 --- a/unittests/IR/MDBuilderTest.cpp +++ b/unittests/IR/MDBuilderTest.cpp @@ -36,10 +36,10 @@ TEST_F(MDBuilderTest, createFPMath) { EXPECT_EQ(MD0, (MDNode *)nullptr); EXPECT_NE(MD1, (MDNode *)nullptr); EXPECT_EQ(MD1->getNumOperands(), 1U); - Value *Op = MD1->getOperand(0); - EXPECT_TRUE(isa(Op)); - EXPECT_TRUE(Op->getType()->isFloatingPointTy()); - ConstantFP *Val = cast(Op); + Metadata *Op = MD1->getOperand(0); + EXPECT_TRUE(mdconst::hasa(Op)); + ConstantFP *Val = mdconst::extract(Op); + EXPECT_TRUE(Val->getType()->isFloatingPointTy()); EXPECT_TRUE(Val->isExactlyValue(1.0)); } TEST_F(MDBuilderTest, createRangeMetadata) { @@ -50,10 +50,10 @@ TEST_F(MDBuilderTest, createRangeMetadata) { EXPECT_EQ(R0, (MDNode *)nullptr); EXPECT_NE(R1, (MDNode *)nullptr); EXPECT_EQ(R1->getNumOperands(), 2U); - EXPECT_TRUE(isa(R1->getOperand(0))); - EXPECT_TRUE(isa(R1->getOperand(1))); - ConstantInt *C0 = cast(R1->getOperand(0)); - ConstantInt *C1 = cast(R1->getOperand(1)); + EXPECT_TRUE(mdconst::hasa(R1->getOperand(0))); + EXPECT_TRUE(mdconst::hasa(R1->getOperand(1))); + ConstantInt *C0 = mdconst::extract(R1->getOperand(0)); + ConstantInt *C1 = mdconst::extract(R1->getOperand(1)); EXPECT_EQ(C0->getValue(), A); EXPECT_EQ(C1->getValue(), B); } @@ -101,7 +101,8 @@ TEST_F(MDBuilderTest, createTBAANode) { EXPECT_EQ(N0->getOperand(1), R); EXPECT_EQ(N1->getOperand(1), R); EXPECT_EQ(N2->getOperand(1), R); - EXPECT_TRUE(isa(N2->getOperand(2))); - EXPECT_EQ(cast(N2->getOperand(2))->getZExtValue(), 1U); + EXPECT_TRUE(mdconst::hasa(N2->getOperand(2))); + EXPECT_EQ(mdconst::extract(N2->getOperand(2))->getZExtValue(), + 1U); } } diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 4f7bd72..f862f04 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/Metadata.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; @@ -23,6 +23,12 @@ namespace { class MetadataTest : public testing::Test { protected: LLVMContext Context; + MDNode *getNode() { return MDNode::get(Context, None); } + MDNode *getNode(Metadata *MD) { return MDNode::get(Context, MD); } + MDNode *getNode(Metadata *MD1, Metadata *MD2) { + Metadata *MDs[] = {MD1, MD2}; + return MDNode::get(Context, MDs); + } }; typedef MetadataTest MDStringTest; @@ -58,7 +64,7 @@ TEST_F(MDStringTest, PrintingSimple) { std::string Str; raw_string_ostream oss(Str); s->print(oss); - EXPECT_STREQ("metadata !\"testing 1 2 3\"", oss.str().c_str()); + EXPECT_STREQ("!\"testing 1 2 3\"", oss.str().c_str()); } // Test printing of MDString with non-printable characters. @@ -68,7 +74,7 @@ TEST_F(MDStringTest, PrintingComplex) { std::string Str; raw_string_ostream oss(Str); s->print(oss); - EXPECT_STREQ("metadata !\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str()); + EXPECT_STREQ("!\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str()); } typedef MetadataTest MDNodeTest; @@ -80,30 +86,27 @@ TEST_F(MDNodeTest, Simple) { MDString *s1 = MDString::get(Context, StringRef(&x[0], 3)); MDString *s2 = MDString::get(Context, StringRef(&y[0], 3)); - ConstantInt *CI = ConstantInt::get(getGlobalContext(), APInt(8, 0)); + ConstantAsMetadata *CI = ConstantAsMetadata::get( + ConstantInt::get(getGlobalContext(), APInt(8, 0))); - std::vector V; + std::vector V; V.push_back(s1); V.push_back(CI); V.push_back(s2); MDNode *n1 = MDNode::get(Context, V); - Value *const c1 = n1; + Metadata *const c1 = n1; MDNode *n2 = MDNode::get(Context, c1); - Value *const c2 = n2; + Metadata *const c2 = n2; MDNode *n3 = MDNode::get(Context, V); MDNode *n4 = MDNode::getIfExists(Context, V); MDNode *n5 = MDNode::getIfExists(Context, c1); MDNode *n6 = MDNode::getIfExists(Context, c2); EXPECT_NE(n1, n2); -#ifdef ENABLE_MDNODE_UNIQUING EXPECT_EQ(n1, n3); -#else - (void) n3; -#endif EXPECT_EQ(n4, n1); EXPECT_EQ(n5, n2); - EXPECT_EQ(n6, (Value*)nullptr); + EXPECT_EQ(n6, (Metadata *)nullptr); EXPECT_EQ(3u, n1->getNumOperands()); EXPECT_EQ(s1, n1->getOperand(0)); @@ -118,22 +121,437 @@ TEST_F(MDNodeTest, Delete) { Constant *C = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 1); Instruction *I = new BitCastInst(C, Type::getInt32Ty(getGlobalContext())); - Value *const V = I; + Metadata *const V = LocalAsMetadata::get(I); MDNode *n = MDNode::get(Context, V); - WeakVH wvh = n; + TrackingMDRef wvh(n); EXPECT_EQ(n, wvh); delete I; } +TEST_F(MDNodeTest, DeleteMDNodeFwdDecl) { + delete MDNode::getTemporary(Context, None); +} + +TEST_F(MDNodeTest, SelfReference) { + // !0 = !{!0} + // !1 = !{!0} + { + MDNode *Temp = MDNode::getTemporary(Context, None); + Metadata *Args[] = {Temp}; + MDNode *Self = MDNode::get(Context, Args); + Self->replaceOperandWith(0, Self); + MDNode::deleteTemporary(Temp); + ASSERT_EQ(Self, Self->getOperand(0)); + + // Self-references should be distinct, so MDNode::get() should grab a + // uniqued node that references Self, not Self. + Args[0] = Self; + MDNode *Ref1 = MDNode::get(Context, Args); + MDNode *Ref2 = MDNode::get(Context, Args); + EXPECT_NE(Self, Ref1); + EXPECT_EQ(Ref1, Ref2); + } + + // !0 = !{!0, !{}} + // !1 = !{!0, !{}} + { + MDNode *Temp = MDNode::getTemporary(Context, None); + Metadata *Args[] = {Temp, MDNode::get(Context, None)}; + MDNode *Self = MDNode::get(Context, Args); + Self->replaceOperandWith(0, Self); + MDNode::deleteTemporary(Temp); + ASSERT_EQ(Self, Self->getOperand(0)); + + // Self-references should be distinct, so MDNode::get() should grab a + // uniqued node that references Self, not Self itself. + Args[0] = Self; + MDNode *Ref1 = MDNode::get(Context, Args); + MDNode *Ref2 = MDNode::get(Context, Args); + EXPECT_NE(Self, Ref1); + EXPECT_EQ(Ref1, Ref2); + } +} + +TEST_F(MDNodeTest, Print) { + Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7); + MDString *S = MDString::get(Context, "foo"); + MDNode *N0 = getNode(); + MDNode *N1 = getNode(N0); + MDNode *N2 = getNode(N0, N1); + + Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2}; + MDNode *N = MDNode::get(Context, Args); + + std::string Expected; + { + raw_string_ostream OS(Expected); + OS << "!{"; + C->printAsOperand(OS); + OS << ", "; + S->printAsOperand(OS); + OS << ", null"; + MDNode *Nodes[] = {N0, N1, N2}; + for (auto *Node : Nodes) + OS << ", <" << (void *)Node << ">"; + OS << "}\n"; + } + + std::string Actual; + { + raw_string_ostream OS(Actual); + N->print(OS); + } + + EXPECT_EQ(Expected, Actual); +} + +TEST_F(MDNodeTest, NullOperand) { + // metadata !{} + MDNode *Empty = MDNode::get(Context, None); + + // metadata !{metadata !{}} + Metadata *Ops[] = {Empty}; + MDNode *N = MDNode::get(Context, Ops); + ASSERT_EQ(Empty, N->getOperand(0)); + + // metadata !{metadata !{}} => metadata !{null} + N->replaceOperandWith(0, nullptr); + ASSERT_EQ(nullptr, N->getOperand(0)); + + // metadata !{null} + Ops[0] = nullptr; + MDNode *NullOp = MDNode::get(Context, Ops); + ASSERT_EQ(nullptr, NullOp->getOperand(0)); + EXPECT_EQ(N, NullOp); +} + +TEST_F(MDNodeTest, DistinctOnUniquingCollision) { + // !{} + MDNode *Empty = MDNode::get(Context, None); + ASSERT_TRUE(Empty->isResolved()); + EXPECT_FALSE(Empty->isDistinct()); + + // !{!{}} + Metadata *Wrapped1Ops[] = {Empty}; + MDNode *Wrapped1 = MDNode::get(Context, Wrapped1Ops); + ASSERT_EQ(Empty, Wrapped1->getOperand(0)); + ASSERT_TRUE(Wrapped1->isResolved()); + EXPECT_FALSE(Wrapped1->isDistinct()); + + // !{!{!{}}} + Metadata *Wrapped2Ops[] = {Wrapped1}; + MDNode *Wrapped2 = MDNode::get(Context, Wrapped2Ops); + ASSERT_EQ(Wrapped1, Wrapped2->getOperand(0)); + ASSERT_TRUE(Wrapped2->isResolved()); + EXPECT_FALSE(Wrapped2->isDistinct()); + + // !{!{!{}}} => !{!{}} + Wrapped2->replaceOperandWith(0, Empty); + ASSERT_EQ(Empty, Wrapped2->getOperand(0)); + EXPECT_TRUE(Wrapped2->isDistinct()); + EXPECT_FALSE(Wrapped1->isDistinct()); +} + +TEST_F(MDNodeTest, getDistinct) { + // !{} + MDNode *Empty = MDNode::get(Context, None); + ASSERT_TRUE(Empty->isResolved()); + ASSERT_FALSE(Empty->isDistinct()); + ASSERT_EQ(Empty, MDNode::get(Context, None)); + + // distinct !{} + MDNode *Distinct1 = MDNode::getDistinct(Context, None); + MDNode *Distinct2 = MDNode::getDistinct(Context, None); + EXPECT_TRUE(Distinct1->isResolved()); + EXPECT_TRUE(Distinct2->isDistinct()); + EXPECT_NE(Empty, Distinct1); + EXPECT_NE(Empty, Distinct2); + EXPECT_NE(Distinct1, Distinct2); + + // !{} + ASSERT_EQ(Empty, MDNode::get(Context, None)); +} + +TEST_F(MDNodeTest, TempIsDistinct) { + MDNode *T = MDNode::getTemporary(Context, None); + EXPECT_TRUE(T->isDistinct()); + MDNode::deleteTemporary(T); +} + +TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) { + // temporary !{} + MDNodeFwdDecl *Temp = MDNode::getTemporary(Context, None); + ASSERT_FALSE(Temp->isResolved()); + + // distinct !{temporary !{}} + Metadata *Ops[] = {Temp}; + MDNode *Distinct = MDNode::getDistinct(Context, Ops); + EXPECT_TRUE(Distinct->isResolved()); + EXPECT_EQ(Temp, Distinct->getOperand(0)); + + // temporary !{} => !{} + MDNode *Empty = MDNode::get(Context, None); + Temp->replaceAllUsesWith(Empty); + MDNode::deleteTemporary(Temp); + EXPECT_EQ(Empty, Distinct->getOperand(0)); +} + +TEST_F(MDNodeTest, handleChangedOperandRecursion) { + // !0 = !{} + MDNode *N0 = MDNode::get(Context, None); + + // !1 = !{!3, null} + std::unique_ptr Temp3(MDNode::getTemporary(Context, None)); + Metadata *Ops1[] = {Temp3.get(), nullptr}; + MDNode *N1 = MDNode::get(Context, Ops1); + + // !2 = !{!3, !0} + Metadata *Ops2[] = {Temp3.get(), N0}; + MDNode *N2 = MDNode::get(Context, Ops2); + + // !3 = !{!2} + Metadata *Ops3[] = {N2}; + MDNode *N3 = MDNode::get(Context, Ops3); + Temp3->replaceAllUsesWith(N3); + + // !4 = !{!1} + Metadata *Ops4[] = {N1}; + MDNode *N4 = MDNode::get(Context, Ops4); + + // Confirm that the cycle prevented RAUW from getting dropped. + EXPECT_TRUE(N0->isResolved()); + EXPECT_FALSE(N1->isResolved()); + EXPECT_FALSE(N2->isResolved()); + EXPECT_FALSE(N3->isResolved()); + EXPECT_FALSE(N4->isResolved()); + + // Create a couple of distinct nodes to observe what's going on. + // + // !5 = distinct !{!2} + // !6 = distinct !{!3} + Metadata *Ops5[] = {N2}; + MDNode *N5 = MDNode::getDistinct(Context, Ops5); + Metadata *Ops6[] = {N3}; + MDNode *N6 = MDNode::getDistinct(Context, Ops6); + + // Mutate !2 to look like !1, causing a uniquing collision (and an RAUW). + // This will ripple up, with !3 colliding with !4, and RAUWing. Since !2 + // references !3, this can cause a re-entry of handleChangedOperand() when !3 + // is not ready for it. + // + // !2->replaceOperandWith(1, nullptr) + // !2: !{!3, !0} => !{!3, null} + // !2->replaceAllUsesWith(!1) + // !3: !{!2] => !{!1} + // !3->replaceAllUsesWith(!4) + N2->replaceOperandWith(1, nullptr); + + // If all has gone well, N2 and N3 will have been RAUW'ed and deleted from + // under us. Just check that the other nodes are sane. + // + // !1 = !{!4, null} + // !4 = !{!1} + // !5 = distinct !{!1} + // !6 = distinct !{!4} + EXPECT_EQ(N4, N1->getOperand(0)); + EXPECT_EQ(N1, N4->getOperand(0)); + EXPECT_EQ(N1, N5->getOperand(0)); + EXPECT_EQ(N4, N6->getOperand(0)); +} + +TEST_F(MDNodeTest, replaceResolvedOperand) { + // Check code for replacing one resolved operand with another. If doing this + // directly (via replaceOperandWith()) becomes illegal, change the operand to + // a global value that gets RAUW'ed. + // + // Use a temporary node to keep N from being resolved. + std::unique_ptr Temp(MDNodeFwdDecl::get(Context, None)); + Metadata *Ops[] = {nullptr, Temp.get()}; + + MDNode *Empty = MDTuple::get(Context, ArrayRef()); + MDNode *N = MDTuple::get(Context, Ops); + EXPECT_EQ(nullptr, N->getOperand(0)); + ASSERT_FALSE(N->isResolved()); + + // Check code for replacing resolved nodes. + N->replaceOperandWith(0, Empty); + EXPECT_EQ(Empty, N->getOperand(0)); + + // Check code for adding another unresolved operand. + N->replaceOperandWith(0, Temp.get()); + EXPECT_EQ(Temp.get(), N->getOperand(0)); + + // Remove the references to Temp; required for teardown. + Temp->replaceAllUsesWith(nullptr); +} + +typedef MetadataTest MDLocationTest; + +TEST_F(MDLocationTest, Overflow) { + MDNode *N = MDNode::get(Context, None); + { + MDLocation *L = MDLocation::get(Context, 2, 7, N); + EXPECT_EQ(2u, L->getLine()); + EXPECT_EQ(7u, L->getColumn()); + } + unsigned U24 = 1u << 24; + unsigned U8 = 1u << 8; + { + MDLocation *L = MDLocation::get(Context, U24 - 1, U8 - 1, N); + EXPECT_EQ(U24 - 1, L->getLine()); + EXPECT_EQ(U8 - 1, L->getColumn()); + } + { + MDLocation *L = MDLocation::get(Context, U24, U8, N); + EXPECT_EQ(0u, L->getLine()); + EXPECT_EQ(0u, L->getColumn()); + } + { + MDLocation *L = MDLocation::get(Context, U24 + 1, U8 + 1, N); + EXPECT_EQ(0u, L->getLine()); + EXPECT_EQ(0u, L->getColumn()); + } +} + +TEST_F(MDLocationTest, getDistinct) { + MDNode *N = MDNode::get(Context, None); + MDLocation *L0 = MDLocation::getDistinct(Context, 2, 7, N); + EXPECT_TRUE(L0->isDistinct()); + MDLocation *L1 = MDLocation::get(Context, 2, 7, N); + EXPECT_FALSE(L1->isDistinct()); + EXPECT_EQ(L1, MDLocation::get(Context, 2, 7, N)); +} + +typedef MetadataTest MetadataAsValueTest; + +TEST_F(MetadataAsValueTest, MDNode) { + MDNode *N = MDNode::get(Context, None); + auto *V = MetadataAsValue::get(Context, N); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(N, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N); + EXPECT_EQ(V, V2); +} + +TEST_F(MetadataAsValueTest, MDNodeMDNode) { + MDNode *N = MDNode::get(Context, None); + Metadata *Ops[] = {N}; + MDNode *N2 = MDNode::get(Context, Ops); + auto *V = MetadataAsValue::get(Context, N2); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(N2, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N2); + EXPECT_EQ(V, V2); + + auto *V3 = MetadataAsValue::get(Context, N); + EXPECT_TRUE(V3->getType()->isMetadataTy()); + EXPECT_NE(V, V3); + EXPECT_EQ(N, V3->getMetadata()); +} + +TEST_F(MetadataAsValueTest, MDNodeConstant) { + auto *C = ConstantInt::getTrue(Context); + auto *MD = ConstantAsMetadata::get(C); + Metadata *Ops[] = {MD}; + auto *N = MDNode::get(Context, Ops); + + auto *V = MetadataAsValue::get(Context, MD); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(MD, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N); + EXPECT_EQ(MD, V2->getMetadata()); + EXPECT_EQ(V, V2); +} + +typedef MetadataTest ValueAsMetadataTest; + +TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr GV0( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + auto *MD = ValueAsMetadata::get(GV0.get()); + EXPECT_TRUE(MD->getValue() == GV0.get()); + ASSERT_TRUE(GV0->use_empty()); + + std::unique_ptr GV1( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + GV0->replaceAllUsesWith(GV1.get()); + EXPECT_TRUE(MD->getValue() == GV1.get()); +} + +TEST_F(ValueAsMetadataTest, CollidingDoubleUpdates) { + // Create a constant. + ConstantAsMetadata *CI = ConstantAsMetadata::get( + ConstantInt::get(getGlobalContext(), APInt(8, 0))); + + // Create a temporary to prevent nodes from resolving. + std::unique_ptr Temp(MDNode::getTemporary(Context, None)); + + // When the first operand of N1 gets reset to nullptr, it'll collide with N2. + Metadata *Ops1[] = {CI, CI, Temp.get()}; + Metadata *Ops2[] = {nullptr, CI, Temp.get()}; + + auto *N1 = MDTuple::get(Context, Ops1); + auto *N2 = MDTuple::get(Context, Ops2); + ASSERT_NE(N1, N2); + + // Tell metadata that the constant is getting deleted. + // + // After this, N1 will be invalid, so don't touch it. + ValueAsMetadata::handleDeletion(CI->getValue()); + EXPECT_EQ(nullptr, N2->getOperand(0)); + EXPECT_EQ(nullptr, N2->getOperand(1)); + EXPECT_EQ(Temp.get(), N2->getOperand(2)); + + // Clean up Temp for teardown. + Temp->replaceAllUsesWith(nullptr); +} + +typedef MetadataTest TrackingMDRefTest; + +TEST_F(TrackingMDRefTest, UpdatesOnRAUW) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr GV0( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + TypedTrackingMDRef MD(ValueAsMetadata::get(GV0.get())); + EXPECT_TRUE(MD->getValue() == GV0.get()); + ASSERT_TRUE(GV0->use_empty()); + + std::unique_ptr GV1( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + GV0->replaceAllUsesWith(GV1.get()); + EXPECT_TRUE(MD->getValue() == GV1.get()); + + // Reset it, so we don't inadvertently test deletion. + MD.reset(); +} + +TEST_F(TrackingMDRefTest, UpdatesOnDeletion) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr GV( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + TypedTrackingMDRef MD(ValueAsMetadata::get(GV.get())); + EXPECT_TRUE(MD->getValue() == GV.get()); + ASSERT_TRUE(GV->use_empty()); + + GV.reset(); + EXPECT_TRUE(!MD); +} + TEST(NamedMDNodeTest, Search) { LLVMContext Context; - Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 1); - Constant *C2 = ConstantInt::get(Type::getInt32Ty(Context), 2); + ConstantAsMetadata *C = + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 1)); + ConstantAsMetadata *C2 = + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 2)); - Value *const V = C; - Value *const V2 = C2; + Metadata *const V = C; + Metadata *const V2 = C2; MDNode *n = MDNode::get(Context, V); MDNode *n2 = MDNode::get(Context, V2); diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index 25037a7..41af0b0 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -29,13 +29,16 @@ public: /// \brief Returns an opaque, unique ID for this pass type. static void *ID() { return (void *)&PassID; } + /// \brief Returns the name of the analysis. + static StringRef name() { return "TestFunctionAnalysis"; } + TestFunctionAnalysis(int &Runs) : Runs(Runs) {} /// \brief Run the analysis pass over the function and return a result. - Result run(Function *F, FunctionAnalysisManager *AM) { + Result run(Function &F, FunctionAnalysisManager *AM) { ++Runs; int Count = 0; - for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI) + for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) ++Count; @@ -60,12 +63,14 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "TestModuleAnalysis"; } + TestModuleAnalysis(int &Runs) : Runs(Runs) {} - Result run(Module *M, ModuleAnalysisManager *AM) { + Result run(Module &M, ModuleAnalysisManager *AM) { ++Runs; int Count = 0; - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) ++Count; return Result(Count); } @@ -81,7 +86,7 @@ char TestModuleAnalysis::PassID; struct TestModulePass { TestModulePass(int &RunCount) : RunCount(RunCount) {} - PreservedAnalyses run(Module *M) { + PreservedAnalyses run(Module &M) { ++RunCount; return PreservedAnalyses::none(); } @@ -92,13 +97,13 @@ struct TestModulePass { }; struct TestPreservingModulePass { - PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); } static StringRef name() { return "TestPreservingModulePass"; } }; struct TestMinPreservingModulePass { - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { PreservedAnalyses PA; // Force running an analysis. @@ -119,13 +124,13 @@ struct TestFunctionPass { AnalyzedFunctionCount(AnalyzedFunctionCount), OnlyUseCachedResults(OnlyUseCachedResults) {} - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) { + PreservedAnalyses run(Function &F, FunctionAnalysisManager *AM) { ++RunCount; const ModuleAnalysisManager &MAM = AM->getResult(F).getManager(); if (TestModuleAnalysis::Result *TMA = - MAM.getCachedResult(F->getParent())) + MAM.getCachedResult(*F.getParent())) AnalyzedFunctionCount += TMA->FunctionCount; if (OnlyUseCachedResults) { @@ -155,9 +160,9 @@ struct TestFunctionPass { struct TestInvalidationFunctionPass { TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} - PreservedAnalyses run(Function *F) { - return F->getName() == Name ? PreservedAnalyses::none() - : PreservedAnalyses::all(); + PreservedAnalyses run(Function &F) { + return F.getName() == Name ? PreservedAnalyses::none() + : PreservedAnalyses::all(); } static StringRef name() { return "TestInvalidationFunctionPass"; } @@ -165,10 +170,10 @@ struct TestInvalidationFunctionPass { StringRef Name; }; -Module *parseIR(const char *IR) { +std::unique_ptr parseIR(const char *IR) { LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(IR, nullptr, Err, C); + return parseAssemblyString(IR, Err, C); } class PassManagerTest : public ::testing::Test { @@ -310,7 +315,7 @@ TEST_F(PassManagerTest, Basic) { MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - MPM.run(M.get(), &MAM); + MPM.run(*M, &MAM); // Validate module pass counters. EXPECT_EQ(1, ModulePassRunCount); diff --git a/unittests/IR/UseTest.cpp b/unittests/IR/UseTest.cpp new file mode 100644 index 0000000..b575a59 --- /dev/null +++ b/unittests/IR/UseTest.cpp @@ -0,0 +1,112 @@ +//===- llvm/unittest/IR/UseTest.cpp - Use unit tests ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/User.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(UseTest, sort) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x) {\n" + "entry:\n" + " %v0 = add i32 %x, 0\n" + " %v2 = add i32 %x, 2\n" + " %v5 = add i32 %x, 5\n" + " %v1 = add i32 %x, 1\n" + " %v3 = add i32 %x, 3\n" + " %v7 = add i32 %x, 7\n" + " %v6 = add i32 %x, 6\n" + " %v4 = add i32 %x, 4\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + char vnbuf[8]; + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); + Function *F = M->getFunction("f"); + ASSERT_TRUE(F); + ASSERT_TRUE(F->arg_begin() != F->arg_end()); + Argument &X = *F->arg_begin(); + ASSERT_EQ("x", X.getName()); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() < R.getUser()->getName(); + }); + unsigned I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() > R.getUser()->getName(); + }); + I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); +} + +TEST(UseTest, reverse) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x) {\n" + "entry:\n" + " %v0 = add i32 %x, 0\n" + " %v2 = add i32 %x, 2\n" + " %v5 = add i32 %x, 5\n" + " %v1 = add i32 %x, 1\n" + " %v3 = add i32 %x, 3\n" + " %v7 = add i32 %x, 7\n" + " %v6 = add i32 %x, 6\n" + " %v4 = add i32 %x, 4\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + char vnbuf[8]; + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); + Function *F = M->getFunction("f"); + ASSERT_TRUE(F); + ASSERT_TRUE(F->arg_begin() != F->arg_end()); + Argument &X = *F->arg_begin(); + ASSERT_EQ("x", X.getName()); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() < R.getUser()->getName(); + }); + unsigned I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); + + X.reverseUseList(); + I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); +} + +} // end anonymous namespace diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp index eb07e82..56b054b 100644 --- a/unittests/IR/UserTest.cpp +++ b/unittests/IR/UserTest.cpp @@ -9,10 +9,10 @@ #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/User.h" -#include "llvm/IR/Instructions.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; @@ -65,7 +65,7 @@ TEST(UserTest, ValueOpIteration) { " ret void\n" "}\n"; SMDiagnostic Err; - Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); Function *F = M->getFunction("f"); BasicBlock &ExitBB = F->back(); diff --git a/unittests/IR/ValueMapTest.cpp b/unittests/IR/ValueMapTest.cpp index 0b7198f..a6bad71 100644 --- a/unittests/IR/ValueMapTest.cpp +++ b/unittests/IR/ValueMapTest.cpp @@ -186,11 +186,11 @@ struct LockMutex : ValueMapConfig { }; static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) { *Data.CalledRAUW = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; + EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked."; } static void onDelete(const ExtraData &Data, KeyT Old) { *Data.CalledDeleted = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; + EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked."; } static MutexT *getMutex(const ExtraData &Data) { return Data.M; } }; diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp index 61e44a9..4dd0c2c 100644 --- a/unittests/IR/ValueTest.cpp +++ b/unittests/IR/ValueTest.cpp @@ -34,7 +34,7 @@ TEST(ValueTest, UsedInBasicBlock) { " ret void\n" "}\n"; SMDiagnostic Err; - Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); Function *F = M->getFunction("f"); @@ -60,6 +60,10 @@ TEST(GlobalTest, CreateAddressSpace) { GlobalVariable::NotThreadLocal, 1); + EXPECT_TRUE(Value::MaximumAlignment == 536870912U); + Dummy0->setAlignment(536870912U); + EXPECT_EQ(Dummy0->getAlignment(), 536870912U); + // Make sure the address space isn't dropped when returning this. Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty); EXPECT_EQ(Dummy0, Dummy1); @@ -83,4 +87,23 @@ TEST(GlobalTest, CreateAddressSpace) { EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace()); EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1; } + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(GlobalTest, AlignDeath) { + LLVMContext &Ctx = getGlobalContext(); + std::unique_ptr M(new Module("TestModule", Ctx)); + Type *Int32Ty = Type::getInt32Ty(Ctx); + GlobalVariable *Var = + new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage, + Constant::getAllOnesValue(Int32Ty), "var", nullptr, + GlobalVariable::NotThreadLocal, 1); + + EXPECT_DEATH(Var->setAlignment(536870913U), "Alignment is not a power of 2"); + EXPECT_DEATH(Var->setAlignment(1073741824U), + "Alignment is greater than MaximumAlignment"); +} +#endif +#endif + } // end anonymous namespace diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp index 8e3cd45..a8924ef 100644 --- a/unittests/IR/WaymarkTest.cpp +++ b/unittests/IR/WaymarkTest.cpp @@ -29,8 +29,9 @@ TEST(WaymarkTest, NativeArray) { Value * values[22]; std::transform(tail, tail + 22, values, char2constant); FunctionType *FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), true); - Function *F = Function::Create(FT, GlobalValue::ExternalLinkage); - const CallInst *A = CallInst::Create(F, makeArrayRef(values)); + std::unique_ptr F( + Function::Create(FT, GlobalValue::ExternalLinkage)); + const CallInst *A = CallInst::Create(F.get(), makeArrayRef(values)); ASSERT_NE(A, (const CallInst*)nullptr); ASSERT_EQ(1U + 22, A->getNumOperands()); const Use *U = &A->getOperandUse(0); diff --git a/unittests/LineEditor/CMakeLists.txt b/unittests/LineEditor/CMakeLists.txt index c6823d8..70d7497 100644 --- a/unittests/LineEditor/CMakeLists.txt +++ b/unittests/LineEditor/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS LineEditor + Support ) add_llvm_unittest(LineEditorTests diff --git a/unittests/Linker/CMakeLists.txt b/unittests/Linker/CMakeLists.txt index c3dccb6..05f45c0 100644 --- a/unittests/Linker/CMakeLists.txt +++ b/unittests/Linker/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + AsmParser core linker ) diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp index 4ccced1..91f97d7 100644 --- a/unittests/Linker/LinkModulesTest.cpp +++ b/unittests/Linker/LinkModulesTest.cpp @@ -7,12 +7,14 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Linker/Linker.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Linker/Linker.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; @@ -88,7 +90,7 @@ TEST_F(LinkModuleTest, BlockAddress) { Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); Module *LinkedModule = new Module("MyModuleLinked", Ctx); - Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, nullptr); + Linker::LinkModules(LinkedModule, M.get()); // Delete the original module. M.reset(); @@ -122,12 +124,13 @@ TEST_F(LinkModuleTest, BlockAddress) { delete LinkedModule; } -TEST_F(LinkModuleTest, EmptyModule) { +static Module *getInternal(LLVMContext &Ctx) { Module *InternalM = new Module("InternalModule", Ctx); FunctionType *FTy = FunctionType::get( Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/); - F = Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); + Function *F = + Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); F->setCallingConv(CallingConv::C); BasicBlock *BB = BasicBlock::Create(Ctx, "", F); @@ -141,16 +144,37 @@ TEST_F(LinkModuleTest, EmptyModule) { GlobalValue::InternalLinkage, nullptr, "g"); GV->setInitializer(ConstantStruct::get(STy, F)); + return InternalM; +} + +TEST_F(LinkModuleTest, EmptyModule) { + std::unique_ptr InternalM(getInternal(Ctx)); + std::unique_ptr EmptyM(new Module("EmptyModule1", Ctx)); + Linker::LinkModules(EmptyM.get(), InternalM.get()); +} + +TEST_F(LinkModuleTest, EmptyModule2) { + std::unique_ptr InternalM(getInternal(Ctx)); + std::unique_ptr EmptyM(new Module("EmptyModule1", Ctx)); + Linker::LinkModules(InternalM.get(), EmptyM.get()); +} + +TEST_F(LinkModuleTest, TypeMerge) { + LLVMContext C; + SMDiagnostic Err; + + const char *M1Str = "%t = type {i32}\n" + "@t1 = weak global %t zeroinitializer\n"; + std::unique_ptr M1 = parseAssemblyString(M1Str, Err, C); - Module *EmptyM = new Module("EmptyModule1", Ctx); - Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, nullptr); + const char *M2Str = "%t = type {i32}\n" + "@t2 = weak global %t zeroinitializer\n"; + std::unique_ptr M2 = parseAssemblyString(M2Str, Err, C); - delete EmptyM; - EmptyM = new Module("EmptyModule2", Ctx); - Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource, nullptr); + Linker::LinkModules(M1.get(), M2.get(), [](const llvm::DiagnosticInfo &){}); - delete EmptyM; - delete InternalM; + EXPECT_EQ(M1->getNamedGlobal("t1")->getType(), + M1->getNamedGlobal("t2")->getType()); } } // end anonymous namespace diff --git a/unittests/Linker/Makefile b/unittests/Linker/Makefile index c6058c4..ddbce07 100644 --- a/unittests/Linker/Makefile +++ b/unittests/Linker/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = Linker -LINK_COMPONENTS := core linker +LINK_COMPONENTS := core linker asmparser include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/CMakeLists.txt b/unittests/MC/CMakeLists.txt index 37543f4..f83eaf4 100644 --- a/unittests/MC/CMakeLists.txt +++ b/unittests/MC/CMakeLists.txt @@ -1,11 +1,12 @@ set(LLVM_LINK_COMPONENTS + ${LLVM_TARGETS_TO_BUILD} MC - MCAnalysis + MCDisassembler Support ) add_llvm_unittest(MCTests - MCAtomTest.cpp + Disassembler.cpp StringTableBuilderTest.cpp YAMLTest.cpp ) diff --git a/unittests/MC/Disassembler.cpp b/unittests/MC/Disassembler.cpp new file mode 100644 index 0000000..dd0f1ef --- /dev/null +++ b/unittests/MC/Disassembler.cpp @@ -0,0 +1,64 @@ +//===- llvm/unittest/Object/Disassembler.cpp ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Disassembler.h" +#include "llvm/Support/TargetSelect.h" +#include "gtest/gtest.h" + +using namespace llvm; + +static const char *symbolLookupCallback(void *DisInfo, uint64_t ReferenceValue, + uint64_t *ReferenceType, + uint64_t ReferencePC, + const char **ReferenceName) { + *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; + return nullptr; +} + +TEST(Disassembler, Test1) { + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllDisassemblers(); + + uint8_t Bytes[] = {0x90, 0x90, 0xeb, 0xfd}; + uint8_t *BytesP = Bytes; + const char OutStringSize = 100; + char OutString[OutStringSize]; + LLVMDisasmContextRef DCR = LLVMCreateDisasm("x86_64-pc-linux", nullptr, 0, + nullptr, symbolLookupCallback); + if (!DCR) + return; + + size_t InstSize; + unsigned NumBytes = sizeof(Bytes); + unsigned PC = 0; + + InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, + OutStringSize); + EXPECT_EQ(InstSize, 1U); + EXPECT_EQ(StringRef(OutString), "\tnop"); + PC += InstSize; + BytesP += InstSize; + NumBytes -= InstSize; + + InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, + OutStringSize); + EXPECT_EQ(InstSize, 1U); + EXPECT_EQ(StringRef(OutString), "\tnop"); + PC += InstSize; + BytesP += InstSize; + NumBytes -= InstSize; + + InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, + OutStringSize); + EXPECT_EQ(InstSize, 2U); + EXPECT_EQ(StringRef(OutString), "\tjmp\t0x1"); + + LLVMDisasmDispose(DCR); +} diff --git a/unittests/MC/MCAtomTest.cpp b/unittests/MC/MCAtomTest.cpp deleted file mode 100644 index 16228b5..0000000 --- a/unittests/MC/MCAtomTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- llvm/unittest/MC/MCAtomTest.cpp - Instructions unit tests ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "gtest/gtest.h" - -namespace llvm { -namespace { - -TEST(MCAtomTest, MCDataSize) { - MCModule M; - MCDataAtom *Atom = M.createDataAtom(0, 0); - EXPECT_EQ(uint64_t(0), Atom->getEndAddr()); - Atom->addData(0); - EXPECT_EQ(uint64_t(0), Atom->getEndAddr()); - Atom->addData(1); - EXPECT_EQ(uint64_t(1), Atom->getEndAddr()); - Atom->addData(2); - EXPECT_EQ(uint64_t(2), Atom->getEndAddr()); - EXPECT_EQ(size_t(3), Atom->getData().size()); -} - -} // end anonymous namespace -} // end namespace llvm diff --git a/unittests/MC/Makefile b/unittests/MC/Makefile index 07a608e..3f8d1ef 100644 --- a/unittests/MC/Makefile +++ b/unittests/MC/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = MC -LINK_COMPONENTS := MCAnalysis +LINK_COMPONENTS := all-targets MCDisassembler Object include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/StringTableBuilderTest.cpp b/unittests/MC/StringTableBuilderTest.cpp index d30dc62..716b9c7 100644 --- a/unittests/MC/StringTableBuilderTest.cpp +++ b/unittests/MC/StringTableBuilderTest.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/StringTableBuilder.h" +#include "llvm/Support/Endian.h" #include "gtest/gtest.h" #include @@ -15,14 +16,14 @@ using namespace llvm; namespace { -TEST(StringTableBuilderTest, Basic) { +TEST(StringTableBuilderTest, BasicELF) { StringTableBuilder B; B.add("foo"); B.add("bar"); B.add("foobar"); - B.finalize(); + B.finalize(StringTableBuilder::ELF); std::string Expected; Expected += '\x00'; @@ -37,4 +38,34 @@ TEST(StringTableBuilderTest, Basic) { EXPECT_EQ(8U, B.getOffset("foo")); } +TEST(StringTableBuilderTest, BasicWinCOFF) { + StringTableBuilder B; + + // Strings must be 9 chars or longer to go in the table. + B.add("hippopotamus"); + B.add("pygmy hippopotamus"); + B.add("river horse"); + + B.finalize(StringTableBuilder::WinCOFF); + + // size_field + "pygmy hippopotamus\0" + "river horse\0" + uint32_t ExpectedSize = 4 + 19 + 12; + EXPECT_EQ(ExpectedSize, B.data().size()); + + std::string Expected; + + ExpectedSize = + support::endian::byte_swap(ExpectedSize); + Expected.append((const char*)&ExpectedSize, 4); + Expected += "pygmy hippopotamus"; + Expected += '\x00'; + Expected += "river horse"; + Expected += '\x00'; + + EXPECT_EQ(Expected, B.data()); + EXPECT_EQ(4U, B.getOffset("pygmy hippopotamus")); + EXPECT_EQ(10U, B.getOffset("hippopotamus")); + EXPECT_EQ(23U, B.getOffset("river horse")); +} + } diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index 0fc84c7..7f15776 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -17,9 +17,9 @@ namespace { TEST(AllocatorTest, Basics) { BumpPtrAllocator Alloc; - int *a = (int*)Alloc.Allocate(sizeof(int), 0); - int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0); - int *c = (int*)Alloc.Allocate(sizeof(int), 0); + int *a = (int*)Alloc.Allocate(sizeof(int), 1); + int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 1); + int *c = (int*)Alloc.Allocate(sizeof(int), 1); *a = 1; b[0] = 2; b[9] = 2; @@ -49,11 +49,11 @@ TEST(AllocatorTest, Basics) { // Allocate enough bytes to create three slabs. TEST(AllocatorTest, ThreeSlabs) { BumpPtrAllocator Alloc; - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(3U, Alloc.GetNumSlabs()); } @@ -61,15 +61,15 @@ TEST(AllocatorTest, ThreeSlabs) { // again. TEST(AllocatorTest, TestReset) { BumpPtrAllocator Alloc; - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); Alloc.Reset(); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -99,11 +99,11 @@ TEST(AllocatorTest, TestOverflow) { BumpPtrAllocator Alloc; // Fill the slab right up until the end pointer. - Alloc.Allocate(4096, 0); + Alloc.Allocate(4096, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); // If we don't allocate a new slab, then we will have overflowed. - Alloc.Allocate(1, 0); + Alloc.Allocate(1, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -111,7 +111,20 @@ TEST(AllocatorTest, TestOverflow) { TEST(AllocatorTest, TestSmallSlabSize) { BumpPtrAllocator Alloc; - Alloc.Allocate(8000, 0); + Alloc.Allocate(8000, 1); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); +} + +// Test requesting alignment that goes past the end of the current slab. +TEST(AllocatorTest, TestAlignmentPastSlab) { + BumpPtrAllocator Alloc; + Alloc.Allocate(4095, 1); + + // Aligning the current slab pointer is likely to move it past the end of the + // slab, which would confuse any unsigned comparisons with the difference of + // the the end pointer and the aligned pointer. + Alloc.Allocate(1024, 8192); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -130,7 +143,7 @@ public: void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); // Find the slab start. - void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment); + void *Slab = (void *)alignAddr((char*)MemBase + sizeof(void *), Alignment); // Hold a pointer to the base so we can free the whole malloced block. ((void**)Slab)[-1] = MemBase; @@ -155,7 +168,7 @@ TEST(AllocatorTest, TestBigAlignment) { BumpPtrAllocatorImpl Alloc; // First allocate a tiny bit to ensure we have to re-align things. - (void)Alloc.Allocate(1, 0); + (void)Alloc.Allocate(1, 1); // Now the big chunk with a big alignment. (void)Alloc.Allocate(3000, 2048); diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 97c5c43..dd270cc 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -32,6 +32,7 @@ add_llvm_unittest(SupportTests ScaledNumberTest.cpp SourceMgrTest.cpp SpecialCaseListTest.cpp + StreamingMemoryObject.cpp StringPool.cpp SwapByteOrderTest.cpp ThreadLocalTest.cpp @@ -42,3 +43,8 @@ add_llvm_unittest(SupportTests formatted_raw_ostream_test.cpp raw_ostream_test.cpp ) + +# ManagedStatic.cpp uses . +if(LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD) + target_link_libraries(SupportTests pthread) +endif() diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp index 88c7d19a..3218189 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -232,3 +232,99 @@ namespace TemporaryCast { struct pod {}; IllegalCast *testIllegalCast() { return cast(pod()); } } + +namespace { +namespace pointer_wrappers { + +struct Base { + bool IsDerived; + Base(bool IsDerived = false) : IsDerived(IsDerived) {} +}; + +struct Derived : Base { + Derived() : Base(true) {} + static bool classof(const Base *B) { return B->IsDerived; } +}; + +class PTy { + Base *B; +public: + PTy(Base *B) : B(B) {} + LLVM_EXPLICIT operator bool() const { return get(); } + Base *get() const { return B; } +}; + +} // end namespace pointer_wrappers +} // end namespace + +namespace llvm { + +template <> struct simplify_type { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) { + return P.get(); + } +}; +template <> struct simplify_type { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) { + return P.get(); + } +}; + +} // end namespace llvm + +namespace { +namespace pointer_wrappers { + +// Some objects. +pointer_wrappers::Base B; +pointer_wrappers::Derived D; + +// Mutable "smart" pointers. +pointer_wrappers::PTy MN(nullptr); +pointer_wrappers::PTy MB(&B); +pointer_wrappers::PTy MD(&D); + +// Const "smart" pointers. +const pointer_wrappers::PTy CN(nullptr); +const pointer_wrappers::PTy CB(&B); +const pointer_wrappers::PTy CD(&D); + +TEST(CastingTest, smart_isa) { + EXPECT_TRUE(!isa(MB)); + EXPECT_TRUE(!isa(CB)); + EXPECT_TRUE(isa(MD)); + EXPECT_TRUE(isa(CD)); +} + +TEST(CastingTest, smart_cast) { + EXPECT_TRUE(cast(MD) == &D); + EXPECT_TRUE(cast(CD) == &D); +} + +TEST(CastingTest, smart_cast_or_null) { + EXPECT_TRUE(cast_or_null(MN) == nullptr); + EXPECT_TRUE(cast_or_null(CN) == nullptr); + EXPECT_TRUE(cast_or_null(MD) == &D); + EXPECT_TRUE(cast_or_null(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast) { + EXPECT_TRUE(dyn_cast(MB) == nullptr); + EXPECT_TRUE(dyn_cast(CB) == nullptr); + EXPECT_TRUE(dyn_cast(MD) == &D); + EXPECT_TRUE(dyn_cast(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast_or_null) { + EXPECT_TRUE(dyn_cast_or_null(MN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null(CN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null(MB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null(CB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null(MD) == &D); + EXPECT_TRUE(dyn_cast_or_null(CD) == &D); +} + +} // end namespace pointer_wrappers +} // end namespace diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index e4a1b67..ac8d3d8 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -153,14 +153,14 @@ class StrDupSaver : public cl::StringSaver { }; typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver, - SmallVectorImpl &NewArgv); - + SmallVectorImpl &NewArgv, + bool MarkEOLs); void testCommandLineTokenizer(ParserFunction *parse, const char *Input, const char *const Output[], size_t OutputSize) { SmallVector Actual; StrDupSaver Saver; - parse(Input, Saver, Actual); + parse(Input, Saver, Actual, /*MarkEOLs=*/false); EXPECT_EQ(OutputSize, Actual.size()); for (unsigned I = 0, E = Actual.size(); I != E; ++I) { if (I < OutputSize) diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp index 698ae3a..36b84d8 100644 --- a/unittests/Support/CompressionTest.cpp +++ b/unittests/Support/CompressionTest.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Compression.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include "gtest/gtest.h" diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 16c9beb..49748db 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -10,8 +10,8 @@ #include "llvm/Support/ConvertUTF.h" #include "gtest/gtest.h" #include -#include #include +#include using namespace llvm; @@ -39,30 +39,30 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) { TEST(ConvertUTFTest, OddLengthInput) { std::string Result; - bool Success = convertUTF16ToUTF8String(ArrayRef("xxxxx", 5), Result); + bool Success = convertUTF16ToUTF8String(makeArrayRef("xxxxx", 5), Result); EXPECT_FALSE(Success); } TEST(ConvertUTFTest, Empty) { std::string Result; - bool Success = convertUTF16ToUTF8String(ArrayRef(), Result); + bool Success = convertUTF16ToUTF8String(None, Result); EXPECT_TRUE(Success); EXPECT_TRUE(Result.empty()); } TEST(ConvertUTFTest, HasUTF16BOM) { - bool HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xff\xfe", 2)); + bool HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xff\xfe", 2)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe\xff", 2)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff", 2)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe\xff ", 3)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff ", 3)); EXPECT_TRUE(HasBOM); // Don't care about odd lengths. - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe\xff\x00asdf", 6)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff\x00asdf", 6)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef()); + HasBOM = hasUTF16ByteOrderMark(None); EXPECT_FALSE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe", 1)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe", 1)); EXPECT_FALSE(HasBOM); } @@ -141,8 +141,8 @@ CheckConvertUTF8ToUnicodeScalars(ConvertUTFResultContainer Expected, if (!Partial) std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsLenient(S); else - std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsPartialLenient(S); + if (Expected.ErrorCode != ErrorCode) return ::testing::AssertionFailure() << "Expected error code " << Expected.ErrorCode << ", actual " diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index d76e7d6..82bbe09 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -60,5 +60,36 @@ TEST(ErrorOr, Covariant) { ErrorOr > b1(ErrorOr >(nullptr)); b1 = ErrorOr >(nullptr); + + ErrorOr> b2(ErrorOr(nullptr)); + ErrorOr b3(nullptr); + ErrorOr> b4(b3); } + +// ErrorOr x(nullptr); +// ErrorOr> y = x; // invalid conversion +static_assert( + !std::is_convertible &, + ErrorOr>>::value, + "do not invoke explicit ctors in implicit conversion from lvalue"); + +// ErrorOr> y = ErrorOr(nullptr); // invalid +// // conversion +static_assert( + !std::is_convertible &&, + ErrorOr>>::value, + "do not invoke explicit ctors in implicit conversion from rvalue"); + +// ErrorOr x(nullptr); +// ErrorOr> y; +// y = x; // invalid conversion +static_assert(!std::is_assignable>, + const ErrorOr &>::value, + "do not invoke explicit ctors in assignment"); + +// ErrorOr> x; +// x = ErrorOr(nullptr); // invalid conversion +static_assert(!std::is_assignable>, + ErrorOr &&>::value, + "do not invoke explicit ctors in assignment"); } // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index b086f1e..c7e1006 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/FileOutputBuffer.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -65,9 +66,8 @@ TEST(FileOutputBuffer, Test) { // Do *not* commit buffer. } // Verify file does not exist (because buffer not committed). - bool Exists = false; - ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists)); - EXPECT_FALSE(Exists); + ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist), + errc::no_such_file_or_directory); ASSERT_NO_ERROR(fs::remove(File2.str())); // TEST 3: Verify sizing down case. @@ -80,14 +80,13 @@ TEST(FileOutputBuffer, Test) { memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); // Write to end of buffer to verify it is writable. memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20); - // Commit buffer, but size down to smaller size - ASSERT_NO_ERROR(Buffer->commit(5000)); + ASSERT_NO_ERROR(Buffer->commit()); } // Verify file is correct size. uint64_t File3Size; ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size)); - ASSERT_EQ(File3Size, 5000ULL); + ASSERT_EQ(File3Size, 8192000ULL); ASSERT_NO_ERROR(fs::remove(File3.str())); // TEST 4: Verify file can be made executable. diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp index b1ca13e..76b63e5 100644 --- a/unittests/Support/LEB128Test.cpp +++ b/unittests/Support/LEB128Test.cpp @@ -106,6 +106,7 @@ TEST(LEB128Test, DecodeULEB128) { EXPECT_DECODE_ULEB128_EQ(0xffu, "\xff\x01"); EXPECT_DECODE_ULEB128_EQ(0x100u, "\x80\x02"); EXPECT_DECODE_ULEB128_EQ(0x101u, "\x81\x02"); + EXPECT_DECODE_ULEB128_EQ(4294975616ULL, "\x80\xc1\x80\x80\x10"); // Decode ULEB128 with extra padding bytes EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x00"); @@ -118,6 +119,42 @@ TEST(LEB128Test, DecodeULEB128) { #undef EXPECT_DECODE_ULEB128_EQ } +TEST(LEB128Test, DecodeSLEB128) { +#define EXPECT_DECODE_SLEB128_EQ(EXPECTED, VALUE) \ + do { \ + unsigned ActualSize = 0; \ + int64_t Actual = decodeSLEB128(reinterpret_cast(VALUE), \ + &ActualSize); \ + EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \ + EXPECT_EQ(EXPECTED, Actual); \ + } while (0) + + // Decode SLEB128 + EXPECT_DECODE_SLEB128_EQ(0L, "\x00"); + EXPECT_DECODE_SLEB128_EQ(1L, "\x01"); + EXPECT_DECODE_SLEB128_EQ(63L, "\x3f"); + EXPECT_DECODE_SLEB128_EQ(-64L, "\x40"); + EXPECT_DECODE_SLEB128_EQ(-63L, "\x41"); + EXPECT_DECODE_SLEB128_EQ(-1L, "\x7f"); + EXPECT_DECODE_SLEB128_EQ(128L, "\x80\x01"); + EXPECT_DECODE_SLEB128_EQ(129L, "\x81\x01"); + EXPECT_DECODE_SLEB128_EQ(-129L, "\xff\x7e"); + EXPECT_DECODE_SLEB128_EQ(-128L, "\x80\x7f"); + EXPECT_DECODE_SLEB128_EQ(-127L, "\x81\x7f"); + EXPECT_DECODE_SLEB128_EQ(64L, "\xc0\x00"); + EXPECT_DECODE_SLEB128_EQ(-12345L, "\xc7\x9f\x7f"); + + // Decode unnormalized SLEB128 with extra padding bytes. + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x80\x00"); + +#undef EXPECT_DECODE_SLEB128_EQ +} + TEST(LEB128Test, SLEB128Size) { // Positive Value Testing Plan: // (1) 128 ^ n - 1 ........ need (n+1) bytes diff --git a/unittests/Support/LineIteratorTest.cpp b/unittests/Support/LineIteratorTest.cpp index 18f3fa9..67f9d97 100644 --- a/unittests/Support/LineIteratorTest.cpp +++ b/unittests/Support/LineIteratorTest.cpp @@ -17,9 +17,9 @@ using namespace llvm::sys; namespace { TEST(LineIteratorTest, Basic) { - std::unique_ptr Buffer(MemoryBuffer::getMemBuffer("line 1\n" - "line 2\n" - "line 3")); + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "line 3"); line_iterator I = line_iterator(*Buffer), E; @@ -40,15 +40,17 @@ TEST(LineIteratorTest, Basic) { EXPECT_EQ(E, I); } -TEST(LineIteratorTest, CommentSkipping) { +TEST(LineIteratorTest, CommentAndBlankSkipping) { std::unique_ptr Buffer( MemoryBuffer::getMemBuffer("line 1\n" "line 2\n" "# Comment 1\n" - "line 4\n" + "\n" + "line 5\n" + "\n" "# Comment 2")); - line_iterator I = line_iterator(*Buffer, '#'), E; + line_iterator I = line_iterator(*Buffer, true, '#'), E; EXPECT_FALSE(I.is_at_eof()); EXPECT_NE(E, I); @@ -59,20 +61,57 @@ TEST(LineIteratorTest, CommentSkipping) { EXPECT_EQ("line 2", *I); EXPECT_EQ(2, I.line_number()); ++I; - EXPECT_EQ("line 4", *I); - EXPECT_EQ(4, I.line_number()); + EXPECT_EQ("line 5", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, CommentSkippingKeepBlanks) { + std::unique_ptr Buffer( + MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "# Comment 1\n" + "# Comment 2\n" + "\n" + "line 6\n" + "\n" + "# Comment 3")); + + line_iterator I = line_iterator(*Buffer, false, '#'), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + EXPECT_EQ("line 6", *I); + EXPECT_EQ(6, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(7, I.line_number()); ++I; EXPECT_TRUE(I.is_at_eof()); EXPECT_EQ(E, I); } + TEST(LineIteratorTest, BlankSkipping) { - std::unique_ptr Buffer(MemoryBuffer::getMemBuffer("\n\n\n" - "line 1\n" - "\n\n\n" - "line 2\n" - "\n\n\n")); + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("\n\n\n" + "line 1\n" + "\n\n\n" + "line 2\n" + "\n\n\n"); line_iterator I = line_iterator(*Buffer), E; @@ -90,26 +129,65 @@ TEST(LineIteratorTest, BlankSkipping) { EXPECT_EQ(E, I); } +TEST(LineIteratorTest, BlankKeeping) { + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("\n\n" + "line 3\n" + "\n" + "line 5\n" + "\n\n"); + line_iterator I = line_iterator(*Buffer, false), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("line 3", *I); + EXPECT_EQ(3, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(4, I.line_number()); + ++I; + EXPECT_EQ("line 5", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(6, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(7, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + TEST(LineIteratorTest, EmptyBuffers) { - std::unique_ptr Buffer(MemoryBuffer::getMemBuffer("")); + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer(""); EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); + EXPECT_TRUE(line_iterator(*Buffer, false).is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, false)); - Buffer.reset(MemoryBuffer::getMemBuffer("\n\n\n")); + Buffer = MemoryBuffer::getMemBuffer("\n\n\n"); EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); - Buffer.reset(MemoryBuffer::getMemBuffer("# foo\n" - "\n" - "# bar")); - EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); - EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); - - Buffer.reset(MemoryBuffer::getMemBuffer("\n" - "# baz\n" - "\n")); - EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); - EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); + Buffer = MemoryBuffer::getMemBuffer("# foo\n" + "\n" + "# bar"); + EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#')); + + Buffer = MemoryBuffer::getMemBuffer("\n" + "# baz\n" + "\n"); + EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#')); } } // anonymous namespace diff --git a/unittests/Support/LockFileManagerTest.cpp b/unittests/Support/LockFileManagerTest.cpp index 885b7d6..efe3c308 100644 --- a/unittests/Support/LockFileManagerTest.cpp +++ b/unittests/Support/LockFileManagerTest.cpp @@ -95,7 +95,7 @@ TEST(LockFileManagerTest, RelativePath) { char PathBuf[1024]; const char *OrigPath = getcwd(PathBuf, 1024); - chdir(TmpDir.c_str()); + ASSERT_FALSE(chdir(TmpDir.c_str())); sys::fs::create_directory("inner"); SmallString<64> LockedFile("inner"); @@ -118,7 +118,7 @@ TEST(LockFileManagerTest, RelativePath) { EC = sys::fs::remove("inner"); ASSERT_FALSE(EC); - chdir(OrigPath); + ASSERT_FALSE(chdir(OrigPath)); EC = sys::fs::remove(StringRef(TmpDir)); ASSERT_FALSE(EC); diff --git a/unittests/Support/MD5Test.cpp b/unittests/Support/MD5Test.cpp index 7c1331b..c4fa5cd 100644 --- a/unittests/Support/MD5Test.cpp +++ b/unittests/Support/MD5Test.cpp @@ -41,19 +41,19 @@ void TestMD5Sum(StringRef Input, StringRef Final) { } TEST(MD5Test, MD5) { - TestMD5Sum(ArrayRef((const uint8_t *)"", (size_t) 0), + TestMD5Sum(makeArrayRef((const uint8_t *)"", (size_t) 0), "d41d8cd98f00b204e9800998ecf8427e"); - TestMD5Sum(ArrayRef((const uint8_t *)"a", (size_t) 1), + TestMD5Sum(makeArrayRef((const uint8_t *)"a", (size_t) 1), "0cc175b9c0f1b6a831c399e269772661"); - TestMD5Sum(ArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", - (size_t) 26), + TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", + (size_t) 26), "c3fcd3d76192e4007dfb496cca67e13b"); - TestMD5Sum(ArrayRef((const uint8_t *)"\0", (size_t) 1), + TestMD5Sum(makeArrayRef((const uint8_t *)"\0", (size_t) 1), "93b885adfe0da089cdf634904fd59f71"); - TestMD5Sum(ArrayRef((const uint8_t *)"a\0", (size_t) 2), + TestMD5Sum(makeArrayRef((const uint8_t *)"a\0", (size_t) 2), "4144e195f46de78a3623da7364d04f11"); - TestMD5Sum(ArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", - (size_t) 27), + TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", + (size_t) 27), "81948d1f1554f58cd1a56ebb01f808cb"); TestMD5Sum("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); } diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 93bf301..1cdd6ad 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -169,4 +169,54 @@ TEST_F(MemoryBufferTest, getOpenFileReopened) { testGetOpenFileSlice(true); } + +TEST_F(MemoryBufferTest, slice) { + // Create a file that is six pages long with different data on each page. + int FD; + SmallString<64> TestPath; + sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath); + raw_fd_ostream OF(FD, true, /*unbuffered=*/true); + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "12345678"; + } + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "abcdefgh"; + } + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "ABCDEFGH"; + } + OF.close(); + + // Try offset of one page. + ErrorOr MB = MemoryBuffer::getFileSlice(TestPath.str(), + 0x4000, 0x1000); + std::error_code EC = MB.getError(); + ASSERT_FALSE(EC); + EXPECT_EQ(0x4000UL, MB.get()->getBufferSize()); + + StringRef BufData = MB.get()->getBuffer(); + EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678")); + EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678")); + EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh")); + EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh")); + EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH")); + EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH")); + + // Try non-page aligned. + ErrorOr MB2 = MemoryBuffer::getFileSlice(TestPath.str(), + 0x3000, 0x0800); + EC = MB2.getError(); + ASSERT_FALSE(EC); + EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize()); + + StringRef BufData2 = MB2.get()->getBuffer(); + EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678")); + EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678")); + EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh")); + EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh")); + +} + + + } diff --git a/unittests/Support/MemoryTest.cpp b/unittests/Support/MemoryTest.cpp index 8ad90e0..f439cb2 100644 --- a/unittests/Support/MemoryTest.cpp +++ b/unittests/Support/MemoryTest.cpp @@ -21,7 +21,7 @@ class MappedMemoryTest : public ::testing::TestWithParam { public: MappedMemoryTest() { Flags = GetParam(); - PageSize = sys::process::get_self()->page_size(); + PageSize = sys::Process::getPageSize(); } protected: diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index db85347..0d661c8 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -16,6 +16,7 @@ #include "gtest/gtest.h" #ifdef LLVM_ON_WIN32 +#include #include #endif @@ -141,7 +142,7 @@ TEST(Support, Path) { StringRef filename(temp_store.begin(), temp_store.size()), stem, ext; stem = path::stem(filename); ext = path::extension(filename); - EXPECT_EQ(*(--sys::path::end(filename)), (stem + ext).str()); + EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str()); path::native(*i, temp_store); } @@ -227,7 +228,7 @@ TEST(Support, AbsolutePathIteratorEnd) { #endif for (StringRef Path : Paths) { - StringRef LastComponent = *--path::end(Path); + StringRef LastComponent = *path::rbegin(Path); EXPECT_EQ(".", LastComponent); } @@ -239,7 +240,7 @@ TEST(Support, AbsolutePathIteratorEnd) { #endif for (StringRef Path : RootPaths) { - StringRef LastComponent = *--path::end(Path); + StringRef LastComponent = *path::rbegin(Path); EXPECT_EQ(1u, LastComponent.size()); EXPECT_TRUE(path::is_separator(LastComponent[0])); } @@ -261,7 +262,7 @@ TEST(Support, HomeDirectory) { class FileSystemTest : public testing::Test { protected: /// Unique temporary directory in which all created filesystem entities must - /// be placed. It is recursively removed at the end of each test. + /// be placed. It is removed at the end of each test (must be empty). SmallString<128> TestDirectory; virtual void SetUp() { @@ -334,9 +335,7 @@ TEST_F(FileSystemTest, TempFiles) { fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); // Make sure it exists. - bool TempFileExists; - ASSERT_NO_ERROR(sys::fs::exists(Twine(TempPath), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); // Create another temp tile. int FD2; @@ -363,8 +362,8 @@ TEST_F(FileSystemTest, TempFiles) { EXPECT_EQ(B.type(), fs::file_type::file_not_found); // Make sure Temp2 doesn't exist. - ASSERT_NO_ERROR(fs::exists(Twine(TempPath2), TempFileExists)); - EXPECT_FALSE(TempFileExists); + ASSERT_EQ(fs::access(Twine(TempPath2), sys::fs::AccessMode::Exist), + errc::no_such_file_or_directory); SmallString<64> TempPath3; ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3)); @@ -387,8 +386,8 @@ TEST_F(FileSystemTest, TempFiles) { ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); // Make sure Temp1 doesn't exist. - ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); - EXPECT_FALSE(TempFileExists); + ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist), + errc::no_such_file_or_directory); #ifdef LLVM_ON_WIN32 // Path name > 260 chars should get an error. @@ -398,8 +397,16 @@ TEST_F(FileSystemTest, TempFiles) { "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; - EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath), - errc::no_such_file_or_directory); + EXPECT_EQ(fs::createUniqueFile(Path270, FileDescriptor, TempPath), + errc::invalid_argument); + // Relative path < 247 chars, no problem. + const char *Path216 = + "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" + "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" + "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" + "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; + ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath)); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); #endif } @@ -409,6 +416,54 @@ TEST_F(FileSystemTest, CreateDir) { ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), errc::file_exists); ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); + +#ifdef LLVM_ON_WIN32 + // Prove that create_directories() can handle a pathname > 248 characters, + // which is the documented limit for CreateDirectory(). + // (248 is MAX_PATH subtracting room for an 8.3 filename.) + // Generate a directory path guaranteed to fall into that range. + size_t TmpLen = TestDirectory.size(); + const char *OneDir = "\\123456789"; + size_t OneDirLen = strlen(OneDir); + ASSERT_LT(OneDirLen, 12U); + size_t NLevels = ((248 - TmpLen) / OneDirLen) + 1; + SmallString<260> LongDir(TestDirectory); + for (size_t I = 0; I < NLevels; ++I) + LongDir.append(OneDir); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_EQ(fs::create_directories(Twine(LongDir), false), + errc::file_exists); + // Tidy up, "recursively" removing the directories. + StringRef ThisDir(LongDir); + for (size_t J = 0; J < NLevels; ++J) { + ASSERT_NO_ERROR(fs::remove(ThisDir)); + ThisDir = path::parent_path(ThisDir); + } + + // Similarly for a relative pathname. Need to set the current directory to + // TestDirectory so that the one we create ends up in the right place. + char PreviousDir[260]; + size_t PreviousDirLen = ::GetCurrentDirectoryA(260, PreviousDir); + ASSERT_GT(PreviousDirLen, 0U); + ASSERT_LT(PreviousDirLen, 260U); + ASSERT_NE(::SetCurrentDirectoryA(TestDirectory.c_str()), 0); + LongDir.clear(); + // Generate a relative directory name with absolute length > 248. + size_t LongDirLen = 249 - TestDirectory.size(); + LongDir.assign(LongDirLen, 'a'); + ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir))); + // While we're here, prove that .. and . handling works in these long paths. + const char *DotDotDirs = "\\..\\.\\b"; + LongDir.append(DotDotDirs); + ASSERT_NO_ERROR(fs::create_directory("b")); + ASSERT_EQ(fs::create_directory(Twine(LongDir), false), errc::file_exists); + // And clean up. + ASSERT_NO_ERROR(fs::remove("b")); + ASSERT_NO_ERROR(fs::remove( + Twine(LongDir.substr(0, LongDir.size() - strlen(DotDotDirs))))); + ASSERT_NE(::SetCurrentDirectoryA(PreviousDir), 0); +#endif } TEST_F(FileSystemTest, DirectoryIteration) { @@ -485,6 +540,8 @@ TEST_F(FileSystemTest, DirectoryIteration) { const char archive[] = "!\x0A"; const char bitcode[] = "\xde\xc0\x17\x0b"; const char coff_object[] = "\x00\x00......"; +const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......" + "\xc7\xa1\xba\xd1\xee\xba\xa9\x4b\xaf\x20\xfa\xf6\x6a\xa4\xdc\xb8"; const char coff_import_library[] = "\x00\x00\xff\xff...."; const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; @@ -501,6 +558,8 @@ const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07"; const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08"; const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a"; const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff"; +const char macho_dynamically_linked_shared_lib_stub[] = + "\xfe\xed\xfa\xce..........\x00\x09"; TEST_F(FileSystemTest, Magic) { struct type { @@ -514,6 +573,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(archive), DEFINE(bitcode), DEFINE(coff_object), + { "coff_bigobj", coff_bigobj, sizeof(coff_bigobj), fs::file_magic::coff_object }, DEFINE(coff_import_library), DEFINE(elf_relocatable), DEFINE(macho_universal_binary), @@ -525,6 +585,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(macho_dynamically_linked_shared_lib), DEFINE(macho_dynamic_linker), DEFINE(macho_bundle), + DEFINE(macho_dynamically_linked_shared_lib_stub), DEFINE(macho_dsym_companion), DEFINE(windows_resource) #undef DEFINE @@ -535,8 +596,8 @@ TEST_F(FileSystemTest, Magic) { ++i) { SmallString<128> file_pathname(TestDirectory); path::append(file_pathname, i->filename); - std::string ErrMsg; - raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_None); + std::error_code EC; + raw_fd_ostream file(file_pathname, EC, sys::fs::F_None); ASSERT_FALSE(file.has_error()); StringRef magic(i->magic_str, i->magic_str_len); file << magic; @@ -549,27 +610,27 @@ TEST_F(FileSystemTest, Magic) { #ifdef LLVM_ON_WIN32 TEST_F(FileSystemTest, CarriageReturn) { SmallString<128> FilePathname(TestDirectory); - std::string ErrMsg; + std::error_code EC; path::append(FilePathname, "test"); { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Text); - EXPECT_EQ(ErrMsg, ""); + raw_fd_ostream File(FilePathname, EC, sys::fs::F_Text); + ASSERT_NO_ERROR(EC); File << '\n'; } { - auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + auto Buf = MemoryBuffer::getFile(FilePathname.str()); EXPECT_TRUE((bool)Buf); EXPECT_EQ(Buf.get()->getBuffer(), "\r\n"); } { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_None); - EXPECT_EQ(ErrMsg, ""); + raw_fd_ostream File(FilePathname, EC, sys::fs::F_None); + ASSERT_NO_ERROR(EC); File << '\n'; } { - auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + auto Buf = MemoryBuffer::getFile(FilePathname.str()); EXPECT_TRUE((bool)Buf); EXPECT_EQ(Buf.get()->getBuffer(), "\n"); } @@ -577,22 +638,31 @@ TEST_F(FileSystemTest, CarriageReturn) { } #endif +TEST_F(FileSystemTest, Resize) { + int FD; + SmallString<64> TempPath; + ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); + ASSERT_NO_ERROR(fs::resize_file(FD, 123)); + fs::file_status Status; + ASSERT_NO_ERROR(fs::status(FD, Status)); + ASSERT_EQ(Status.getSize(), 123U); +} + TEST_F(FileSystemTest, FileMapping) { // Create a temp file. int FileDescriptor; SmallString<64> TempPath; ASSERT_NO_ERROR( fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + unsigned Size = 4096; + ASSERT_NO_ERROR(fs::resize_file(FileDescriptor, Size)); + // Map in temp file and add some content std::error_code EC; StringRef Val("hello there"); { fs::mapped_file_region mfr(FileDescriptor, - true, - fs::mapped_file_region::readwrite, - 4096, - 0, - EC); + fs::mapped_file_region::readwrite, Size, 0, EC); ASSERT_NO_ERROR(EC); std::copy(Val.begin(), Val.end(), mfr.data()); // Explicitly add a 0. @@ -601,27 +671,19 @@ TEST_F(FileSystemTest, FileMapping) { } // Map it back in read-only - fs::mapped_file_region mfr(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + int FD; + EC = fs::openFileForRead(Twine(TempPath), FD); + ASSERT_NO_ERROR(EC); + fs::mapped_file_region mfr(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); // Verify content EXPECT_EQ(StringRef(mfr.const_data()), Val); // Unmap temp file - - fs::mapped_file_region m(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + fs::mapped_file_region m(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); - const char *Data = m.const_data(); - fs::mapped_file_region mfrrv(std::move(m)); - EXPECT_EQ(mfrrv.const_data(), Data); + ASSERT_EQ(close(FD), 0); } TEST(Support, NormalizePath) { @@ -640,22 +702,22 @@ TEST(Support, NormalizePath) { SmallString<64> Path5("\\a"); SmallString<64> Path6("a\\"); - ASSERT_NO_ERROR(fs::normalize_separators(Path1)); + path::native(Path1); EXPECT_PATH_IS(Path1, "a", "a"); - ASSERT_NO_ERROR(fs::normalize_separators(Path2)); - EXPECT_PATH_IS(Path2, "a/b", "a/b"); + path::native(Path2); + EXPECT_PATH_IS(Path2, "a\\b", "a/b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path3)); + path::native(Path3); EXPECT_PATH_IS(Path3, "a\\b", "a/b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path4)); + path::native(Path4); EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path5)); + path::native(Path5); EXPECT_PATH_IS(Path5, "\\a", "/a"); - ASSERT_NO_ERROR(fs::normalize_separators(Path6)); + path::native(Path6); EXPECT_PATH_IS(Path6, "a\\", "a/"); #undef EXPECT_PATH_IS diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index f406072..298a0a3 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -19,26 +19,6 @@ namespace { using namespace llvm; using namespace sys; -TEST(ProcessTest, SelfProcess) { - EXPECT_TRUE(process::get_self()); - EXPECT_EQ(process::get_self(), process::get_self()); - -#if defined(LLVM_ON_UNIX) - EXPECT_EQ(getpid(), process::get_self()->get_id()); -#elif defined(LLVM_ON_WIN32) - EXPECT_EQ(GetCurrentProcessId(), process::get_self()->get_id()); -#endif - - EXPECT_LT(1u, process::get_self()->page_size()); - - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_user_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_user_time()); - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_system_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_system_time()); - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_wall_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time()); -} - TEST(ProcessTest, GetRandomNumberTest) { const unsigned r1 = Process::GetRandomNumber(); const unsigned r2 = Process::GetRandomNumber(); diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 4e7316f..0feed47 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -34,6 +34,16 @@ void sleep_for(unsigned int seconds) { #error sleep_for is not implemented on your platform. #endif +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + SmallString<128> MessageStorage; \ + raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } // From TestMain.cpp. extern const char *TestMainArgv0; @@ -60,6 +70,56 @@ static void CopyEnvironment(std::vector &out) { } } +#ifdef LLVM_ON_WIN32 +TEST(ProgramTest, CreateProcessLongPath) { + if (getenv("LLVM_PROGRAM_TEST_LONG_PATH")) + exit(0); + + // getMainExecutable returns an absolute path; prepend the long-path prefix. + std::string MyAbsExe = + sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); + std::string MyExe; + if (!StringRef(MyAbsExe).startswith("\\\\?\\")) + MyExe.append("\\\\?\\"); + MyExe.append(MyAbsExe); + + const char *ArgV[] = { + MyExe.c_str(), + "--gtest_filter=ProgramTest.CreateProcessLongPath", + nullptr + }; + + // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child. + std::vector EnvP; + CopyEnvironment(EnvP); + EnvP.push_back("LLVM_PROGRAM_TEST_LONG_PATH=1"); + EnvP.push_back(nullptr); + + // Redirect stdout to a long path. + SmallString<128> TestDirectory; + ASSERT_NO_ERROR( + fs::createUniqueDirectory("program-redirect-test", TestDirectory)); + SmallString<256> LongPath(TestDirectory); + LongPath.push_back('\\'); + // MAX_PATH = 260 + LongPath.append(260 - TestDirectory.size(), 'a'); + StringRef LongPathRef(LongPath); + + std::string Error; + bool ExecutionFailed; + const StringRef *Redirects[] = { nullptr, &LongPathRef, nullptr }; + int RC = ExecuteAndWait(MyExe, ArgV, &EnvP[0], Redirects, + /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &Error, + &ExecutionFailed); + EXPECT_FALSE(ExecutionFailed) << Error; + EXPECT_EQ(0, RC); + + // Remove the long stdout. + ASSERT_NO_ERROR(fs::remove(Twine(LongPath))); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory))); +} +#endif + TEST(ProgramTest, CreateProcessTrailingSlash) { if (getenv("LLVM_PROGRAM_TEST_CHILD")) { if (ProgramTestStringArg1 == "has\\\\ trailing\\" && @@ -220,4 +280,44 @@ TEST(ProgramTest, TestExecuteNegative) { } +#ifdef LLVM_ON_WIN32 +const char utf16le_text[] = + "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; +const char utf16be_text[] = + "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; +#endif +const char utf8_text[] = "\x6c\x69\x6e\x67\xc3\xbc\x69\xc3\xa7\x61"; + +TEST(ProgramTest, TestWriteWithSystemEncoding) { + SmallString<128> TestDirectory; + ASSERT_NO_ERROR(fs::createUniqueDirectory("program-test", TestDirectory)); + errs() << "Test Directory: " << TestDirectory << '\n'; + errs().flush(); + SmallString<128> file_pathname(TestDirectory); + path::append(file_pathname, "international-file.txt"); + // Only on Windows we should encode in UTF16. For other systems, use UTF8 + ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text, + sys::WEM_UTF16)); + int fd = 0; + ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); +#if defined(LLVM_ON_WIN32) + char buf[18]; + ASSERT_EQ(::read(fd, buf, 18), 18); + if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE + ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); + } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE + ASSERT_EQ(strncmp(&buf[2], utf16le_text, 16), 0); + } else { + FAIL() << "Invalid BOM in UTF-16 file"; + } +#else + char buf[10]; + ASSERT_EQ(::read(fd, buf, 10), 10); + ASSERT_EQ(strncmp(buf, utf8_text, 10), 0); +#endif + ::close(fd); + ASSERT_NO_ERROR(fs::remove(file_pathname.str())); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} + } // end anonymous namespace diff --git a/unittests/Support/ScaledNumberTest.cpp b/unittests/Support/ScaledNumberTest.cpp index 7bbef7e..d8d6e31 100644 --- a/unittests/Support/ScaledNumberTest.cpp +++ b/unittests/Support/ScaledNumberTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ScaledNumber.h" - #include "llvm/Support/DataTypes.h" #include "gtest/gtest.h" diff --git a/unittests/Support/SourceMgrTest.cpp b/unittests/Support/SourceMgrTest.cpp index 2b69fe9..79c2d72 100644 --- a/unittests/Support/SourceMgrTest.cpp +++ b/unittests/Support/SourceMgrTest.cpp @@ -23,8 +23,9 @@ public: std::string Output; void setMainBuffer(StringRef Text, StringRef BufferName) { - MemoryBuffer *MainBuffer = MemoryBuffer::getMemBuffer(Text, BufferName); - MainBufferID = SM.AddNewSourceBuffer(MainBuffer, llvm::SMLoc()); + std::unique_ptr MainBuffer = + MemoryBuffer::getMemBuffer(Text, BufferName); + MainBufferID = SM.AddNewSourceBuffer(std::move(MainBuffer), llvm::SMLoc()); } SMLoc getLoc(unsigned Offset) { diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp index bb9c351..740dbfe 100644 --- a/unittests/Support/SpecialCaseListTest.cpp +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -17,14 +17,15 @@ namespace { class SpecialCaseListTest : public ::testing::Test { protected: - SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { - std::unique_ptr MB(MemoryBuffer::getMemBuffer(List)); + std::unique_ptr makeSpecialCaseList(StringRef List, + std::string &Error) { + std::unique_ptr MB = MemoryBuffer::getMemBuffer(List); return SpecialCaseList::create(MB.get(), Error); } - SpecialCaseList *makeSpecialCaseList(StringRef List) { + std::unique_ptr makeSpecialCaseList(StringRef List) { std::string Error; - SpecialCaseList *SCL = makeSpecialCaseList(List, Error); + auto SCL = makeSpecialCaseList(List, Error); assert(SCL); assert(Error == ""); return SCL; @@ -32,13 +33,13 @@ protected: }; TEST_F(SpecialCaseListTest, Basic) { - std::unique_ptr SCL( + std::unique_ptr SCL = makeSpecialCaseList("# This is a comment.\n" "\n" "src:hello\n" "src:bye\n" "src:hi=category\n" - "src:z*=category\n")); + "src:z*=category\n"); EXPECT_TRUE(SCL->inSection("src", "hello")); EXPECT_TRUE(SCL->inSection("src", "bye")); EXPECT_TRUE(SCL->inSection("src", "hi", "category")); @@ -48,39 +49,21 @@ TEST_F(SpecialCaseListTest, Basic) { EXPECT_FALSE(SCL->inSection("src", "hello", "category")); } -TEST_F(SpecialCaseListTest, GlobalInitCompat) { - std::unique_ptr SCL( - makeSpecialCaseList("global:foo=init\n")); +TEST_F(SpecialCaseListTest, GlobalInit) { + std::unique_ptr SCL = + makeSpecialCaseList("global:foo=init\n"); EXPECT_FALSE(SCL->inSection("global", "foo")); EXPECT_FALSE(SCL->inSection("global", "bar")); EXPECT_TRUE(SCL->inSection("global", "foo", "init")); EXPECT_FALSE(SCL->inSection("global", "bar", "init")); - SCL.reset(makeSpecialCaseList("global-init:foo\n")); - EXPECT_FALSE(SCL->inSection("global", "foo")); - EXPECT_FALSE(SCL->inSection("global", "bar")); - EXPECT_TRUE(SCL->inSection("global", "foo", "init")); - EXPECT_FALSE(SCL->inSection("global", "bar", "init")); - - SCL.reset(makeSpecialCaseList("type:t2=init\n")); + SCL = makeSpecialCaseList("type:t2=init\n"); EXPECT_FALSE(SCL->inSection("type", "t1")); EXPECT_FALSE(SCL->inSection("type", "t2")); EXPECT_FALSE(SCL->inSection("type", "t1", "init")); EXPECT_TRUE(SCL->inSection("type", "t2", "init")); - SCL.reset(makeSpecialCaseList("global-init-type:t2\n")); - EXPECT_FALSE(SCL->inSection("type", "t1")); - EXPECT_FALSE(SCL->inSection("type", "t2")); - EXPECT_FALSE(SCL->inSection("type", "t1", "init")); - EXPECT_TRUE(SCL->inSection("type", "t2", "init")); - - SCL.reset(makeSpecialCaseList("src:hello=init\n")); - EXPECT_FALSE(SCL->inSection("src", "hello")); - EXPECT_FALSE(SCL->inSection("src", "bye")); - EXPECT_TRUE(SCL->inSection("src", "hello", "init")); - EXPECT_FALSE(SCL->inSection("src", "bye", "init")); - - SCL.reset(makeSpecialCaseList("global-init-src:hello\n")); + SCL = makeSpecialCaseList("src:hello=init\n"); EXPECT_FALSE(SCL->inSection("src", "hello")); EXPECT_FALSE(SCL->inSection("src", "bye")); EXPECT_TRUE(SCL->inSection("src", "hello", "init")); @@ -88,14 +71,14 @@ TEST_F(SpecialCaseListTest, GlobalInitCompat) { } TEST_F(SpecialCaseListTest, Substring) { - std::unique_ptr SCL(makeSpecialCaseList("src:hello\n" - "fun:foo\n" - "global:bar\n")); + std::unique_ptr SCL = makeSpecialCaseList("src:hello\n" + "fun:foo\n" + "global:bar\n"); EXPECT_FALSE(SCL->inSection("src", "othello")); EXPECT_FALSE(SCL->inSection("fun", "tomfoolery")); EXPECT_FALSE(SCL->inSection("global", "bartender")); - SCL.reset(makeSpecialCaseList("fun:*foo*\n")); + SCL = makeSpecialCaseList("fun:*foo*\n"); EXPECT_TRUE(SCL->inSection("fun", "tomfoolery")); EXPECT_TRUE(SCL->inSection("fun", "foobar")); } @@ -117,7 +100,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { } TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { - std::unique_ptr SCL(makeSpecialCaseList("")); + std::unique_ptr SCL = makeSpecialCaseList(""); EXPECT_FALSE(SCL->inSection("foo", "bar")); } diff --git a/unittests/Support/StreamingMemoryObject.cpp b/unittests/Support/StreamingMemoryObject.cpp new file mode 100644 index 0000000..2013649 --- /dev/null +++ b/unittests/Support/StreamingMemoryObject.cpp @@ -0,0 +1,29 @@ +//===- llvm/unittest/Support/StreamingMemoryObject.cpp - unit tests -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/StreamingMemoryObject.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; + +namespace { +class NullDataStreamer : public DataStreamer { + size_t GetBytes(unsigned char *buf, size_t len) override { + memset(buf, 0, len); + return len; + } +}; +} + +TEST(StreamingMemoryObject, Test) { + auto *DS = new NullDataStreamer(); + StreamingMemoryObject O(DS); + EXPECT_TRUE(O.isValidAddress(32 * 1024)); +} diff --git a/unittests/Support/StringPool.cpp b/unittests/Support/StringPool.cpp index 7b7805f..ac39fec 100644 --- a/unittests/Support/StringPool.cpp +++ b/unittests/Support/StringPool.cpp @@ -1,6 +1,6 @@ -//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +//===- llvm/unittest/Support/StringPoiil.cpp - StringPool tests -----------===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. diff --git a/unittests/Support/ThreadLocalTest.cpp b/unittests/Support/ThreadLocalTest.cpp index ea751be..e71c7db 100644 --- a/unittests/Support/ThreadLocalTest.cpp +++ b/unittests/Support/ThreadLocalTest.cpp @@ -1,6 +1,6 @@ -//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +//===- llvm/unittest/Support/ThreadLocalTest.cpp - ThreadLocal tests ------===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. @@ -9,6 +9,7 @@ #include "llvm/Support/ThreadLocal.h" #include "gtest/gtest.h" +#include using namespace llvm; using namespace sys; @@ -25,6 +26,10 @@ struct S { TEST_F(ThreadLocalTest, Basics) { ThreadLocal x; + static_assert( + std::is_const::type>::value, + "ThreadLocal::get didn't return a pointer to const object"); + EXPECT_EQ(nullptr, x.get()); S s; @@ -33,6 +38,20 @@ TEST_F(ThreadLocalTest, Basics) { x.erase(); EXPECT_EQ(nullptr, x.get()); + + ThreadLocal y; + + static_assert( + !std::is_const::type>::value, + "ThreadLocal::get returned a pointer to const object"); + + EXPECT_EQ(nullptr, y.get()); + + y.set(&s); + EXPECT_EQ(&s, y.get()); + + y.erase(); + EXPECT_EQ(nullptr, y.get()); } } diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 8aed980..074e27f 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -84,6 +84,13 @@ TEST(YAMLIO, TestMapRead) { } } +TEST(YAMLIO, TestMalformedMapRead) { + FooBar doc; + Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages); + yin >> doc; + EXPECT_TRUE(!!yin.error()); +} + // // Test the reading of a yaml sequence of mappings // diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index e983935..823a0d6 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -18,7 +18,7 @@ namespace llvm { static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) { - // Prevent SourceMgr from writing errors to stderr + // Prevent SourceMgr from writing errors to stderr // to reduce noise in unit test runs. } @@ -210,8 +210,9 @@ TEST(YAMLParser, DiagnosticFilenameFromBufferID) { // When we construct a YAML stream over a named buffer, // we get its ID as filename in diagnostics. - MemoryBuffer* Buffer = MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); - yaml::Stream Stream(Buffer, SM); + std::unique_ptr Buffer = + MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); + yaml::Stream Stream(Buffer->getMemBufferRef(), SM); Stream.printError(Stream.begin()->getRoot(), "Hello, World!"); EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename()); } diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index 44d27d0..39cfaf0 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -143,4 +143,41 @@ TEST(raw_ostreamTest, WriteEscaped) { EXPECT_EQ("\\001\\010\\200", Str); } +TEST(raw_ostreamTest, Justify) { + EXPECT_EQ("xyz ", printToString(left_justify("xyz", 6), 6)); + EXPECT_EQ("abc", printToString(left_justify("abc", 3), 3)); + EXPECT_EQ("big", printToString(left_justify("big", 1), 3)); + EXPECT_EQ(" xyz", printToString(right_justify("xyz", 6), 6)); + EXPECT_EQ("abc", printToString(right_justify("abc", 3), 3)); + EXPECT_EQ("big", printToString(right_justify("big", 1), 3)); +} + +TEST(raw_ostreamTest, FormatHex) { + EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 6), 6)); + EXPECT_EQ("0x001234", printToString(format_hex(0x1234, 8), 8)); + EXPECT_EQ("0x00001234", printToString(format_hex(0x1234, 10), 10)); + EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 4), 6)); + EXPECT_EQ("0xff", printToString(format_hex(255, 4), 4)); + EXPECT_EQ("0xFF", printToString(format_hex(255, 4, true), 4)); + EXPECT_EQ("0x1", printToString(format_hex(1, 3), 3)); + EXPECT_EQ("0x12", printToString(format_hex(0x12, 3), 4)); + EXPECT_EQ("0x123", printToString(format_hex(0x123, 3), 5)); + EXPECT_EQ("0xffffffffffffffff", + printToString(format_hex(UINT64_MAX, 18), 18)); + EXPECT_EQ("0x8000000000000000", + printToString(format_hex((INT64_MIN), 18), 18)); +} + +TEST(raw_ostreamTest, FormatDecimal) { + EXPECT_EQ(" 0", printToString(format_decimal(0, 4), 4)); + EXPECT_EQ(" -1", printToString(format_decimal(-1, 4), 4)); + EXPECT_EQ(" -1", printToString(format_decimal(-1, 6), 6)); + EXPECT_EQ("1234567890", printToString(format_decimal(1234567890, 10), 10)); + EXPECT_EQ(" 9223372036854775807", + printToString(format_decimal(INT64_MAX, 21), 21)); + EXPECT_EQ(" -9223372036854775808", + printToString(format_decimal(INT64_MIN, 21), 21)); +} + + } diff --git a/unittests/Transforms/CMakeLists.txt b/unittests/Transforms/CMakeLists.txt index 8ec56f1..e3ce185 100644 --- a/unittests/Transforms/CMakeLists.txt +++ b/unittests/Transforms/CMakeLists.txt @@ -1,2 +1 @@ -add_subdirectory(DebugIR) add_subdirectory(Utils) diff --git a/unittests/Transforms/DebugIR/CMakeLists.txt b/unittests/Transforms/DebugIR/CMakeLists.txt deleted file mode 100644 index 88734d2..0000000 --- a/unittests/Transforms/DebugIR/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(LLVM_LINK_COMPONENTS - Core - Instrumentation - Support - ) - -add_llvm_unittest(DebugIRTests - DebugIR.cpp - ) diff --git a/unittests/Transforms/DebugIR/DebugIR.cpp b/unittests/Transforms/DebugIR/DebugIR.cpp deleted file mode 100644 index 41df147..0000000 --- a/unittests/Transforms/DebugIR/DebugIR.cpp +++ /dev/null @@ -1,308 +0,0 @@ -//===- DebugIR.cpp - Unit tests for the DebugIR pass ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The tests in this file verify the DebugIR pass that generates debug metadata -// for LLVM IR. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Triple.h" -#include "../lib/Transforms/Instrumentation/DebugIR.h" -#include "llvm/Config/config.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Path.h" -#include "llvm/Transforms/Instrumentation.h" - -// These tests do not depend on MCJIT, but we use the TrivialModuleBuilder -// helper class to construct some trivial Modules. -#include "../unittests/ExecutionEngine/MCJIT/MCJITTestBase.h" - -#include - -#include "gtest/gtest.h" - -#if defined(LLVM_ON_WIN32) -#include -#define getcwd_impl _getcwd -#elif defined (HAVE_GETCWD) -#include -#define getcwd_impl getcwd -#endif // LLVM_ON_WIN32 - -using namespace llvm; -using namespace std; - -namespace { - -/// Insert a mock CUDescriptor with the specified producer -void insertCUDescriptor(Module *M, StringRef File, StringRef Dir, - StringRef Producer) { - DIBuilder B(*M); - B.createCompileUnit(dwarf::DW_LANG_C99, File, Dir, Producer, false, "", 0); - B.finalize(); -} - -/// Attempts to remove file at Path and returns true if it existed, or false if -/// it did not. -bool removeIfExists(StringRef Path) { - // This is an approximation, on error we don't know in general if the file - // existed or not. - std::error_code EC = sys::fs::remove(Path, false); - return EC != llvm::errc::no_such_file_or_directory; -} - -char * current_dir() { -#if defined(LLVM_ON_WIN32) || defined(HAVE_GETCWD) - // calling getcwd (or _getcwd() on windows) with a null buffer makes it - // allocate a sufficiently sized buffer to store the current working dir. - return getcwd_impl(nullptr, 0); -#else - return 0; -#endif -} - -class TestDebugIR : public ::testing::Test, public TrivialModuleBuilder { -protected: - TestDebugIR() - : TrivialModuleBuilder(sys::getProcessTriple()) - , cwd(current_dir()) {} - - ~TestDebugIR() { free(cwd); } - - /// Returns a concatenated path string consisting of Dir and Filename - string getPath(const string &Dir, const string &Filename) { - SmallVector Path; - sys::path::append(Path, Dir, Filename); - Path.resize(Dir.size() + Filename.size() + 2); - Path[Dir.size() + Filename.size() + 1] = '\0'; - return string(Path.data()); - } - - LLVMContext Context; - char *cwd; - std::unique_ptr M; - std::unique_ptr D; -}; - -// Test empty named Module that is not supposed to be output to disk. -TEST_F(TestDebugIR, EmptyNamedModuleNoWrite) { - string Dir = "MadeUpDirectory"; - string File = "empty_module.ll"; - string Path(getPath(Dir, File)); - - M.reset(createEmptyModule(Path)); - - // constructing DebugIR with no args should not result in any file generated. - D.reset(static_cast(llvm::createDebugIRPass())); - D->runOnModule(*M); - - // verify DebugIR did not generate a file - ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; -} - -// Test a non-empty unnamed module that is output to an autogenerated file name. -TEST_F(TestDebugIR, NonEmptyUnnamedModuleWriteToAutogeneratedFile) { - M.reset(createEmptyModule()); - insertAddFunction(M.get()); - D.reset(static_cast(llvm::createDebugIRPass(true, true))); - - string Path; - D->runOnModule(*M, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test not specifying a name in the module -- DebugIR should generate a name -// and write the file contents. -TEST_F(TestDebugIR, EmptyModuleWriteAnonymousFile) { - M.reset(createEmptyModule()); - D.reset(static_cast(llvm::createDebugIRPass(false, false))); - - string Path; - D->runOnModule(*M, Path); - - // verify DebugIR generated a file and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -#ifdef HAVE_GETCWD // These tests require get_current_dir_name() - -// Test empty named Module that is to be output to path specified at Module -// construction. -TEST_F(TestDebugIR, EmptyNamedModuleWriteFile) { - string Filename("NamedFile1"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - D.reset(static_cast(llvm::createDebugIRPass(true, true))); - - string Path; - D->runOnModule(*M, Path); - - // verify DebugIR was able to correctly parse the file name from module ID - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test an empty unnamed module generates an output file whose path is specified -// at DebugIR construction. -TEST_F(TestDebugIR, EmptyUnnamedModuleWriteNamedFile) { - string Filename("NamedFile2"); - - M.reset(createEmptyModule()); - D.reset(static_cast(llvm::createDebugIRPass( - false, false, StringRef(cwd), StringRef(Filename)))); - string Path; - D->runOnModule(*M, Path); - - string ExpectedPath(getPath(cwd, Filename)); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test an empty named module generates an output file at the path specified -// during DebugIR construction. -TEST_F(TestDebugIR, EmptyNamedModuleWriteNamedFile) { - string Filename("NamedFile3"); - - string UnexpectedPath(getPath(cwd, "UnexpectedFilename")); - M.reset(createEmptyModule(UnexpectedPath)); - - D.reset(static_cast(llvm::createDebugIRPass( - false, false, StringRef(cwd), StringRef(Filename)))); - string Path; - D->runOnModule(*M, Path); - - string ExpectedPath(getPath(cwd, Filename)); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; - - // verify DebugIR did not generate a file at the path specified at Module - // construction. - ASSERT_FALSE(removeIfExists(UnexpectedPath)) << "Unexpected file " << Path; -} - -// Test a non-empty named module that is not supposed to be output to disk -TEST_F(TestDebugIR, NonEmptyNamedModuleNoWrite) { - string Filename("NamedFile4"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - insertAddFunction(M.get()); - - D.reset(static_cast(llvm::createDebugIRPass())); - - string Path; - D->runOnModule(*M, Path); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR did not generate a file - ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; -} - -// Test a non-empty named module that is output to disk. -TEST_F(TestDebugIR, NonEmptyNamedModuleWriteFile) { - string Filename("NamedFile5"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - insertAddFunction(M.get()); - - D.reset(static_cast(llvm::createDebugIRPass(true, true))); - - string Path; - D->runOnModule(*M, Path); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test a non-empty unnamed module is output to a path specified at DebugIR -// construction. -TEST_F(TestDebugIR, NonEmptyUnnamedModuleWriteToNamedFile) { - string Filename("NamedFile6"); - - M.reset(createEmptyModule()); - insertAddFunction(M.get()); - - D.reset(static_cast( - llvm::createDebugIRPass(true, true, cwd, Filename))); - string Path; - D->runOnModule(*M, Path); - - string ExpectedPath(getPath(cwd, Filename)); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test that information inside existing debug metadata is retained -TEST_F(TestDebugIR, ExistingMetadataRetained) { - string Filename("NamedFile7"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - insertAddFunction(M.get()); - - StringRef Producer("TestProducer"); - insertCUDescriptor(M.get(), Filename, cwd, Producer); - - DebugInfoFinder Finder; - Finder.processModule(*M); - ASSERT_EQ((unsigned)1, Finder.compile_unit_count()); - D.reset(static_cast(llvm::createDebugIRPass())); - - string Path; - D->runOnModule(*M, Path); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR did not generate a file - ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; - - DICompileUnit CU(*Finder.compile_units().begin()); - - // Verify original CU information is retained - ASSERT_EQ(Filename, CU.getFilename()); - ASSERT_EQ(cwd, CU.getDirectory()); - ASSERT_EQ(Producer, CU.getProducer()); -} - -#endif // HAVE_GETCWD - -#ifdef GTEST_HAS_DEATH_TEST - -// Test a non-empty unnamed module that is not supposed to be output to disk -// NOTE: this test is expected to die with LLVM_ERROR, and such depends on -// google test's "death test" mode. -TEST_F(TestDebugIR, NonEmptyUnnamedModuleNoWrite) { - M.reset(createEmptyModule(StringRef())); - insertAddFunction(M.get()); - D.reset(static_cast(llvm::createDebugIRPass())); - - // No name in module or on DebugIR construction ==> DebugIR should assert - EXPECT_DEATH(D->runOnModule(*M), - "DebugIR unable to determine file name in input."); -} - -#endif // GTEST_HAS_DEATH_TEST -} diff --git a/unittests/Transforms/DebugIR/Makefile b/unittests/Transforms/DebugIR/Makefile deleted file mode 100644 index 9ace8c3..0000000 --- a/unittests/Transforms/DebugIR/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- unittests/Transforms/Utils/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -TESTNAME = DebugIR -LINK_COMPONENTS := Instrumentation - -include $(LEVEL)/Makefile.config -include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Transforms/Makefile b/unittests/Transforms/Makefile index d5cca39..599b18a 100644 --- a/unittests/Transforms/Makefile +++ b/unittests/Transforms/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. -PARALLEL_DIRS = DebugIR Utils +PARALLEL_DIRS = Utils include $(LEVEL)/Makefile.common diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index b3a1f5b..1d22d5b 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -13,16 +13,15 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Constant.h" -#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "gtest/gtest.h" using namespace llvm; @@ -232,7 +231,7 @@ protected: // Function DI DIFile File = DBuilder.createFile("filename.c", "/file/dir/"); - DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef()); + DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None); DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes); DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, "filename.c", "/file/dir", "CloneFunc", false, "", 0); @@ -255,10 +254,11 @@ protected: // Create a local variable around the alloca DIType IntType = DBuilder.createBasicType("int", 32, 0, dwarf::DW_ATE_signed); + DIExpression E = DBuilder.createExpression(); DIVariable Variable = DBuilder.createLocalVariable( dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true); - DBuilder.insertDeclare(Alloca, Variable, Store); - DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator); + DBuilder.insertDeclare(Alloca, Variable, E, Store); + DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator); // Finalize the debug info DBuilder.finalize(); diff --git a/utils/FileCheck/FileCheck.cpp b/utils/FileCheck/FileCheck.cpp index 9e6a6a2..59affa1 100644 --- a/utils/FileCheck/FileCheck.cpp +++ b/utils/FileCheck/FileCheck.cpp @@ -57,6 +57,11 @@ static cl::list ImplicitCheckNot( "this pattern occur which are not matched by a positive pattern"), cl::value_desc("pattern")); +static cl::opt AllowEmptyInput( + "allow-empty", cl::init(false), + cl::desc("Allow the input file to be empty. This is useful when making\n" + "checks that some error message does not occur, for example.")); + typedef cl::list::const_iterator prefix_iterator; //===----------------------------------------------------------------------===// @@ -631,8 +636,9 @@ struct CheckString { /// /// \param PreserveHorizontal Don't squash consecutive horizontal whitespace /// characters to a single space. -static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, - bool PreserveHorizontal) { +static std::unique_ptr +CanonicalizeInputFile(std::unique_ptr MB, + bool PreserveHorizontal) { SmallString<128> NewFile; NewFile.reserve(MB->getBufferSize()); @@ -657,12 +663,8 @@ static MemoryBuffer *CanonicalizeInputFile(MemoryBuffer *MB, ++Ptr; } - // Free the old buffer and return a new one. - MemoryBuffer *MB2 = - MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier()); - - delete MB; - return MB2; + return std::unique_ptr( + MemoryBuffer::getMemBufferCopy(NewFile.str(), MB->getBufferIdentifier())); } static bool IsPartOfWord(char c) { @@ -837,25 +839,26 @@ static bool ReadCheckFile(SourceMgr &SM, // If we want to canonicalize whitespace, strip excess whitespace from the // buffer containing the CHECK lines. Remove DOS style line endings. - MemoryBuffer *F = CanonicalizeInputFile(FileOrErr.get().release(), - NoCanonicalizeWhiteSpace); - - SM.AddNewSourceBuffer(F, SMLoc()); + std::unique_ptr F = CanonicalizeInputFile( + std::move(FileOrErr.get()), NoCanonicalizeWhiteSpace); // Find all instances of CheckPrefix followed by : in the file. StringRef Buffer = F->getBuffer(); + SM.AddNewSourceBuffer(std::move(F), SMLoc()); + std::vector ImplicitNegativeChecks; for (const auto &PatternString : ImplicitCheckNot) { // Create a buffer with fake command line content in order to display the // command line option responsible for the specific implicit CHECK-NOT. std::string Prefix = std::string("-") + ImplicitCheckNot.ArgStr + "='"; std::string Suffix = "'"; - MemoryBuffer *CmdLine = MemoryBuffer::getMemBufferCopy( + std::unique_ptr CmdLine = MemoryBuffer::getMemBufferCopy( Prefix + PatternString + Suffix, "command line"); + StringRef PatternInBuffer = CmdLine->getBuffer().substr(Prefix.size(), PatternString.size()); - SM.AddNewSourceBuffer(CmdLine, SMLoc()); + SM.AddNewSourceBuffer(std::move(CmdLine), SMLoc()); ImplicitNegativeChecks.push_back(Pattern(Check::CheckNot)); ImplicitNegativeChecks.back().ParsePattern(PatternInBuffer, @@ -1212,7 +1215,11 @@ static bool ValidateCheckPrefixes() { I != E; ++I) { StringRef Prefix(*I); - if (!PrefixSet.insert(Prefix)) + // Reject empty prefixes. + if (Prefix == "") + return false; + + if (!PrefixSet.insert(Prefix).second) return false; if (!ValidateCheckPrefix(Prefix)) @@ -1258,27 +1265,27 @@ int main(int argc, char **argv) { << "': " << EC.message() << '\n'; return 2; } - std::unique_ptr File = std::move(FileOrErr.get()); + std::unique_ptr &File = FileOrErr.get(); - if (File->getBufferSize() == 0) { + if (File->getBufferSize() == 0 && !AllowEmptyInput) { errs() << "FileCheck error: '" << InputFilename << "' is empty.\n"; return 2; } // Remove duplicate spaces in the input file if requested. // Remove DOS style line endings. - MemoryBuffer *F = - CanonicalizeInputFile(File.release(), NoCanonicalizeWhiteSpace); - - SM.AddNewSourceBuffer(F, SMLoc()); - - /// VariableTable - This holds all the current filecheck variables. - StringMap VariableTable; + std::unique_ptr F = + CanonicalizeInputFile(std::move(File), NoCanonicalizeWhiteSpace); // Check that we have all of the expected strings, in order, in the input // file. StringRef Buffer = F->getBuffer(); + SM.AddNewSourceBuffer(std::move(F), SMLoc()); + + /// VariableTable - This holds all the current filecheck variables. + StringMap VariableTable; + bool hasError = false; unsigned i = 0, j = 0, e = CheckStrings.size(); diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 1277086..5ee20dd 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -115,6 +115,7 @@ #include #include #include +#include using namespace llvm; #define DEBUG_TYPE "asm-matcher-emitter" @@ -255,9 +256,8 @@ public: return true; // ... or if any of its super classes are a subset of RHS. - for (std::vector::const_iterator it = SuperClasses.begin(), - ie = SuperClasses.end(); it != ie; ++it) - if ((*it)->isSubsetOf(RHS)) + for (const ClassInfo *CI : SuperClasses) + if (CI->isSubsetOf(RHS)) return true; return false; @@ -391,6 +391,10 @@ struct MatchableInfo { /// AsmVariantID - Target's assembly syntax variant no. int AsmVariantID; + /// AsmString - The assembly string for this instruction (with variants + /// removed), e.g. "movsx $src, $dst". + std::string AsmString; + /// TheDef - This is the definition of the instruction or InstAlias that this /// matchable came from. Record *const TheDef; @@ -408,10 +412,6 @@ struct MatchableInfo { /// MCInst. SmallVector ResOperands; - /// AsmString - The assembly string for this instruction (with variants - /// removed), e.g. "movsx $src, $dst". - std::string AsmString; - /// Mnemonic - This is the first token of the matched instruction, its /// mnemonic. StringRef Mnemonic; @@ -423,7 +423,7 @@ struct MatchableInfo { SmallVector AsmOperands; /// Predicates - The required subtarget features to match this instruction. - SmallVector RequiredFeatures; + SmallVector RequiredFeatures; /// ConversionFnKind - The enum value which is passed to the generated /// convertToMCInst to convert parsed operands into an MCInst for this @@ -434,13 +434,15 @@ struct MatchableInfo { bool HasDeprecation; MatchableInfo(const CodeGenInstruction &CGI) - : AsmVariantID(0), TheDef(CGI.TheDef), DefRec(&CGI), - AsmString(CGI.AsmString) { + : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI) { } - MatchableInfo(const CodeGenInstAlias *Alias) - : AsmVariantID(0), TheDef(Alias->TheDef), DefRec(Alias), - AsmString(Alias->AsmString) { + MatchableInfo(std::unique_ptr Alias) + : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef), DefRec(Alias.release()) { + } + + ~MatchableInfo() { + delete DefRec.dyn_cast(); } // Two-operand aliases clone from the main matchable, but mark the second @@ -448,7 +450,7 @@ struct MatchableInfo { void formTwoOperandAlias(StringRef Constraint); void initialize(const AsmMatcherInfo &Info, - SmallPtrSet &SingletonRegisters, + SmallPtrSetImpl &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix); /// validate - Return true if this matchable is a valid thing to match against @@ -516,7 +518,7 @@ struct MatchableInfo { /// couldMatchAmbiguouslyWith - Check whether this matchable could /// ambiguously match the same set of operands as \p RHS (without being a /// strictly superior match). - bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) { + bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) const { // The primary comparator is the instruction mnemonic. if (Mnemonic != RHS.Mnemonic) return false; @@ -552,7 +554,7 @@ struct MatchableInfo { return !(HasLT ^ HasGT); } - void dump(); + void dump() const; private: void tokenizeAsmString(const AsmMatcherInfo &Info); @@ -565,16 +567,16 @@ struct SubtargetFeatureInfo { Record *TheDef; /// \brief An unique index assigned to represent this feature. - unsigned Index; + uint64_t Index; - SubtargetFeatureInfo(Record *D, unsigned Idx) : TheDef(D), Index(Idx) {} + SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {} /// \brief The name of the enumerated constant identifying this feature. std::string getEnumName() const { return "Feature_" + TheDef->getName(); } - void dump() { + void dump() const { errs() << getEnumName() << " " << Index << "\n"; TheDef->dump(); } @@ -582,10 +584,10 @@ struct SubtargetFeatureInfo { struct OperandMatchEntry { unsigned OperandMask; - MatchableInfo* MI; + const MatchableInfo* MI; ClassInfo *CI; - static OperandMatchEntry create(MatchableInfo* mi, ClassInfo *ci, + static OperandMatchEntry create(const MatchableInfo *mi, ClassInfo *ci, unsigned opMask) { OperandMatchEntry X; X.OperandMask = opMask; @@ -608,10 +610,10 @@ public: CodeGenTarget &Target; /// The classes which are needed for matching. - std::vector Classes; + std::forward_list Classes; /// The information on the matchables to match. - std::vector Matchables; + std::vector> Matchables; /// Info for custom matching operands by user defined methods. std::vector OperandMatchInfo; @@ -621,7 +623,7 @@ public: RegisterClassesTy RegisterClasses; /// Map of Predicate records to their subtarget information. - std::map SubtargetFeatures; + std::map SubtargetFeatures; /// Map of AsmOperandClass records to their class information. std::map AsmOperandClasses; @@ -644,7 +646,7 @@ private: /// buildRegisterClasses - Build the ClassInfo* instances for register /// classes. - void buildRegisterClasses(SmallPtrSet &SingletonRegisters); + void buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters); /// buildOperandClasses - Build the ClassInfo* instances for user defined /// operand classes. @@ -669,11 +671,10 @@ public: /// getSubtargetFeature - Lookup or create the subtarget feature info for the /// given operand. - SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { + const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const { assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!"); - std::map::const_iterator I = - SubtargetFeatures.find(Def); - return I == SubtargetFeatures.end() ? nullptr : I->second; + const auto &I = SubtargetFeatures.find(Def); + return I == SubtargetFeatures.end() ? nullptr : &I->second; } RecordKeeper &getRecords() const { @@ -683,11 +684,11 @@ public: } // End anonymous namespace -void MatchableInfo::dump() { +void MatchableInfo::dump() const { errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n"; for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) { - AsmOperand &Op = AsmOperands[i]; + const AsmOperand &Op = AsmOperands[i]; errs() << " op[" << i << "] = " << Op.Class->ClassName << " - "; errs() << '\"' << Op.Token << "\"\n"; } @@ -766,7 +767,7 @@ void MatchableInfo::formTwoOperandAlias(StringRef Constraint) { } void MatchableInfo::initialize(const AsmMatcherInfo &Info, - SmallPtrSet &SingletonRegisters, + SmallPtrSetImpl &SingletonRegisters, int AsmVariantNo, std::string &RegisterPrefix) { AsmVariantID = AsmVariantNo; AsmString = @@ -777,8 +778,8 @@ void MatchableInfo::initialize(const AsmMatcherInfo &Info, // Compute the require features. std::vector Predicates =TheDef->getValueAsListOfDefs("Predicates"); for (unsigned i = 0, e = Predicates.size(); i != e; ++i) - if (SubtargetFeatureInfo *Feature = - Info.getSubtargetFeature(Predicates[i])) + if (const SubtargetFeatureInfo *Feature = + Info.getSubtargetFeature(Predicates[i])) RequiredFeatures.push_back(Feature); // Collect singleton registers, if used. @@ -995,7 +996,8 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { ClassInfo *&Entry = TokenClasses[Token]; if (!Entry) { - Entry = new ClassInfo(); + Classes.emplace_front(); + Entry = &Classes.front(); Entry->Kind = ClassInfo::Token; Entry->ClassName = "Token"; Entry->Name = "MCK_" + getEnumNameForToken(Token); @@ -1004,7 +1006,6 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) { Entry->RenderMethod = ""; Entry->ParserMethod = ""; Entry->DiagnosticType = ""; - Classes.push_back(Entry); } return Entry; @@ -1075,11 +1076,9 @@ struct LessRegisterSet { }; void AsmMatcherInfo:: -buildRegisterClasses(SmallPtrSet &SingletonRegisters) { - const std::vector &Registers = - Target.getRegBank().getRegisters(); - ArrayRef RegClassList = - Target.getRegBank().getRegClasses(); +buildRegisterClasses(SmallPtrSetImpl &SingletonRegisters) { + const auto &Registers = Target.getRegBank().getRegisters(); + auto &RegClassList = Target.getRegBank().getRegClasses(); typedef std::set RegisterSetSet; @@ -1087,15 +1086,12 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { RegisterSetSet RegisterSets; // Gather the defined sets. - for (ArrayRef::const_iterator it = - RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) - RegisterSets.insert(RegisterSet( - (*it)->getOrder().begin(), (*it)->getOrder().end())); + for (const CodeGenRegisterClass &RC : RegClassList) + RegisterSets.insert( + RegisterSet(RC.getOrder().begin(), RC.getOrder().end())); // Add any required singleton sets. - for (SmallPtrSet::iterator it = SingletonRegisters.begin(), - ie = SingletonRegisters.end(); it != ie; ++it) { - Record *Rec = *it; + for (Record *Rec : SingletonRegisters) { RegisterSets.insert(RegisterSet(&Rec, &Rec + 1)); } @@ -1103,19 +1099,16 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { // a unique register set class), and build the mapping of registers to the set // they should classify to. std::map RegisterMap; - for (std::vector::const_iterator it = Registers.begin(), - ie = Registers.end(); it != ie; ++it) { - const CodeGenRegister &CGR = **it; + for (const CodeGenRegister &CGR : Registers) { // Compute the intersection of all sets containing this register. RegisterSet ContainingSet; - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it) { - if (!it->count(CGR.TheDef)) + for (const RegisterSet &RS : RegisterSets) { + if (!RS.count(CGR.TheDef)) continue; if (ContainingSet.empty()) { - ContainingSet = *it; + ContainingSet = RS; continue; } @@ -1123,7 +1116,7 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { std::swap(Tmp, ContainingSet); std::insert_iterator II(ContainingSet, ContainingSet.begin()); - std::set_intersection(Tmp.begin(), Tmp.end(), it->begin(), it->end(), II, + std::set_intersection(Tmp.begin(), Tmp.end(), RS.begin(), RS.end(), II, LessRecordByID()); } @@ -1136,39 +1129,35 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { // Construct the register classes. std::map RegisterSetClasses; unsigned Index = 0; - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it, ++Index) { - ClassInfo *CI = new ClassInfo(); + for (const RegisterSet &RS : RegisterSets) { + Classes.emplace_front(); + ClassInfo *CI = &Classes.front(); CI->Kind = ClassInfo::RegisterClass0 + Index; CI->ClassName = "Reg" + utostr(Index); CI->Name = "MCK_Reg" + utostr(Index); CI->ValueName = ""; CI->PredicateMethod = ""; // unused CI->RenderMethod = "addRegOperands"; - CI->Registers = *it; + CI->Registers = RS; // FIXME: diagnostic type. CI->DiagnosticType = ""; - Classes.push_back(CI); - RegisterSetClasses.insert(std::make_pair(*it, CI)); + RegisterSetClasses.insert(std::make_pair(RS, CI)); + ++Index; } // Find the superclasses; we could compute only the subgroup lattice edges, // but there isn't really a point. - for (RegisterSetSet::iterator it = RegisterSets.begin(), - ie = RegisterSets.end(); it != ie; ++it) { - ClassInfo *CI = RegisterSetClasses[*it]; - for (RegisterSetSet::iterator it2 = RegisterSets.begin(), - ie2 = RegisterSets.end(); it2 != ie2; ++it2) - if (*it != *it2 && - std::includes(it2->begin(), it2->end(), it->begin(), it->end(), + for (const RegisterSet &RS : RegisterSets) { + ClassInfo *CI = RegisterSetClasses[RS]; + for (const RegisterSet &RS2 : RegisterSets) + if (RS != RS2 && + std::includes(RS2.begin(), RS2.end(), RS.begin(), RS.end(), LessRecordByID())) - CI->SuperClasses.push_back(RegisterSetClasses[*it2]); + CI->SuperClasses.push_back(RegisterSetClasses[RS2]); } // Name the register classes which correspond to a user defined RegisterClass. - for (ArrayRef::const_iterator - it = RegClassList.begin(), ie = RegClassList.end(); it != ie; ++it) { - const CodeGenRegisterClass &RC = **it; + for (const CodeGenRegisterClass &RC : RegClassList) { // Def will be NULL for non-user defined register classes. Record *Def = RC.getDef(); if (!Def) @@ -1191,9 +1180,7 @@ buildRegisterClasses(SmallPtrSet &SingletonRegisters) { RegisterClasses[it->first] = RegisterSetClasses[it->second]; // Name the register classes which correspond to singleton registers. - for (SmallPtrSet::iterator it = SingletonRegisters.begin(), - ie = SingletonRegisters.end(); it != ie; ++it) { - Record *Rec = *it; + for (Record *Rec : SingletonRegisters) { ClassInfo *CI = RegisterClasses[Rec]; assert(CI && "Missing singleton register class info!"); @@ -1211,36 +1198,36 @@ void AsmMatcherInfo::buildOperandClasses() { Records.getAllDerivedDefinitions("AsmOperandClass"); // Pre-populate AsmOperandClasses map. - for (std::vector::iterator it = AsmOperands.begin(), - ie = AsmOperands.end(); it != ie; ++it) - AsmOperandClasses[*it] = new ClassInfo(); + for (Record *Rec : AsmOperands) { + Classes.emplace_front(); + AsmOperandClasses[Rec] = &Classes.front(); + } unsigned Index = 0; - for (std::vector::iterator it = AsmOperands.begin(), - ie = AsmOperands.end(); it != ie; ++it, ++Index) { - ClassInfo *CI = AsmOperandClasses[*it]; + for (Record *Rec : AsmOperands) { + ClassInfo *CI = AsmOperandClasses[Rec]; CI->Kind = ClassInfo::UserClass0 + Index; - ListInit *Supers = (*it)->getValueAsListInit("SuperClasses"); + ListInit *Supers = Rec->getValueAsListInit("SuperClasses"); for (unsigned i = 0, e = Supers->getSize(); i != e; ++i) { DefInit *DI = dyn_cast(Supers->getElement(i)); if (!DI) { - PrintError((*it)->getLoc(), "Invalid super class reference!"); + PrintError(Rec->getLoc(), "Invalid super class reference!"); continue; } ClassInfo *SC = AsmOperandClasses[DI->getDef()]; if (!SC) - PrintError((*it)->getLoc(), "Invalid super class reference!"); + PrintError(Rec->getLoc(), "Invalid super class reference!"); else CI->SuperClasses.push_back(SC); } - CI->ClassName = (*it)->getValueAsString("Name"); + CI->ClassName = Rec->getValueAsString("Name"); CI->Name = "MCK_" + CI->ClassName; - CI->ValueName = (*it)->getName(); + CI->ValueName = Rec->getName(); // Get or construct the predicate method name. - Init *PMName = (*it)->getValueInit("PredicateMethod"); + Init *PMName = Rec->getValueInit("PredicateMethod"); if (StringInit *SI = dyn_cast(PMName)) { CI->PredicateMethod = SI->getValue(); } else { @@ -1249,7 +1236,7 @@ void AsmMatcherInfo::buildOperandClasses() { } // Get or construct the render method name. - Init *RMName = (*it)->getValueInit("RenderMethod"); + Init *RMName = Rec->getValueInit("RenderMethod"); if (StringInit *SI = dyn_cast(RMName)) { CI->RenderMethod = SI->getValue(); } else { @@ -1258,18 +1245,17 @@ void AsmMatcherInfo::buildOperandClasses() { } // Get the parse method name or leave it as empty. - Init *PRMName = (*it)->getValueInit("ParserMethod"); + Init *PRMName = Rec->getValueInit("ParserMethod"); if (StringInit *SI = dyn_cast(PRMName)) CI->ParserMethod = SI->getValue(); // Get the diagnostic type or leave it as empty. // Get the parse method name or leave it as empty. - Init *DiagnosticType = (*it)->getValueInit("DiagnosticType"); + Init *DiagnosticType = Rec->getValueInit("DiagnosticType"); if (StringInit *SI = dyn_cast(DiagnosticType)) CI->DiagnosticType = SI->getValue(); - AsmOperandClasses[*it] = CI; - Classes.push_back(CI); + ++Index; } } @@ -1288,16 +1274,13 @@ void AsmMatcherInfo::buildOperandMatchInfo() { typedef std::map> OpClassMaskTy; OpClassMaskTy OpClassMask; - for (std::vector::const_iterator it = - Matchables.begin(), ie = Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; + for (const auto &MI : Matchables) { OpClassMask.clear(); // Keep track of all operands of this instructions which belong to the // same class. - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { + const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i]; if (Op.Class->ParserMethod.empty()) continue; unsigned &OperandMask = OpClassMask[Op.Class]; @@ -1305,11 +1288,11 @@ void AsmMatcherInfo::buildOperandMatchInfo() { } // Generate operand match info for each mnemonic/operand class pair. - for (OpClassMaskTy::iterator iit = OpClassMask.begin(), - iie = OpClassMask.end(); iit != iie; ++iit) { - unsigned OpMask = iit->second; - ClassInfo *CI = iit->first; - OperandMatchInfo.push_back(OperandMatchEntry::create(&II, CI, OpMask)); + for (const auto &OCM : OpClassMask) { + unsigned OpMask = OCM.second; + ClassInfo *CI = OCM.first; + OperandMatchInfo.push_back(OperandMatchEntry::create(MI.get(), CI, + OpMask)); } } } @@ -1327,10 +1310,10 @@ void AsmMatcherInfo::buildInfo() { if (Pred->getName().empty()) PrintFatalError(Pred->getLoc(), "Predicate has no name!"); - unsigned FeatureNo = SubtargetFeatures.size(); - SubtargetFeatures[Pred] = new SubtargetFeatureInfo(Pred, FeatureNo); - DEBUG(SubtargetFeatures[Pred]->dump()); - assert(FeatureNo < 32 && "Too many subtarget features!"); + SubtargetFeatures.insert(std::make_pair( + Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()))); + DEBUG(SubtargetFeatures.find(Pred)->second.dump()); + assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!"); } // Parse the instructions; we need to do this first so that we can gather the @@ -1344,20 +1327,18 @@ void AsmMatcherInfo::buildInfo() { std::string RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix"); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - const CodeGenInstruction &CGI = **I; + for (const CodeGenInstruction *CGI : Target.instructions()) { // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instructions we consider. - if (!StringRef(CGI.TheDef->getName()).startswith(MatchPrefix)) + if (!StringRef(CGI->TheDef->getName()).startswith(MatchPrefix)) continue; // Ignore "codegen only" instructions. - if (CGI.TheDef->getValueAsBit("isCodeGenOnly")) + if (CGI->TheDef->getValueAsBit("isCodeGenOnly")) continue; - std::unique_ptr II(new MatchableInfo(CGI)); + std::unique_ptr II(new MatchableInfo(*CGI)); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); @@ -1366,14 +1347,7 @@ void AsmMatcherInfo::buildInfo() { if (!II->validate(CommentDelimiter, true)) continue; - // Ignore "Int_*" and "*_Int" instructions, which are internal aliases. - // - // FIXME: This is a total hack. - if (StringRef(II->TheDef->getName()).startswith("Int_") || - StringRef(II->TheDef->getName()).endswith("_Int")) - continue; - - Matchables.push_back(II.release()); + Matchables.push_back(std::move(II)); } // Parse all of the InstAlias definitions and stick them in the list of @@ -1381,8 +1355,8 @@ void AsmMatcherInfo::buildInfo() { std::vector AllInstAliases = Records.getAllDerivedDefinitions("InstAlias"); for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) { - CodeGenInstAlias *Alias = - new CodeGenInstAlias(AllInstAliases[i], AsmVariantNo, Target); + auto Alias = llvm::make_unique(AllInstAliases[i], + AsmVariantNo, Target); // If the tblgen -match-prefix option is specified (for tblgen hackers), // filter the set of instruction aliases we consider, based on the target @@ -1391,14 +1365,14 @@ void AsmMatcherInfo::buildInfo() { .startswith( MatchPrefix)) continue; - std::unique_ptr II(new MatchableInfo(Alias)); + std::unique_ptr II(new MatchableInfo(std::move(Alias))); II->initialize(*this, SingletonRegisters, AsmVariantNo, RegisterPrefix); // Validate the alias definitions. II->validate(CommentDelimiter, false); - Matchables.push_back(II.release()); + Matchables.push_back(std::move(II)); } } @@ -1410,11 +1384,8 @@ void AsmMatcherInfo::buildInfo() { // Build the information about matchables, now that we have fully formed // classes. - std::vector NewMatchables; - for (std::vector::iterator it = Matchables.begin(), - ie = Matchables.end(); it != ie; ++it) { - MatchableInfo *II = *it; - + std::vector> NewMatchables; + for (auto &II : Matchables) { // Parse the tokens after the mnemonic. // Note: buildInstructionOperandReference may insert new AsmOperands, so // don't precompute the loop bound. @@ -1449,9 +1420,9 @@ void AsmMatcherInfo::buildInfo() { OperandName = Token.substr(1); if (II->DefRec.is()) - buildInstructionOperandReference(II, OperandName, i); + buildInstructionOperandReference(II.get(), OperandName, i); else - buildAliasOperandReference(II, OperandName, Op); + buildAliasOperandReference(II.get(), OperandName, Op); } if (II->DefRec.is()) { @@ -1469,14 +1440,14 @@ void AsmMatcherInfo::buildInfo() { AliasII->formTwoOperandAlias(Constraint); // Add the alias to the matchables list. - NewMatchables.push_back(AliasII.release()); + NewMatchables.push_back(std::move(AliasII)); } } else II->buildAliasResultOperands(); } if (!NewMatchables.empty()) - Matchables.insert(Matchables.end(), NewMatchables.begin(), - NewMatchables.end()); + std::move(NewMatchables.begin(), NewMatchables.end(), + std::back_inserter(Matchables)); // Process token alias definitions and set up the associated superclass // information. @@ -1493,7 +1464,7 @@ void AsmMatcherInfo::buildInfo() { } // Reorder classes so that classes precede super classes. - std::sort(Classes.begin(), Classes.end(), less_ptr()); + Classes.sort(); } /// buildInstructionOperandReference - The specified operand is a reference to a @@ -1703,7 +1674,7 @@ static unsigned getConverterOperandID(const std::string &Name, static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, - std::vector &Infos, + std::vector> &Infos, raw_ostream &OS) { SetVector OperandConversionKinds; SetVector InstructionConversionKinds; @@ -1767,16 +1738,13 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, OperandConversionKinds.insert("CVT_Tied"); enum { CVT_Done, CVT_Reg, CVT_Tied }; - for (std::vector::const_iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - MatchableInfo &II = **it; - + for (auto &II : Infos) { // Check if we have a custom match function. std::string AsmMatchConverter = - II.getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); + II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter"); if (!AsmMatchConverter.empty()) { std::string Signature = "ConvertCustom_" + AsmMatchConverter; - II.ConversionFnKind = Signature; + II->ConversionFnKind = Signature; // Check if we have already generated this signature. if (!InstructionConversionKinds.insert(Signature)) @@ -1808,16 +1776,17 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, std::vector ConversionRow; // Compute the convert enum and the case body. - MaxRowLength = std::max(MaxRowLength, II.ResOperands.size()*2 + 1 ); + MaxRowLength = std::max(MaxRowLength, II->ResOperands.size()*2 + 1 ); - for (unsigned i = 0, e = II.ResOperands.size(); i != e; ++i) { - const MatchableInfo::ResOperand &OpInfo = II.ResOperands[i]; + for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) { + const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i]; // Generate code to populate each result operand. switch (OpInfo.Kind) { case MatchableInfo::ResOperand::RenderAsmOperand: { // This comes from something we parsed. - MatchableInfo::AsmOperand &Op = II.AsmOperands[OpInfo.AsmOperandNum]; + const MatchableInfo::AsmOperand &Op = + II->AsmOperands[OpInfo.AsmOperandNum]; // Registers are always converted the same, don't duplicate the // conversion function based on them. @@ -1940,7 +1909,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, if (Signature == "Convert") Signature += "_NoOperands"; - II.ConversionFnKind = Signature; + II->ConversionFnKind = Signature; // Save the signature. If we already have it, don't add a new row // to the table. @@ -2003,7 +1972,7 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName, /// emitMatchClassEnumeration - Emit the enumeration for match class kinds. static void emitMatchClassEnumeration(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { OS << "namespace {\n\n"; @@ -2011,9 +1980,7 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target, << "/// instruction matching.\n"; OS << "enum MatchClassKind {\n"; OS << " InvalidMatchClass = 0,\n"; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &CI = **it; + for (const auto &CI : Infos) { OS << " " << CI.Name << ", // "; if (CI.Kind == ClassInfo::Token) { OS << "'" << CI.ValueName << "'\n"; @@ -2053,10 +2020,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, // Check the user classes. We don't care what order since we're only // actually matching against one of them. - for (std::vector::iterator it = Info.Classes.begin(), - ie = Info.Classes.end(); it != ie; ++it) { - ClassInfo &CI = **it; - + for (const auto &CI : Info.Classes) { if (!CI.isUserClass()) continue; @@ -2075,11 +2039,9 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, OS << " MatchClassKind OpKind;\n"; OS << " switch (Operand.getReg()) {\n"; OS << " default: OpKind = InvalidMatchClass; break;\n"; - for (AsmMatcherInfo::RegisterClassesTy::iterator - it = Info.RegisterClasses.begin(), ie = Info.RegisterClasses.end(); - it != ie; ++it) + for (const auto &RC : Info.RegisterClasses) OS << " case " << Info.Target.getName() << "::" - << it->first->getName() << ": OpKind = " << it->second->Name + << RC.first->getName() << ": OpKind = " << RC.second->Name << "; break;\n"; OS << " }\n"; OS << " return isSubclass(OpKind, Kind) ? " @@ -2094,7 +2056,7 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info, /// emitIsSubclass - Emit the subclass predicate function. static void emitIsSubclass(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n"; OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n"; @@ -2107,15 +2069,9 @@ static void emitIsSubclass(CodeGenTarget &Target, SS << " switch (A) {\n"; SS << " default:\n"; SS << " return false;\n"; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &A = **it; - + for (const auto &A : Infos) { std::vector SuperClasses; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &B = **it; - + for (const auto &B : Infos) { if (&A != &B && A.isSubsetOf(B)) SuperClasses.push_back(B.Name); } @@ -2157,17 +2113,14 @@ static void emitIsSubclass(CodeGenTarget &Target, /// emitMatchTokenString - Emit the function to match a token string to the /// appropriate match class value. static void emitMatchTokenString(CodeGenTarget &Target, - std::vector &Infos, + std::forward_list &Infos, raw_ostream &OS) { // Construct the match list. std::vector Matches; - for (std::vector::iterator it = Infos.begin(), - ie = Infos.end(); it != ie; ++it) { - ClassInfo &CI = **it; - + for (const auto &CI : Infos) { if (CI.Kind == ClassInfo::Token) - Matches.push_back(StringMatcher::StringPair(CI.ValueName, - "return " + CI.Name + ";")); + Matches.push_back( + StringMatcher::StringPair(CI.ValueName, "return " + CI.Name + ";")); } OS << "static MatchClassKind matchTokenString(StringRef Name) {\n"; @@ -2184,16 +2137,14 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, raw_ostream &OS) { // Construct the match list. std::vector Matches; - const std::vector &Regs = - Target.getRegBank().getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - if (Reg->TheDef->getValueAsString("AsmName").empty()) + const auto &Regs = Target.getRegBank().getRegisters(); + for (const CodeGenRegister &Reg : Regs) { + if (Reg.TheDef->getValueAsString("AsmName").empty()) continue; - Matches.push_back(StringMatcher::StringPair( - Reg->TheDef->getValueAsString("AsmName"), - "return " + utostr(Reg->EnumValue) + ";")); + Matches.push_back( + StringMatcher::StringPair(Reg.TheDef->getValueAsString("AsmName"), + "return " + utostr(Reg.EnumValue) + ";")); } OS << "static unsigned MatchRegisterName(StringRef Name) {\n"; @@ -2205,7 +2156,9 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser, } static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range <= 0xFFFFFFFFULL && "Enum too large"); + assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFFFFFFULL) + return "uint64_t"; if (Range > 0xFFFF) return "uint32_t"; if (Range > 0xFF) @@ -2228,11 +2181,9 @@ static void emitSubtargetFeatureFlagEnumeration(AsmMatcherInfo &Info, << "instruction matching.\n"; OS << "enum SubtargetFeatureFlag : " << getMinimalRequiredFeaturesType(Info) << " {\n"; - for (std::map::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; - OS << " " << SFI.getEnumName() << " = (1U << " << SFI.Index << "),\n"; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; + OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n"; } OS << " Feature_None = 0\n"; OS << "};\n\n"; @@ -2263,13 +2214,11 @@ static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) { static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) { OS << "// User-level names for subtarget features that participate in\n" << "// instruction matching.\n" - << "static const char *getSubtargetFeatureName(unsigned Val) {\n"; + << "static const char *getSubtargetFeatureName(uint64_t Val) {\n"; if (!Info.SubtargetFeatures.empty()) { OS << " switch(Val) {\n"; - typedef std::map RecFeatMap; - for (RecFeatMap::const_iterator it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; // FIXME: Totally just a placeholder name to get the algorithm working. OS << " case " << SFI.getEnumName() << ": return \"" << SFI.TheDef->getValueAsString("PredicateName") << "\";\n"; @@ -2290,13 +2239,11 @@ static void emitComputeAvailableFeatures(AsmMatcherInfo &Info, std::string ClassName = Info.AsmParser->getValueAsString("AsmParserClassName"); - OS << "unsigned " << Info.Target.getName() << ClassName << "::\n" + OS << "uint64_t " << Info.Target.getName() << ClassName << "::\n" << "ComputeAvailableFeatures(uint64_t FB) const {\n"; - OS << " unsigned Features = 0;\n"; - for (std::map::const_iterator - it = Info.SubtargetFeatures.begin(), - ie = Info.SubtargetFeatures.end(); it != ie; ++it) { - SubtargetFeatureInfo &SFI = *it->second; + OS << " uint64_t Features = 0;\n"; + for (const auto &SF : Info.SubtargetFeatures) { + const SubtargetFeatureInfo &SFI = SF.second; OS << " if ("; std::string CondStorage = @@ -2342,7 +2289,7 @@ static std::string GetAliasRequiredFeatures(Record *R, std::string Result; unsigned NumFeatures = 0; for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) { - SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); + const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]); if (!F) PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() + @@ -2446,7 +2393,7 @@ static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info, if (Aliases.empty()) return false; OS << "static void applyMnemonicAliases(StringRef &Mnemonic, " - "unsigned Features, unsigned VariantID) {\n"; + "uint64_t Features, unsigned VariantID) {\n"; OS << " switch (VariantID) {\n"; unsigned VariantCount = Target.getAsmParserVariantCount(); for (unsigned VC = 0; VC != VariantCount; ++VC) { @@ -2486,8 +2433,8 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " RequiredFeatures;\n"; OS << " " << getMinimalTypeForRange(MaxMnemonicIndex) << " Mnemonic;\n"; - OS << " " << getMinimalTypeForRange(Info.Classes.size()) - << " Class;\n"; + OS << " " << getMinimalTypeForRange(std::distance( + Info.Classes.begin(), Info.Classes.end())) << " Class;\n"; OS << " " << getMinimalTypeForRange(MaxMask) << " OperandMask;\n\n"; OS << " StringRef getMnemonic() const {\n"; @@ -2564,13 +2511,11 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, << " &Operands,\n unsigned MCK) {\n\n" << " switch(MCK) {\n"; - for (std::vector::const_iterator it = Info.Classes.begin(), - ie = Info.Classes.end(); it != ie; ++it) { - ClassInfo *CI = *it; - if (CI->ParserMethod.empty()) + for (const auto &CI : Info.Classes) { + if (CI.ParserMethod.empty()) continue; - OS << " case " << CI->Name << ":\n" - << " return " << CI->ParserMethod << "(Operands);\n"; + OS << " case " << CI.Name << ":\n" + << " return " << CI.ParserMethod << "(Operands);\n"; } OS << " default:\n"; @@ -2589,7 +2534,7 @@ static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target, // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the next operand index.\n"; OS << " unsigned NextOpNum = Operands.size()-1;\n"; @@ -2649,22 +2594,23 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // stable_sort to ensure that ambiguous instructions are still // deterministically ordered. std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(), - less_ptr()); + [](const std::unique_ptr &a, + const std::unique_ptr &b){ + return *a < *b;}); DEBUG_WITH_TYPE("instruction_info", { - for (std::vector::iterator - it = Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) - (*it)->dump(); + for (const auto &MI : Info.Matchables) + MI->dump(); }); // Check for ambiguous matchables. DEBUG_WITH_TYPE("ambiguous_instrs", { unsigned NumAmbiguous = 0; - for (unsigned i = 0, e = Info.Matchables.size(); i != e; ++i) { - for (unsigned j = i + 1; j != e; ++j) { - MatchableInfo &A = *Info.Matchables[i]; - MatchableInfo &B = *Info.Matchables[j]; + for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E; + ++I) { + for (auto J = std::next(I); J != E; ++J) { + const MatchableInfo &A = **I; + const MatchableInfo &B = **J; if (A.couldMatchAmbiguouslyWith(B)) { errs() << "warning: ambiguous matchables:\n"; @@ -2691,7 +2637,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "#undef GET_ASSEMBLER_HEADER\n"; OS << " // This should be included into the middle of the declaration of\n"; OS << " // your subclasses implementation of MCTargetAsmParser.\n"; - OS << " unsigned ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; + OS << " uint64_t ComputeAvailableFeatures(uint64_t FeatureBits) const;\n"; OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, " << "unsigned Opcode,\n" << " const OperandVector " @@ -2699,11 +2645,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " void convertToMapAndConstraints(unsigned Kind,\n "; OS << " const OperandVector &Operands) override;\n"; OS << " bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) override;\n"; - OS << " unsigned MatchInstructionImpl(\n"; - OS.indent(27); - OS << "const OperandVector &Operands,\n" + OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n" << " MCInst &Inst,\n" - << " unsigned &ErrorInfo," + << " uint64_t &ErrorInfo," << " bool matchingInlineAsm,\n" << " unsigned VariantID = 0);\n"; @@ -2784,15 +2728,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { size_t MaxNumOperands = 0; unsigned MaxMnemonicIndex = 0; bool HasDeprecation = false; - for (std::vector::const_iterator it = - Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; - MaxNumOperands = std::max(MaxNumOperands, II.AsmOperands.size()); - HasDeprecation |= II.HasDeprecation; + for (const auto &MI : Info.Matchables) { + MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size()); + HasDeprecation |= MI->HasDeprecation; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); MaxMnemonicIndex = std::max(MaxMnemonicIndex, StringTable.GetOrAddStringOffset(LenMnemonic, false)); } @@ -2820,8 +2761,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { << " ConvertFn;\n"; OS << " " << getMinimalRequiredFeaturesType(Info) << " RequiredFeatures;\n"; - OS << " " << getMinimalTypeForRange(Info.Classes.size()) - << " Classes[" << MaxNumOperands << "];\n"; + OS << " " << getMinimalTypeForRange( + std::distance(Info.Classes.begin(), Info.Classes.end())) + << " Classes[" << MaxNumOperands << "];\n"; OS << " StringRef getMnemonic() const {\n"; OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n"; OS << " MnemonicTable[Mnemonic]);\n"; @@ -2850,33 +2792,30 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << "static const MatchEntry MatchTable" << VC << "[] = {\n"; - for (std::vector::const_iterator it = - Info.Matchables.begin(), ie = Info.Matchables.end(); - it != ie; ++it) { - MatchableInfo &II = **it; - if (II.AsmVariantID != AsmVariantNo) + for (const auto &MI : Info.Matchables) { + if (MI->AsmVariantID != AsmVariantNo) continue; // Store a pascal-style length byte in the mnemonic. - std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str(); + std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str(); OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false) - << " /* " << II.Mnemonic << " */, " + << " /* " << MI->Mnemonic << " */, " << Target.getName() << "::" - << II.getResultInst()->TheDef->getName() << ", " - << II.ConversionFnKind << ", "; + << MI->getResultInst()->TheDef->getName() << ", " + << MI->ConversionFnKind << ", "; // Write the required features mask. - if (!II.RequiredFeatures.empty()) { - for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) { + if (!MI->RequiredFeatures.empty()) { + for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) { if (i) OS << "|"; - OS << II.RequiredFeatures[i]->getEnumName(); + OS << MI->RequiredFeatures[i]->getEnumName(); } } else OS << "0"; OS << ", { "; - for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { - MatchableInfo::AsmOperand &Op = II.AsmOperands[i]; + for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) { + const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i]; if (i) OS << ", "; OS << Op.Class->Name; @@ -2893,7 +2832,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // Find the appropriate table for this asm variant.\n"; OS << " const MatchEntry *Start, *End;\n"; OS << " switch (VariantID) {\n"; - OS << " default: // unreachable\n"; + OS << " default: llvm_unreachable(\"invalid variant!\");\n"; for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); @@ -2909,10 +2848,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Finally, build the match function. OS << "unsigned " << Target.getName() << ClassName << "::\n" - << "MatchInstructionImpl(const OperandVector" - << " &Operands,\n"; - OS << " MCInst &Inst,\n" - << "unsigned &ErrorInfo, bool matchingInlineAsm, unsigned VariantID) {\n"; + << "MatchInstructionImpl(const OperandVector &Operands,\n"; + OS << " MCInst &Inst, uint64_t &ErrorInfo,\n" + << " bool matchingInlineAsm, unsigned VariantID) {\n"; OS << " // Eliminate obvious mismatches.\n"; OS << " if (Operands.size() > " << (MaxNumOperands+1) << ") {\n"; @@ -2922,7 +2860,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { // Emit code to get the available features. OS << " // Get the current feature set.\n"; - OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n"; + OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n"; OS << " // Get the instruction mnemonic, which is the first token.\n"; OS << " StringRef Mnemonic = ((" << Target.getName() @@ -2938,7 +2876,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " bool HadMatchOtherThanFeatures = false;\n"; OS << " bool HadMatchOtherThanPredicate = false;\n"; OS << " unsigned RetCode = Match_InvalidOperand;\n"; - OS << " unsigned MissingFeatures = ~0U;\n"; + OS << " uint64_t MissingFeatures = ~0ULL;\n"; OS << " // Set ErrorInfo to the operand that mismatches if it is\n"; OS << " // wrong for all instances of the instruction.\n"; OS << " ErrorInfo = ~0U;\n"; @@ -2947,7 +2885,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " // Find the appropriate table for this asm variant.\n"; OS << " const MatchEntry *Start, *End;\n"; OS << " switch (VariantID) {\n"; - OS << " default: // unreachable\n"; + OS << " default: llvm_unreachable(\"invalid variant!\");\n"; for (unsigned VC = 0; VC != VariantCount; ++VC) { Record *AsmVariant = Target.getAsmParserVariant(VC); int AsmVariantNo = AsmVariant->getValueAsInt("Variant"); @@ -3014,14 +2952,15 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if ((AvailableFeatures & it->RequiredFeatures) " << "!= it->RequiredFeatures) {\n"; OS << " HadMatchOtherThanFeatures = true;\n"; - OS << " unsigned NewMissingFeatures = it->RequiredFeatures & " + OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & " "~AvailableFeatures;\n"; - OS << " if (CountPopulation_32(NewMissingFeatures) <=\n" - " CountPopulation_32(MissingFeatures))\n"; + OS << " if (CountPopulation_64(NewMissingFeatures) <=\n" + " CountPopulation_64(MissingFeatures))\n"; OS << " MissingFeatures = NewMissingFeatures;\n"; OS << " continue;\n"; OS << " }\n"; OS << "\n"; + OS << " Inst.clear();\n\n"; OS << " if (matchingInlineAsm) {\n"; OS << " Inst.setOpcode(it->Opcode);\n"; OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n"; @@ -3055,7 +2994,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) { OS << " if (MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, STI, Info)) {\n"; OS << " SMLoc Loc = ((" << Target.getName() << "Operand&)*Operands[0]).getStartLoc();\n"; - OS << " Parser.Warning(Loc, Info, None);\n"; + OS << " getParser().Warning(Loc, Info, None);\n"; OS << " }\n"; } diff --git a/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp index 7ef70d3..5924d5f 100644 --- a/utils/TableGen/AsmWriterEmitter.cpp +++ b/utils/TableGen/AsmWriterEmitter.cpp @@ -208,9 +208,6 @@ FindUniqueOperandCommands(std::vector &UniqueOperandCommands, // Otherwise, scan to see if all of the other instructions in this command // set share the operand. bool AllSame = true; - // Keep track of the maximum, number of operands or any - // instruction we see in the group. - size_t MaxSize = FirstInst->Operands.size(); for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx); NIT != InstIdxs.end(); @@ -220,10 +217,6 @@ FindUniqueOperandCommands(std::vector &UniqueOperandCommands, const AsmWriterInst *OtherInst = getAsmWriterInstByID(NIT-InstIdxs.begin()); - if (OtherInst && - OtherInst->Operands.size() > FirstInst->Operands.size()) - MaxSize = std::max(MaxSize, OtherInst->Operands.size()); - if (!OtherInst || OtherInst->Operands.size() == Op || OtherInst->Operands[Op] != FirstInst->Operands[Op]) { AllSame = false; @@ -350,7 +343,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { // in the opcode-indexed table. unsigned BitsLeft = 64-AsmStrBits; - std::vector > TableDrivenOperandPrinters; + std::vector> TableDrivenOperandPrinters; while (1) { std::vector UniqueOperandCommands; @@ -393,7 +386,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { } // Remember the handlers for this set of operands. - TableDrivenOperandPrinters.push_back(UniqueOperandCommands); + TableDrivenOperandPrinters.push_back(std::move(UniqueOperandCommands)); } @@ -474,7 +467,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << " switch ((Bits >> " << (64-BitsLeft) << ") & " << ((1 << NumBits)-1) << ") {\n" - << " default: // unreachable.\n"; + << " default: llvm_unreachable(\"Invalid command number.\");\n"; // Print out all the cases. for (unsigned i = 0, e = Commands.size(); i != e; ++i) { @@ -520,14 +513,23 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { O << "}\n"; } +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + static void emitRegisterNameString(raw_ostream &O, StringRef AltName, - const std::vector &Registers) { + const std::deque &Registers) { SequenceToOffsetTable StringTable; SmallVector AsmNames(Registers.size()); - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Registers[i]; - std::string &AsmName = AsmNames[i]; + unsigned i = 0; + for (const auto &Reg : Registers) { + std::string &AsmName = AsmNames[i++]; // "NoRegAltName" is special. We don't need to do a lookup for that, // as it's just a reference to the default register name. @@ -564,7 +566,8 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, StringTable.emit(O, printChar); O << " };\n\n"; - O << " static const uint32_t RegAsmOffset" << AltName << "[] = {"; + O << " static const " << getMinimalTypeForRange(StringTable.size()-1) + << " RegAsmOffset" << AltName << "[] = {"; for (unsigned i = 0, e = Registers.size(); i != e; ++i) { if ((i % 14) == 0) O << "\n "; @@ -577,8 +580,7 @@ emitRegisterNameString(raw_ostream &O, StringRef AltName, void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { Record *AsmWriter = Target.getAsmWriter(); std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); - const std::vector &Registers = - Target.getRegBank().getRegisters(); + const auto &Registers = Target.getRegBank().getRegisters(); std::vector AltNameIndices = Target.getRegAltNameIndices(); bool hasAltNames = AltNameIndices.size() > 1; @@ -602,26 +604,25 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { emitRegisterNameString(O, "", Registers); if (hasAltNames) { - O << " const uint32_t *RegAsmOffset;\n" - << " const char *AsmStrs;\n" - << " switch(AltIdx) {\n" + O << " switch(AltIdx) {\n" << " default: llvm_unreachable(\"Invalid register alt name index!\");\n"; for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) { std::string Namespace = AltNameIndices[1]->getValueAsString("Namespace"); std::string AltName(AltNameIndices[i]->getName()); - O << " case " << Namespace << "::" << AltName - << ":\n" - << " AsmStrs = AsmStrs" << AltName << ";\n" - << " RegAsmOffset = RegAsmOffset" << AltName << ";\n" - << " break;\n"; + O << " case " << Namespace << "::" << AltName << ":\n" + << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" + << AltName << "[RegNo-1]) &&\n" + << " \"Invalid alt name index for register!\");\n" + << " return AsmStrs" << AltName << "+RegAsmOffset" + << AltName << "[RegNo-1];\n"; } - O << "}\n"; + O << " }\n"; + } else { + O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n" + << " \"Invalid alt name index for register!\");\n" + << " return AsmStrs+RegAsmOffset[RegNo-1];\n"; } - - O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n" - << " \"Invalid alt name index for register!\");\n" - << " return AsmStrs+RegAsmOffset[RegNo-1];\n" - << "}\n"; + O << "}\n"; } namespace { @@ -654,20 +655,26 @@ public: std::pair parseName(StringRef::iterator Start, StringRef::iterator End) { StringRef::iterator I = Start; + StringRef::iterator Next; if (*I == '{') { // ${some_name} Start = ++I; while (I != End && *I != '}') ++I; + Next = I; + // eat the final '}' + if (Next != End) + ++Next; } else { // $name, just eat the usual suspects. while (I != End && ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') || (*I >= '0' && *I <= '9') || *I == '_')) ++I; + Next = I; } - return std::make_pair(StringRef(Start, I - Start), I); + return std::make_pair(StringRef(Start, I - Start), Next); } void print(raw_ostream &O) { @@ -1084,13 +1091,10 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) { Record *AsmWriter = Target.getAsmWriter(); - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); - I != E; ++I) - if (!(*I)->AsmString.empty() && (*I)->TheDef->getName() != "PHI") + for (const CodeGenInstruction *I : Target.instructions()) + if (!I->AsmString.empty() && I->TheDef->getName() != "PHI") Instructions.push_back( - AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"), - AsmWriter->getValueAsInt("OperandSpacing"))); + AsmWriterInst(*I, AsmWriter->getValueAsInt("Variant"))); // Get the instruction numbering. NumberedInstructions = &Target.getInstructionsByEnumValue(); diff --git a/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp index 5d9ead1..6ddc510 100644 --- a/utils/TableGen/AsmWriterInst.cpp +++ b/utils/TableGen/AsmWriterInst.cpp @@ -48,9 +48,7 @@ std::string AsmWriterOperand::getCode() const { /// ParseAsmString - Parse the specified Instruction's AsmString into this /// AsmWriterInst. /// -AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, - unsigned Variant, - int OperandSpacing) { +AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { this->CGI = &CGI; // NOTE: Any extensions to this code need to be mirrored in the diff --git a/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h index 4cee352..6a900b7 100644 --- a/utils/TableGen/AsmWriterInst.h +++ b/utils/TableGen/AsmWriterInst.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef ASMWRITER_INST_H -#define ASMWRITER_INST_H +#ifndef LLVM_UTILS_TABLEGEN_ASMWRITERINST_H +#define LLVM_UTILS_TABLEGEN_ASMWRITERINST_H #include #include @@ -88,8 +88,7 @@ namespace llvm { const CodeGenInstruction *CGI; AsmWriterInst(const CodeGenInstruction &CGI, - unsigned Variant, - int OperandSpacing); + unsigned Variant); /// MatchesAllButOneOp - If this instruction is exactly identical to the /// specified instruction except for one differing operand, return the diff --git a/utils/TableGen/CTagsEmitter.cpp b/utils/TableGen/CTagsEmitter.cpp index 5d6d6da..bbed92a1 100644 --- a/utils/TableGen/CTagsEmitter.cpp +++ b/utils/TableGen/CTagsEmitter.cpp @@ -69,19 +69,15 @@ SMLoc CTagsEmitter::locate(const Record *R) { } void CTagsEmitter::run(raw_ostream &OS) { - const std::map &Classes = Records.getClasses(); - const std::map &Defs = Records.getDefs(); + const auto &Classes = Records.getClasses(); + const auto &Defs = Records.getDefs(); std::vector Tags; // Collect tags. Tags.reserve(Classes.size() + Defs.size()); - for (std::map::const_iterator I = Classes.begin(), - E = Classes.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); - for (std::map::const_iterator I = Defs.begin(), - E = Defs.end(); - I != E; ++I) - Tags.push_back(Tag(I->first, locate(I->second))); + for (const auto &C : Classes) + Tags.push_back(Tag(C.first, locate(C.second.get()))); + for (const auto &D : Defs) + Tags.push_back(Tag(D.first, locate(D.second.get()))); // Emit tags. std::sort(Tags.begin(), Tags.end()); OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n"; diff --git a/utils/TableGen/CallingConvEmitter.cpp b/utils/TableGen/CallingConvEmitter.cpp index ec2251d..6a65e5e 100644 --- a/utils/TableGen/CallingConvEmitter.cpp +++ b/utils/TableGen/CallingConvEmitter.cpp @@ -181,13 +181,17 @@ void CallingConvEmitter::EmitAction(Record *Action, if (Size) O << Size << ", "; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())), "; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext()))," + " "; if (Align) O << Align; else - O << "\n" << IndentStr << " State.getTarget().getDataLayout()" - "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()))"; + O << "\n" << IndentStr + << " State.getMachineFunction().getSubtarget().getDataLayout()" + "->getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()" + "))"; O << ");\n" << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset" << Counter << ", LocVT, LocInfo));\n"; diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp index 4d0c0ca..11911b6 100644 --- a/utils/TableGen/CodeEmitterGen.cpp +++ b/utils/TableGen/CodeEmitterGen.cpp @@ -24,14 +24,6 @@ #include using namespace llvm; -// FIXME: Somewhat hackish to use a command line option for this. There should -// be a CodeEmitter class in the Target.td that controls this sort of thing -// instead. -static cl::opt -MCEmitter("mc-emitter", - cl::desc("Generate CodeEmitter for use with the MC library."), - cl::init(false)); - namespace { class CodeEmitterGen { @@ -134,15 +126,13 @@ AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName, if (SO.second == 0) { Case += " // op: " + VarName + "\n" + " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx); - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } } else { Case += " // op: " + VarName + "\n" + " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")"; - if (MCEmitter) - Case += ", Fixups, STI"; + Case += ", Fixups, STI"; Case += ");\n"; } @@ -223,8 +213,7 @@ std::string CodeEmitterGen::getInstructionCase(Record *R, std::string PostEmitter = R->getValueAsString("PostEncoderMethod"); if (!PostEmitter.empty()) { Case += " Value = " + PostEmitter + "(MI, Value"; - if (MCEmitter) - Case += ", STI"; + Case += ", STI"; Case += ");\n"; } @@ -243,12 +232,9 @@ void CodeEmitterGen::run(raw_ostream &o) { // Emit function declaration o << "uint64_t " << Target.getName(); - if (MCEmitter) - o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" - << " SmallVectorImpl &Fixups,\n" - << " const MCSubtargetInfo &STI) const {\n"; - else - o << "CodeEmitter::getBinaryCodeForInstr(const MachineInstr &MI) const {\n"; + o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n" + << " SmallVectorImpl &Fixups,\n" + << " const MCSubtargetInfo &STI) const {\n"; // Emit instruction base values o << " static const uint64_t InstBits[] = {\n"; diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp index 2602bbc..c3de37e 100644 --- a/utils/TableGen/CodeGenDAGPatterns.cpp +++ b/utils/TableGen/CodeGenDAGPatterns.cpp @@ -771,7 +771,7 @@ static unsigned getPatternSize(const TreePatternNode *P, /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. -unsigned PatternToMatch:: +int PatternToMatch:: getPatternComplexity(const CodeGenDAGPatterns &CGP) const { return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity(); } @@ -1387,7 +1387,7 @@ static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo, if (R->isSubClassOf("SubRegIndex")) { assert(ResNo == 0 && "SubRegisterIndices only produce one result!"); - return EEVT::TypeSet(); + return EEVT::TypeSet(MVT::i32, TP); } if (R->isSubClassOf("ValueType")) { @@ -1529,6 +1529,31 @@ TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const { return false; } +static bool isOperandClass(const TreePatternNode *N, StringRef Class) { + if (!N->isLeaf()) + return N->getOperator()->isSubClassOf(Class); + + DefInit *DI = dyn_cast(N->getLeafValue()); + if (DI && DI->getDef()->isSubClassOf(Class)) + return true; + + return false; +} + +static void emitTooManyOperandsError(TreePattern &TP, + StringRef InstName, + unsigned Expected, + unsigned Actual) { + TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) + + " operands but expected only " + Twine(Expected) + "!"); +} + +static void emitTooFewOperandsError(TreePattern &TP, + StringRef InstName, + unsigned Actual) { + TP.error("Instruction '" + InstName + + "' expects more than the provided " + Twine(Actual) + " operands!"); +} /// ApplyTypeConstraints - Apply all of the type constraints relevant to /// this node and its children in the tree. This returns true if it makes a @@ -1689,6 +1714,34 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled"); MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP); MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP); + } else if (getOperator()->getName() == "REG_SEQUENCE") { + // We need to do extra, custom typechecking for REG_SEQUENCE since it is + // variadic. + + unsigned NChild = getNumChildren(); + if (NChild < 3) { + TP.error("REG_SEQUENCE requires at least 3 operands!"); + return false; + } + + if (NChild % 2 == 0) { + TP.error("REG_SEQUENCE requires an odd number of operands!"); + return false; + } + + if (!isOperandClass(getChild(0), "RegisterClass")) { + TP.error("REG_SEQUENCE requires a RegisterClass for first operand!"); + return false; + } + + for (unsigned I = 1; I < NChild; I += 2) { + TreePatternNode *SubIdxChild = getChild(I + 1); + if (!isOperandClass(SubIdxChild, "SubRegIndex")) { + TP.error("REG_SEQUENCE requires a SubRegIndex for operand " + + itostr(I + 1) + "!"); + return false; + } + } } unsigned ChildNo = 0; @@ -1704,8 +1757,7 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // Verify that we didn't run out of provided operands. if (ChildNo >= getNumChildren()) { - TP.error("Instruction '" + getOperator()->getName() + - "' expects more operands than were provided."); + emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren()); return false; } @@ -1729,8 +1781,8 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { // And the remaining sub-operands against subsequent children. for (unsigned Arg = 1; Arg < NumArgs; ++Arg) { if (ChildNo >= getNumChildren()) { - TP.error("Instruction '" + getOperator()->getName() + - "' expects more operands than were provided."); + emitTooFewOperandsError(TP, getOperator()->getName(), + getNumChildren()); return false; } Child = getChild(ChildNo++); @@ -1749,9 +1801,9 @@ bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) { MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP); } - if (ChildNo != getNumChildren()) { - TP.error("Instruction '" + getOperator()->getName() + - "' was provided too many operands!"); + if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) { + emitTooManyOperandsError(TP, getOperator()->getName(), + ChildNo, getNumChildren()); return false; } @@ -1871,7 +1923,7 @@ TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput, Trees.push_back(Pat); } -void TreePattern::error(const std::string &Msg) { +void TreePattern::error(const Twine &Msg) { if (HasError) return; dump(); @@ -2226,13 +2278,6 @@ CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : VerifyInstructionFlags(); } -CodeGenDAGPatterns::~CodeGenDAGPatterns() { - for (pf_iterator I = PatternFragments.begin(), - E = PatternFragments.end(); I != E; ++I) - delete I->second; -} - - Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const { Record *N = Records.getDef(Name); if (!N || !N->isSubClassOf("SDNode")) { @@ -2294,9 +2339,9 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { DagInit *Tree = Fragments[i]->getValueAsDag("Fragment"); TreePattern *P = - new TreePattern(Fragments[i], Tree, - !Fragments[i]->isSubClassOf("OutPatFrag"), *this); - PatternFragments[Fragments[i]] = P; + (PatternFragments[Fragments[i]] = llvm::make_unique( + Fragments[i], Tree, !Fragments[i]->isSubClassOf("OutPatFrag"), + *this)).get(); // Validate the argument list, converting it to set, to discard duplicates. std::vector &Args = P->getArgList(); @@ -2354,16 +2399,16 @@ void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) { if (OutFrags != Fragments[i]->isSubClassOf("OutPatFrag")) continue; - TreePattern *ThePat = PatternFragments[Fragments[i]]; - ThePat->InlinePatternFragments(); + TreePattern &ThePat = *PatternFragments[Fragments[i]]; + ThePat.InlinePatternFragments(); // Infer as many types as possible. Don't worry about it if we don't infer // all of them, some may depend on the inputs of the pattern. - ThePat->InferAllTypes(); - ThePat->resetError(); + ThePat.InferAllTypes(); + ThePat.resetError(); // If debugging, print out the pattern fragment result. - DEBUG(ThePat->dump()); + DEBUG(ThePat.dump()); } } @@ -2524,8 +2569,10 @@ FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat, I->error("set destination should be a register!"); DefInit *Val = dyn_cast(Dest->getLeafValue()); - if (!Val) + if (!Val) { I->error("set destination should be a register!"); + continue; + } if (Val->getDef()->isSubClassOf("RegisterClass") || Val->getDef()->isSubClassOf("ValueType") || @@ -3081,13 +3128,6 @@ void CodeGenDAGPatterns::InferInstructionFlags() { CodeGenInstruction &InstInfo = const_cast(*Instructions[i]); - // Treat neverHasSideEffects = 1 as the equivalent of hasSideEffects = 0. - // This flag is obsolete and will be removed. - if (InstInfo.neverHasSideEffects) { - assert(!InstInfo.hasSideEffects); - InstInfo.hasSideEffects_Unset = false; - } - // Get the primary instruction pattern. const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern(); if (!Pattern) { @@ -3274,14 +3314,14 @@ void CodeGenDAGPatterns::ParsePatterns() { if (LI->getSize() == 0) continue; // no pattern. // Parse the instruction. - TreePattern *Result = new TreePattern(CurPattern, LI, false, *this); + TreePattern Result(CurPattern, LI, false, *this); // Inline pattern fragments into it. - Result->InlinePatternFragments(); + Result.InlinePatternFragments(); - if (Result->getNumTrees() != 1) - Result->error("Cannot handle instructions producing instructions " - "with temporaries yet!"); + if (Result.getNumTrees() != 1) + Result.error("Cannot handle instructions producing instructions " + "with temporaries yet!"); bool IterateInference; bool InferredAllPatternTypes, InferredAllResultTypes; @@ -3294,7 +3334,7 @@ void CodeGenDAGPatterns::ParsePatterns() { // Infer as many types as possible. If we cannot infer all of them, we // can never do anything with this pattern: report it to the user. InferredAllResultTypes = - Result->InferAllTypes(&Pattern->getNamedNodesMap()); + Result.InferAllTypes(&Pattern->getNamedNodesMap()); IterateInference = false; @@ -3302,13 +3342,13 @@ void CodeGenDAGPatterns::ParsePatterns() { // resolve cases where the input type is known to be a pointer type (which // is considered resolved), but the result knows it needs to be 32- or // 64-bits. Infer the other way for good measure. - for (unsigned i = 0, e = std::min(Result->getTree(0)->getNumTypes(), + for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(), Pattern->getTree(0)->getNumTypes()); i != e; ++i) { - IterateInference = Pattern->getTree(0)-> - UpdateNodeType(i, Result->getTree(0)->getExtType(i), *Result); - IterateInference |= Result->getTree(0)-> - UpdateNodeType(i, Pattern->getTree(0)->getExtType(i), *Result); + IterateInference = Pattern->getTree(0)->UpdateNodeType( + i, Result.getTree(0)->getExtType(i), Result); + IterateInference |= Result.getTree(0)->UpdateNodeType( + i, Pattern->getTree(0)->getExtType(i), Result); } // If our iteration has converged and the input pattern's types are fully @@ -3322,8 +3362,8 @@ void CodeGenDAGPatterns::ParsePatterns() { // arbitrary types to the result pattern's nodes. if (!IterateInference && InferredAllPatternTypes && !InferredAllResultTypes) - IterateInference = ForceArbitraryInstResultType(Result->getTree(0), - *Result); + IterateInference = + ForceArbitraryInstResultType(Result.getTree(0), Result); } while (IterateInference); // Verify that we inferred enough types that we can do something with the @@ -3332,7 +3372,7 @@ void CodeGenDAGPatterns::ParsePatterns() { Pattern->error("Could not infer all types in pattern!"); if (!InferredAllResultTypes) { Pattern->dump(); - Result->error("Could not infer all types in pattern result!"); + Result.error("Could not infer all types in pattern result!"); } // Validate that the input pattern is correct. @@ -3345,7 +3385,7 @@ void CodeGenDAGPatterns::ParsePatterns() { InstImpResults); // Promote the xform function to be an explicit node if set. - TreePatternNode *DstPattern = Result->getOnlyTree(); + TreePatternNode *DstPattern = Result.getOnlyTree(); std::vector ResultNodeOperands; for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) { TreePatternNode *OpNode = DstPattern->getChild(ii); @@ -3357,16 +3397,16 @@ void CodeGenDAGPatterns::ParsePatterns() { } ResultNodeOperands.push_back(OpNode); } - DstPattern = Result->getOnlyTree(); + DstPattern = Result.getOnlyTree(); if (!DstPattern->isLeaf()) DstPattern = new TreePatternNode(DstPattern->getOperator(), ResultNodeOperands, DstPattern->getNumTypes()); - for (unsigned i = 0, e = Result->getOnlyTree()->getNumTypes(); i != e; ++i) - DstPattern->setType(i, Result->getOnlyTree()->getExtType(i)); + for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i) + DstPattern->setType(i, Result.getOnlyTree()->getExtType(i)); - TreePattern Temp(Result->getRecord(), DstPattern, false, *this); + TreePattern Temp(Result.getRecord(), DstPattern, false, *this); Temp.InferAllTypes(); diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h index fb30cdd..c0812cf 100644 --- a/utils/TableGen/CodeGenDAGPatterns.h +++ b/utils/TableGen/CodeGenDAGPatterns.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_DAGPATTERNS_H -#define CODEGEN_DAGPATTERNS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H +#define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H #include "CodeGenIntrinsics.h" #include "CodeGenTarget.h" @@ -597,7 +597,7 @@ public: /// error - If this is the first error in the current resolution step, /// print it and set the error flag. Otherwise, continue silently. - void error(const std::string &Msg); + void error(const Twine &Msg); bool hasError() const { return HasError; } @@ -667,7 +667,7 @@ public: PatternToMatch(Record *srcrecord, ListInit *preds, TreePatternNode *src, TreePatternNode *dst, const std::vector &dstregs, - unsigned complexity, unsigned uid) + int complexity, unsigned uid) : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst), Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {} @@ -676,7 +676,7 @@ public: TreePatternNode *SrcPattern; // Source pattern to match. TreePatternNode *DstPattern; // Resulting pattern. std::vector Dstregs; // Physical register defs being matched. - unsigned AddedComplexity; // Add to matching pattern complexity. + int AddedComplexity; // Add to matching pattern complexity. unsigned ID; // Unique ID for the record. Record *getSrcRecord() const { return SrcRecord; } @@ -684,13 +684,13 @@ public: TreePatternNode *getSrcPattern() const { return SrcPattern; } TreePatternNode *getDstPattern() const { return DstPattern; } const std::vector &getDstRegs() const { return Dstregs; } - unsigned getAddedComplexity() const { return AddedComplexity; } + int getAddedComplexity() const { return AddedComplexity; } std::string getPredicateCheck() const; /// Compute the complexity metric for the input pattern. This roughly /// corresponds to the number of nodes that are covered. - unsigned getPatternComplexity(const CodeGenDAGPatterns &CGP) const; + int getPatternComplexity(const CodeGenDAGPatterns &CGP) const; }; class CodeGenDAGPatterns { @@ -702,7 +702,8 @@ class CodeGenDAGPatterns { std::map SDNodes; std::map, LessRecordByID> SDNodeXForms; std::map ComplexPatterns; - std::map PatternFragments; + std::map, LessRecordByID> + PatternFragments; std::map DefaultOperands; std::map Instructions; @@ -716,7 +717,6 @@ class CodeGenDAGPatterns { std::vector PatternsToMatch; public: CodeGenDAGPatterns(RecordKeeper &R); - ~CodeGenDAGPatterns(); CodeGenTarget &getTargetInfo() { return Target; } const CodeGenTarget &getTargetInfo() const { return Target; } @@ -778,15 +778,16 @@ public: // Pattern Fragment information. TreePattern *getPatternFragment(Record *R) const { assert(PatternFragments.count(R) && "Invalid pattern fragment request!"); - return PatternFragments.find(R)->second; + return PatternFragments.find(R)->second.get(); } TreePattern *getPatternFragmentIfRead(Record *R) const { - if (!PatternFragments.count(R)) return nullptr; - return PatternFragments.find(R)->second; + if (!PatternFragments.count(R)) + return nullptr; + return PatternFragments.find(R)->second.get(); } - typedef std::map::const_iterator - pf_iterator; + typedef std::map, + LessRecordByID>::const_iterator pf_iterator; pf_iterator pf_begin() const { return PatternFragments.begin(); } pf_iterator pf_end() const { return PatternFragments.end(); } diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp index 2577ad4..1060296 100644 --- a/utils/TableGen/CodeGenInstruction.cpp +++ b/utils/TableGen/CodeGenInstruction.cpp @@ -68,10 +68,13 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { std::string PrintMethod = "printOperand"; std::string EncoderMethod; std::string OperandType = "OPERAND_UNKNOWN"; + std::string OperandNamespace = "MCOI"; unsigned NumOps = 1; DagInit *MIOpInfo = nullptr; if (Rec->isSubClassOf("RegisterOperand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); + OperandType = Rec->getValueAsString("OperandType"); + OperandNamespace = Rec->getValueAsString("OperandNamespace"); } else if (Rec->isSubClassOf("Operand")) { PrintMethod = Rec->getValueAsString("PrintMethod"); OperandType = Rec->getValueAsString("OperandType"); @@ -113,8 +116,8 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { Twine(i) + " has the same name as a previous operand!"); OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod, - OperandType, MIOperandNo, NumOps, - MIOpInfo)); + OperandNamespace + "::" + OperandType, + MIOperandNo, NumOps, MIOpInfo)); MIOperandNo += NumOps; } @@ -314,6 +317,9 @@ CodeGenInstruction::CodeGenInstruction(Record *R) hasPostISelHook = R->getValueAsBit("hasPostISelHook"); hasCtrlDep = R->getValueAsBit("hasCtrlDep"); isNotDuplicable = R->getValueAsBit("isNotDuplicable"); + isRegSequence = R->getValueAsBit("isRegSequence"); + isExtractSubreg = R->getValueAsBit("isExtractSubreg"); + isInsertSubreg = R->getValueAsBit("isInsertSubreg"); bool Unset; mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset); @@ -322,7 +328,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R) mayStore_Unset = Unset; hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset); hasSideEffects_Unset = Unset; - neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); @@ -332,9 +337,6 @@ CodeGenInstruction::CodeGenInstruction(Record *R) ImplicitDefs = R->getValueAsListOfDefs("Defs"); ImplicitUses = R->getValueAsListOfDefs("Uses"); - if (neverHasSideEffects + hasSideEffects > 1) - PrintFatalError(R->getName() + ": multiple conflicting side-effect flags set!"); - // Parse Constraints. ParseConstraints(R->getValueAsString("Constraints"), Operands); @@ -520,10 +522,25 @@ bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo, return true; } + // Bits (also used for 0bxx literals) + if (BitsInit *BI = dyn_cast(Arg)) { + if (hasSubOps || !InstOpRec->isSubClassOf("Operand")) + return false; + if (!BI->isComplete()) + return false; + // Convert the bits init to an integer and use that for the result. + IntInit *II = + dyn_cast_or_null(BI->convertInitializerTo(IntRecTy::get())); + if (!II) + return false; + ResOp = ResultOperand(II->getValue()); + return true; + } + // If both are Operands with the same MVT, allow the conversion. It's // up to the user to make sure the values are appropriate, just like // for isel Pat's. - if (InstOpRec->isSubClassOf("Operand") && + if (InstOpRec->isSubClassOf("Operand") && ADI && ADI->getDef()->isSubClassOf("Operand")) { // FIXME: What other attributes should we check here? Identical // MIOperandInfo perhaps? diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index f143875..bdbe546 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INSTRUCTION_H -#define CODEGEN_INSTRUCTION_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H +#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H #include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineValueType.h" @@ -247,12 +247,14 @@ namespace llvm { bool isNotDuplicable : 1; bool hasSideEffects : 1; bool hasSideEffects_Unset : 1; - bool neverHasSideEffects : 1; bool isAsCheapAsAMove : 1; bool hasExtraSrcRegAllocReq : 1; bool hasExtraDefRegAllocReq : 1; bool isCodeGenOnly : 1; bool isPseudo : 1; + bool isRegSequence : 1; + bool isExtractSubreg : 1; + bool isInsertSubreg : 1; std::string DeprecatedReason; bool HasComplexDeprecationPredicate; diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h index a9ece01..1f1adf1 100644 --- a/utils/TableGen/CodeGenIntrinsics.h +++ b/utils/TableGen/CodeGenIntrinsics.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_INTRINSIC_H -#define CODEGEN_INTRINSIC_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H +#define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H #include "llvm/CodeGen/MachineValueType.h" #include diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index 8099f13..bef8a4b 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -82,7 +82,7 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { } } -unsigned CodeGenSubRegIndex::computeLaneMask() { +unsigned CodeGenSubRegIndex::computeLaneMask() const { // Already computed? if (LaneMask) return LaneMask; @@ -92,8 +92,8 @@ unsigned CodeGenSubRegIndex::computeLaneMask() { // The lane mask is simply the union of all sub-indices. unsigned M = 0; - for (CompMap::iterator I = Composed.begin(), E = Composed.end(); I != E; ++I) - M |= I->second->computeLaneMask(); + for (const auto &C : Composed) + M |= C.second->computeLaneMask(); assert(M && "Missing lane mask, sub-register cycle?"); LaneMask = M; return LaneMask; @@ -146,6 +146,7 @@ void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) { } const std::string &CodeGenRegister::getName() const { + assert(TheDef && "no def"); return TheDef->getName(); } @@ -661,7 +662,8 @@ CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R) : TheDef(R), Name(R->getName()), TopoSigs(RegBank.getNumTopoSigs()), - EnumValue(-1) { + EnumValue(-1), + LaneMask(0) { // Rename anonymous register classes. if (R->getName().size() > 9 && R->getName()[9] == '.') { static unsigned AnonCounter = 0; @@ -810,34 +812,34 @@ static bool testSubClass(const CodeGenRegisterClass *A, /// Register classes with the same registers, spill size, and alignment form a /// clique. They will be ordered alphabetically. /// -static int TopoOrderRC(CodeGenRegisterClass *const *PA, - CodeGenRegisterClass *const *PB) { - const CodeGenRegisterClass *A = *PA; - const CodeGenRegisterClass *B = *PB; +static bool TopoOrderRC(const CodeGenRegisterClass &PA, + const CodeGenRegisterClass &PB) { + auto *A = &PA; + auto *B = &PB; if (A == B) return 0; // Order by ascending spill size. if (A->SpillSize < B->SpillSize) - return -1; + return true; if (A->SpillSize > B->SpillSize) - return 1; + return false; // Order by ascending spill alignment. if (A->SpillAlignment < B->SpillAlignment) - return -1; + return true; if (A->SpillAlignment > B->SpillAlignment) - return 1; + return false; // Order by descending set size. Note that the classes' allocation order may // not have been computed yet. The Members set is always vaild. if (A->getMembers().size() > B->getMembers().size()) - return -1; + return true; if (A->getMembers().size() < B->getMembers().size()) - return 1; + return false; // Finally order by name as a tie breaker. - return StringRef(A->getName()).compare(B->getName()); + return StringRef(A->getName()) < B->getName(); } std::string CodeGenRegisterClass::getQualifiedName() const { @@ -850,60 +852,60 @@ std::string CodeGenRegisterClass::getQualifiedName() const { // Compute sub-classes of all register classes. // Assume the classes are ordered topologically. void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) { - ArrayRef RegClasses = RegBank.getRegClasses(); + auto &RegClasses = RegBank.getRegClasses(); // Visit backwards so sub-classes are seen first. - for (unsigned rci = RegClasses.size(); rci; --rci) { - CodeGenRegisterClass &RC = *RegClasses[rci - 1]; + for (auto I = RegClasses.rbegin(), E = RegClasses.rend(); I != E; ++I) { + CodeGenRegisterClass &RC = *I; RC.SubClasses.resize(RegClasses.size()); RC.SubClasses.set(RC.EnumValue); // Normally, all subclasses have IDs >= rci, unless RC is part of a clique. - for (unsigned s = rci; s != RegClasses.size(); ++s) { - if (RC.SubClasses.test(s)) + for (auto I2 = I.base(), E2 = RegClasses.end(); I2 != E2; ++I2) { + CodeGenRegisterClass &SubRC = *I2; + if (RC.SubClasses.test(SubRC.EnumValue)) continue; - CodeGenRegisterClass *SubRC = RegClasses[s]; - if (!testSubClass(&RC, SubRC)) + if (!testSubClass(&RC, &SubRC)) continue; // SubRC is a sub-class. Grap all its sub-classes so we won't have to // check them again. - RC.SubClasses |= SubRC->SubClasses; + RC.SubClasses |= SubRC.SubClasses; } // Sweep up missed clique members. They will be immediately preceding RC. - for (unsigned s = rci - 1; s && testSubClass(&RC, RegClasses[s - 1]); --s) - RC.SubClasses.set(s - 1); + for (auto I2 = std::next(I); I2 != E && testSubClass(&RC, &*I2); ++I2) + RC.SubClasses.set(I2->EnumValue); } // Compute the SuperClasses lists from the SubClasses vectors. - for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { - const BitVector &SC = RegClasses[rci]->getSubClasses(); - for (int s = SC.find_first(); s >= 0; s = SC.find_next(s)) { - if (unsigned(s) == rci) + for (auto &RC : RegClasses) { + const BitVector &SC = RC.getSubClasses(); + auto I = RegClasses.begin(); + for (int s = 0, next_s = SC.find_first(); next_s != -1; + next_s = SC.find_next(s)) { + std::advance(I, next_s - s); + s = next_s; + if (&*I == &RC) continue; - RegClasses[s]->SuperClasses.push_back(RegClasses[rci]); + I->SuperClasses.push_back(&RC); } } // With the class hierarchy in place, let synthesized register classes inherit // properties from their closest super-class. The iteration order here can // propagate properties down multiple levels. - for (unsigned rci = 0; rci != RegClasses.size(); ++rci) - if (!RegClasses[rci]->getDef()) - RegClasses[rci]->inheritProperties(RegBank); + for (auto &RC : RegClasses) + if (!RC.getDef()) + RC.inheritProperties(RegBank); } -void -CodeGenRegisterClass::getSuperRegClasses(CodeGenSubRegIndex *SubIdx, - BitVector &Out) const { - DenseMap >::const_iterator - FindI = SuperRegClasses.find(SubIdx); +void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx, + BitVector &Out) const { + auto FindI = SuperRegClasses.find(SubIdx); if (FindI == SuperRegClasses.end()) return; - for (SmallPtrSet::const_iterator I = - FindI->second.begin(), E = FindI->second.end(); I != E; ++I) - Out.set((*I)->EnumValue); + for (CodeGenRegisterClass *RC : FindI->second) + Out.set(RC->EnumValue); } // Populate a unique sorted list of units from a register set. @@ -934,13 +936,12 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { for (unsigned i = 0, e = SRIs.size(); i != e; ++i) getSubRegIdx(SRIs[i]); // Build composite maps from ComposedOf fields. - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) - SubRegIndices[i]->updateComponents(*this); + for (auto &Idx : SubRegIndices) + Idx.updateComponents(*this); // Read in the register definitions. std::vector Regs = Records.getAllDerivedDefinitions("Register"); std::sort(Regs.begin(), Regs.end(), LessRecordRegister()); - Registers.reserve(Regs.size()); // Assign the enumeration values. for (unsigned i = 0, e = Regs.size(); i != e; ++i) getReg(Regs[i]); @@ -949,42 +950,41 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { std::vector Tups = Records.getAllDerivedDefinitions("RegisterTuples"); - std::vector TupRegsCopy; - for (unsigned i = 0, e = Tups.size(); i != e; ++i) { - const std::vector *TupRegs = Sets.expand(Tups[i]); - TupRegsCopy.reserve(TupRegs->size()); - TupRegsCopy.assign(TupRegs->begin(), TupRegs->end()); - std::sort(TupRegsCopy.begin(), TupRegsCopy.end(), LessRecordRegister()); - for (unsigned j = 0, je = TupRegsCopy.size(); j != je; ++j) - getReg((TupRegsCopy)[j]); - TupRegsCopy.clear(); + for (Record *R : Tups) { + std::vector TupRegs = *Sets.expand(R); + std::sort(TupRegs.begin(), TupRegs.end(), LessRecordRegister()); + for (Record *RC : TupRegs) + getReg(RC); } // Now all the registers are known. Build the object graph of explicit // register-register references. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i]->buildObjectGraph(*this); + for (auto &Reg : Registers) + Reg.buildObjectGraph(*this); // Compute register name map. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - RegistersByName.GetOrCreateValue( - Registers[i]->TheDef->getValueAsString("AsmName"), - Registers[i]); + for (auto &Reg : Registers) + // FIXME: This could just be RegistersByName[name] = register, except that + // causes some failures in MIPS - perhaps they have duplicate register name + // entries? (or maybe there's a reason for it - I don't know much about this + // code, just drive-by refactoring) + RegistersByName.insert( + std::make_pair(Reg.TheDef->getValueAsString("AsmName"), &Reg)); // Precompute all sub-register maps. // This will create Composite entries for all inferred sub-register indices. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i]->computeSubRegs(*this); + for (auto &Reg : Registers) + Reg.computeSubRegs(*this); // Infer even more sub-registers by combining leading super-registers. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - if (Registers[i]->CoveredBySubRegs) - Registers[i]->computeSecondarySubRegs(*this); + for (auto &Reg : Registers) + if (Reg.CoveredBySubRegs) + Reg.computeSecondarySubRegs(*this); // After the sub-register graph is complete, compute the topologically // ordered SuperRegs list. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - Registers[i]->computeSuperRegs(*this); + for (auto &Reg : Registers) + Reg.computeSuperRegs(*this); // Native register units are associated with a leaf register. They've all been // discovered now. @@ -996,35 +996,35 @@ CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) { PrintFatalError("No 'RegisterClass' subclasses defined!"); // Allocate user-defined register classes. - RegClasses.reserve(RCs.size()); - for (unsigned i = 0, e = RCs.size(); i != e; ++i) - addToMaps(new CodeGenRegisterClass(*this, RCs[i])); + for (auto *RC : RCs) { + RegClasses.push_back(CodeGenRegisterClass(*this, RC)); + addToMaps(&RegClasses.back()); + } // Infer missing classes to create a full algebra. computeInferredRegisterClasses(); // Order register classes topologically and assign enum values. - array_pod_sort(RegClasses.begin(), RegClasses.end(), TopoOrderRC); - for (unsigned i = 0, e = RegClasses.size(); i != e; ++i) - RegClasses[i]->EnumValue = i; + RegClasses.sort(TopoOrderRC); + unsigned i = 0; + for (auto &RC : RegClasses) + RC.EnumValue = i++; CodeGenRegisterClass::computeSubClasses(*this); } // Create a synthetic CodeGenSubRegIndex without a corresponding Record. CodeGenSubRegIndex* CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) { - CodeGenSubRegIndex *Idx = new CodeGenSubRegIndex(Name, Namespace, - SubRegIndices.size() + 1); - SubRegIndices.push_back(Idx); - return Idx; + SubRegIndices.emplace_back(Name, Namespace, SubRegIndices.size() + 1); + return &SubRegIndices.back(); } CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) { CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def]; if (Idx) return Idx; - Idx = new CodeGenSubRegIndex(Def, SubRegIndices.size() + 1); - SubRegIndices.push_back(Idx); + SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1); + Idx = &SubRegIndices.back(); return Idx; } @@ -1032,14 +1032,12 @@ CodeGenRegister *CodeGenRegBank::getReg(Record *Def) { CodeGenRegister *&Reg = Def2Reg[Def]; if (Reg) return Reg; - Reg = new CodeGenRegister(Def, Registers.size() + 1); - Registers.push_back(Reg); + Registers.emplace_back(Def, Registers.size() + 1); + Reg = &Registers.back(); return Reg; } void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) { - RegClasses.push_back(RC); - if (Record *Def = RC->getDef()) Def2RC.insert(std::make_pair(Def, RC)); @@ -1061,9 +1059,9 @@ CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC, return FoundI->second; // Sub-class doesn't exist, create a new one. - CodeGenRegisterClass *NewRC = new CodeGenRegisterClass(*this, Name, K); - addToMaps(NewRC); - return NewRC; + RegClasses.push_back(CodeGenRegisterClass(*this, Name, K)); + addToMaps(&RegClasses.back()); + return &RegClasses.back(); } CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) { @@ -1124,21 +1122,19 @@ void CodeGenRegBank::computeComposites() { // and many registers will share TopoSigs on regular architectures. BitVector TopoSigs(getNumTopoSigs()); - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - CodeGenRegister *Reg1 = Registers[i]; - + for (const auto &Reg1 : Registers) { // Skip identical subreg structures already processed. - if (TopoSigs.test(Reg1->getTopoSig())) + if (TopoSigs.test(Reg1.getTopoSig())) continue; - TopoSigs.set(Reg1->getTopoSig()); + TopoSigs.set(Reg1.getTopoSig()); - const CodeGenRegister::SubRegMap &SRM1 = Reg1->getSubRegs(); + const CodeGenRegister::SubRegMap &SRM1 = Reg1.getSubRegs(); for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(), e1 = SRM1.end(); i1 != e1; ++i1) { CodeGenSubRegIndex *Idx1 = i1->first; CodeGenRegister *Reg2 = i1->second; // Ignore identity compositions. - if (Reg1 == Reg2) + if (&Reg1 == Reg2) continue; const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs(); // Try composing Idx1 with another SubRegIndex. @@ -1150,7 +1146,7 @@ void CodeGenRegBank::computeComposites() { if (Reg2 == Reg3) continue; // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3. - CodeGenSubRegIndex *Idx3 = Reg1->getSubRegIndex(Reg3); + CodeGenSubRegIndex *Idx3 = Reg1.getSubRegIndex(Reg3); assert(Idx3 && "Sub-register doesn't have an index"); // Conflicting composition? Emit a warning but allow it. @@ -1171,15 +1167,14 @@ void CodeGenRegBank::computeComposites() { // // Conservatively share a lane mask bit if two sub-register indices overlap in // some registers, but not in others. That shouldn't happen a lot. -void CodeGenRegBank::computeSubRegIndexLaneMasks() { +void CodeGenRegBank::computeSubRegLaneMasks() { // First assign individual bits to all the leaf indices. unsigned Bit = 0; // Determine mask of lanes that cover their registers. CoveringLanes = ~0u; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - CodeGenSubRegIndex *Idx = SubRegIndices[i]; - if (Idx->getComposites().empty()) { - Idx->LaneMask = 1u << Bit; + for (auto &Idx : SubRegIndices) { + if (Idx.getComposites().empty()) { + Idx.LaneMask = 1u << Bit; // Share bit 31 in the unlikely case there are more than 32 leafs. // // Sharing bits is harmless; it allows graceful degradation in targets @@ -1194,7 +1189,71 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() { // is no longer covering its registers. CoveringLanes &= ~(1u << Bit); } else { - Idx->LaneMask = 0; + Idx.LaneMask = 0; + } + } + + // Compute transformation sequences for composeSubRegIndexLaneMask. The idea + // here is that for each possible target subregister we look at the leafs + // in the subregister graph that compose for this target and create + // transformation sequences for the lanemasks. Each step in the sequence + // consists of a bitmask and a bitrotate operation. As the rotation amounts + // are usually the same for many subregisters we can easily combine the steps + // by combining the masks. + for (const auto &Idx : SubRegIndices) { + const auto &Composites = Idx.getComposites(); + auto &LaneTransforms = Idx.CompositionLaneMaskTransform; + // Go through all leaf subregisters and find the ones that compose with Idx. + // These make out all possible valid bits in the lane mask we want to + // transform. Looking only at the leafs ensure that only a single bit in + // the mask is set. + unsigned NextBit = 0; + for (auto &Idx2 : SubRegIndices) { + // Skip non-leaf subregisters. + if (!Idx2.getComposites().empty()) + continue; + // Replicate the behaviour from the lane mask generation loop above. + unsigned SrcBit = NextBit; + unsigned SrcMask = 1u << SrcBit; + if (NextBit < 31) + ++NextBit; + assert(Idx2.LaneMask == SrcMask); + + // Get the composed subregister if there is any. + auto C = Composites.find(&Idx2); + if (C == Composites.end()) + continue; + const CodeGenSubRegIndex *Composite = C->second; + // The Composed subreg should be a leaf subreg too + assert(Composite->getComposites().empty()); + + // Create Mask+Rotate operation and merge with existing ops if possible. + unsigned DstBit = Log2_32(Composite->LaneMask); + int Shift = DstBit - SrcBit; + uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift; + for (auto &I : LaneTransforms) { + if (I.RotateLeft == RotateLeft) { + I.Mask |= SrcMask; + SrcMask = 0; + } + } + if (SrcMask != 0) { + MaskRolPair MaskRol = { SrcMask, RotateLeft }; + LaneTransforms.push_back(MaskRol); + } + } + // Optimize if the transformation consists of one step only: Set mask to + // 0xffffffff (including some irrelevant invalid bits) so that it should + // merge with more entries later while compressing the table. + if (LaneTransforms.size() == 1) + LaneTransforms[0].Mask = ~0u; + + // Further compression optimization: For invalid compositions resulting + // in a sequence with 0 entries we can just pick any other. Choose + // Mask 0xffffffff with Rotation 0. + if (LaneTransforms.size() == 0) { + MaskRolPair P = { ~0u, 0 }; + LaneTransforms.push_back(P); } } @@ -1202,13 +1261,24 @@ void CodeGenRegBank::computeSubRegIndexLaneMasks() { // by the sub-register graph? This doesn't occur in any known targets. // Inherit lanes from composites. - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - unsigned Mask = SubRegIndices[i]->computeLaneMask(); + for (const auto &Idx : SubRegIndices) { + unsigned Mask = Idx.computeLaneMask(); // If some super-registers without CoveredBySubRegs use this index, we can // no longer assume that the lanes are covering their registers. - if (!SubRegIndices[i]->AllSuperRegsCovered) + if (!Idx.AllSuperRegsCovered) CoveringLanes &= ~Mask; } + + // Compute lane mask combinations for register classes. + for (auto &RegClass : RegClasses) { + unsigned LaneMask = 0; + for (const auto &SubRegIndex : SubRegIndices) { + if (RegClass.getSubClassWithSubReg(&SubRegIndex) != &RegClass) + continue; + LaneMask |= SubRegIndex.LaneMask; + } + RegClass.LaneMask = LaneMask; + } } namespace { @@ -1245,22 +1315,20 @@ static void computeUberSets(std::vector &UberSets, std::vector &RegSets, CodeGenRegBank &RegBank) { - const std::vector &Registers = RegBank.getRegisters(); + const auto &Registers = RegBank.getRegisters(); // The Register EnumValue is one greater than its index into Registers. - assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + assert(Registers.size() == Registers.back().EnumValue && "register enum value mismatch"); // For simplicitly make the SetID the same as EnumValue. IntEqClasses UberSetIDs(Registers.size()+1); std::set AllocatableRegs; - for (unsigned i = 0, e = RegBank.getRegClasses().size(); i != e; ++i) { - - CodeGenRegisterClass *RegClass = RegBank.getRegClasses()[i]; - if (!RegClass->Allocatable) + for (auto &RegClass : RegBank.getRegClasses()) { + if (!RegClass.Allocatable) continue; - const CodeGenRegister::Set &Regs = RegClass->getMembers(); + const CodeGenRegister::Set &Regs = RegClass.getMembers(); if (Regs.empty()) continue; @@ -1275,8 +1343,8 @@ static void computeUberSets(std::vector &UberSets, } } // Combine non-allocatable regs. - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - unsigned RegNum = Registers[i]->EnumValue; + for (const auto &Reg : Registers) { + unsigned RegNum = Reg.EnumValue; if (AllocatableRegs.count(RegNum)) continue; @@ -1290,17 +1358,17 @@ static void computeUberSets(std::vector &UberSets, // Insert Registers into the UberSets formed by union-find. // Do not resize after this. UberSets.resize(UberSetIDs.getNumClasses()); - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { - const CodeGenRegister *Reg = Registers[i]; - unsigned USetID = UberSetIDs[Reg->EnumValue]; + unsigned i = 0; + for (const CodeGenRegister &Reg : Registers) { + unsigned USetID = UberSetIDs[Reg.EnumValue]; if (!USetID) USetID = ZeroID; else if (USetID == ZeroID) USetID = 0; UberRegSet *USet = &UberSets[USetID]; - USet->Regs.insert(Reg); - RegSets[i] = USet; + USet->Regs.insert(&Reg); + RegSets[i++] = USet; } } @@ -1333,11 +1401,8 @@ static void computeUberWeights(std::vector &UberSets, if (I->Weight != MaxWeight) { DEBUG( dbgs() << "UberSet " << I - UberSets.begin() << " Weight " << MaxWeight; - for (CodeGenRegister::Set::iterator - UnitI = I->Regs.begin(), UnitE = I->Regs.end(); - UnitI != UnitE; ++UnitI) { - dbgs() << " " << (*UnitI)->getName(); - } + for (auto &Unit : I->Regs) + dbgs() << " " << Unit->getName(); dbgs() << "\n"); // Update the set weight. I->Weight = MaxWeight; @@ -1438,11 +1503,11 @@ void CodeGenRegBank::computeRegUnitWeights() { for (bool Changed = true; Changed; ++NumIters) { assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights"); Changed = false; - for (unsigned i = 0, e = Registers.size(); i != e; ++i) { + for (auto &Reg : Registers) { CodeGenRegister::RegUnitList NormalUnits; std::set NormalRegs; - Changed |= normalizeWeight(Registers[i], UberSets, RegSets, - NormalRegs, NormalUnits, *this); + Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs, + NormalUnits, *this); } } } @@ -1533,18 +1598,17 @@ void CodeGenRegBank::computeRegUnitSets() { assert(RegUnitSets.empty() && "dirty RegUnitSets"); // Compute a unique RegUnitSet for each RegClass. - const ArrayRef &RegClasses = getRegClasses(); - unsigned NumRegClasses = RegClasses.size(); - for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { - if (!RegClasses[RCIdx]->Allocatable) + auto &RegClasses = getRegClasses(); + for (auto &RC : RegClasses) { + if (!RC.Allocatable) continue; // Speculatively grow the RegUnitSets to hold the new set. RegUnitSets.resize(RegUnitSets.size() + 1); - RegUnitSets.back().Name = RegClasses[RCIdx]->getName(); + RegUnitSets.back().Name = RC.getName(); // Compute a sorted list of units in this class. - RegClasses[RCIdx]->buildRegUnitSet(RegUnitSets.back().Units); + RC.buildRegUnitSet(RegUnitSets.back().Units); // Find an existing RegUnitSet. std::vector::const_iterator SetI = @@ -1558,9 +1622,8 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef Units = RegUnitSets[USIdx].Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets[USIdx].Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n"; }); @@ -1572,9 +1635,8 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef Units = RegUnitSets[USIdx].Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets[USIdx].Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n"; } dbgs() << "\nUnion sets:\n"); @@ -1619,9 +1681,8 @@ void CodeGenRegBank::computeRegUnitSets() { else { DEBUG(dbgs() << "UnitSet " << RegUnitSets.size()-1 << " " << RegUnitSets.back().Name << ":"; - ArrayRef Units = RegUnitSets.back().Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets.back().Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n";); } } @@ -1635,29 +1696,30 @@ void CodeGenRegBank::computeRegUnitSets() { USIdx < USEnd; ++USIdx) { dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name << ":"; - ArrayRef Units = RegUnitSets[USIdx].Units; - for (unsigned i = 0, e = Units.size(); i < e; ++i) - dbgs() << " " << RegUnits[Units[i]].Roots[0]->getName(); + for (auto &U : RegUnitSets[USIdx].Units) + dbgs() << " " << RegUnits[U].Roots[0]->getName(); dbgs() << "\n"; }); // For each register class, list the UnitSets that are supersets. - RegClassUnitSets.resize(NumRegClasses); - for (unsigned RCIdx = 0, RCEnd = NumRegClasses; RCIdx != RCEnd; ++RCIdx) { - if (!RegClasses[RCIdx]->Allocatable) + RegClassUnitSets.resize(RegClasses.size()); + int RCIdx = -1; + for (auto &RC : RegClasses) { + ++RCIdx; + if (!RC.Allocatable) continue; // Recompute the sorted list of units in this class. std::vector RCRegUnits; - RegClasses[RCIdx]->buildRegUnitSet(RCRegUnits); + RC.buildRegUnitSet(RCRegUnits); // Don't increase pressure for unallocatable regclasses. if (RCRegUnits.empty()) continue; - DEBUG(dbgs() << "RC " << RegClasses[RCIdx]->getName() << " Units: \n"; - for (unsigned i = 0, e = RCRegUnits.size(); i < e; ++i) - dbgs() << RegUnits[RCRegUnits[i]].getRoots()[0]->getName() << " "; + DEBUG(dbgs() << "RC " << RC.getName() << " Units: \n"; + for (auto &U : RCRegUnits) + dbgs() << RegUnits[U].getRoots()[0]->getName() << " "; dbgs() << "\n UnitSetIDs:"); // Find all supersets. @@ -1702,9 +1764,44 @@ void CodeGenRegBank::computeRegUnitSets() { } } +void CodeGenRegBank::computeRegUnitLaneMasks() { + for (auto &Register : Registers) { + // Create an initial lane mask for all register units. + const auto &RegUnits = Register.getRegUnits(); + CodeGenRegister::RegUnitLaneMaskList RegUnitLaneMasks(RegUnits.size(), 0); + // Iterate through SubRegisters. + typedef CodeGenRegister::SubRegMap SubRegMap; + const SubRegMap &SubRegs = Register.getSubRegs(); + for (SubRegMap::const_iterator S = SubRegs.begin(), + SE = SubRegs.end(); S != SE; ++S) { + CodeGenRegister *SubReg = S->second; + // Ignore non-leaf subregisters, their lane masks are fully covered by + // the leaf subregisters anyway. + if (SubReg->getSubRegs().size() != 0) + continue; + CodeGenSubRegIndex *SubRegIndex = S->first; + const CodeGenRegister *SubRegister = S->second; + unsigned LaneMask = SubRegIndex->LaneMask; + // Distribute LaneMask to Register Units touched. + for (const auto &SUI : SubRegister->getRegUnits()) { + bool Found = false; + for (size_t u = 0, ue = RegUnits.size(); u < ue; ++u) { + if (SUI == RegUnits[u]) { + RegUnitLaneMasks[u] |= LaneMask; + assert(!Found); + Found = true; + } + } + assert(Found); + } + } + Register.setRegUnitLaneMasks(RegUnitLaneMasks); + } +} + void CodeGenRegBank::computeDerivedInfo() { computeComposites(); - computeSubRegIndexLaneMasks(); + computeSubRegLaneMasks(); // Compute a weight for each register unit created during getSubRegs. // This may create adopted register units (with unit # >= NumNativeRegUnits). @@ -1714,6 +1811,8 @@ void CodeGenRegBank::computeDerivedInfo() { // supersets for the union of overlapping sets. computeRegUnitSets(); + computeRegUnitLaneMasks(); + // Get the weight of each set. for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units); @@ -1740,9 +1839,13 @@ void CodeGenRegBank::computeDerivedInfo() { // returns a maximal register class for all X. // void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { - for (unsigned rci = 0, rce = RegClasses.size(); rci != rce; ++rci) { + assert(!RegClasses.empty()); + // Stash the iterator to the last element so that this loop doesn't visit + // elements added by the getOrCreateSubClass call within it. + for (auto I = RegClasses.begin(), E = std::prev(RegClasses.end()); + I != std::next(E); ++I) { CodeGenRegisterClass *RC1 = RC; - CodeGenRegisterClass *RC2 = RegClasses[rci]; + CodeGenRegisterClass *RC2 = &*I; if (RC1 == RC2) continue; @@ -1779,7 +1882,7 @@ void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) { // void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // Map SubRegIndex to set of registers in RC supporting that SubRegIndex. - typedef std::map SubReg2SetMap; // Compute the set of registers supporting each SubRegIndex. @@ -1794,22 +1897,21 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // Find matching classes for all SRSets entries. Iterate in SubRegIndex // numerical order to visit synthetic indices last. - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; - SubReg2SetMap::const_iterator I = SRSets.find(SubIdx); + for (const auto &SubIdx : SubRegIndices) { + SubReg2SetMap::const_iterator I = SRSets.find(&SubIdx); // Unsupported SubRegIndex. Skip it. if (I == SRSets.end()) continue; // In most cases, all RC registers support the SubRegIndex. if (I->second.size() == RC->getMembers().size()) { - RC->setSubClassWithSubReg(SubIdx, RC); + RC->setSubClassWithSubReg(&SubIdx, RC); continue; } // This is a real subset. See if we have a matching class. CodeGenRegisterClass *SubRC = getOrCreateSubClass(RC, &I->second, RC->getName() + "_with_" + I->first->getName()); - RC->setSubClassWithSubReg(SubIdx, SubRC); + RC->setSubClassWithSubReg(&SubIdx, SubRC); } } @@ -1821,18 +1923,17 @@ void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) { // void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, - unsigned FirstSubRegRC) { + std::list::iterator FirstSubRegRC) { SmallVector, 16> SSPairs; BitVector TopoSigs(getNumTopoSigs()); // Iterate in SubRegIndex numerical order to visit synthetic indices last. - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *SubIdx = SubRegIndices[sri]; + for (auto &SubIdx : SubRegIndices) { // Skip indexes that aren't fully supported by RC's registers. This was // computed by inferSubClassWithSubReg() above which should have been // called first. - if (RC->getSubClassWithSubReg(SubIdx) != RC) + if (RC->getSubClassWithSubReg(&SubIdx) != RC) continue; // Build list of (Super, Sub) pairs for this SubIdx. @@ -1841,7 +1942,7 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, for (CodeGenRegister::Set::const_iterator RI = RC->getMembers().begin(), RE = RC->getMembers().end(); RI != RE; ++RI) { const CodeGenRegister *Super = *RI; - const CodeGenRegister *Sub = Super->getSubRegs().find(SubIdx)->second; + const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second; assert(Sub && "Missing sub-register"); SSPairs.push_back(std::make_pair(Super, Sub)); TopoSigs.set(Sub->getTopoSig()); @@ -1849,29 +1950,32 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, // Iterate over sub-register class candidates. Ignore classes created by // this loop. They will never be useful. - for (unsigned rci = FirstSubRegRC, rce = RegClasses.size(); rci != rce; - ++rci) { - CodeGenRegisterClass *SubRC = RegClasses[rci]; + // Store an iterator to the last element (not end) so that this loop doesn't + // visit newly inserted elements. + assert(!RegClasses.empty()); + for (auto I = FirstSubRegRC, E = std::prev(RegClasses.end()); + I != std::next(E); ++I) { + CodeGenRegisterClass &SubRC = *I; // Topological shortcut: SubRC members have the wrong shape. - if (!TopoSigs.anyCommon(SubRC->getTopoSigs())) + if (!TopoSigs.anyCommon(SubRC.getTopoSigs())) continue; // Compute the subset of RC that maps into SubRC. CodeGenRegister::Set SubSet; for (unsigned i = 0, e = SSPairs.size(); i != e; ++i) - if (SubRC->contains(SSPairs[i].second)) + if (SubRC.contains(SSPairs[i].second)) SubSet.insert(SSPairs[i].first); if (SubSet.empty()) continue; // RC injects completely into SubRC. if (SubSet.size() == SSPairs.size()) { - SubRC->addSuperRegClass(SubIdx, RC); + SubRC.addSuperRegClass(&SubIdx, RC); continue; } // Only a subset of RC maps into SubRC. Make sure it is represented by a // class. - getOrCreateSubClass(RC, &SubSet, RC->getName() + - "_with_" + SubIdx->getName() + - "_in_" + SubRC->getName()); + getOrCreateSubClass(RC, &SubSet, RC->getName() + "_with_" + + SubIdx.getName() + "_in_" + + SubRC.getName()); } } } @@ -1881,14 +1985,19 @@ void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC, // Infer missing register classes. // void CodeGenRegBank::computeInferredRegisterClasses() { + assert(!RegClasses.empty()); // When this function is called, the register classes have not been sorted // and assigned EnumValues yet. That means getSubClasses(), // getSuperClasses(), and hasSubClass() functions are defunct. - unsigned FirstNewRC = RegClasses.size(); + + // Use one-before-the-end so it doesn't move forward when new elements are + // added. + auto FirstNewRC = std::prev(RegClasses.end()); // Visit all register classes, including the ones being added by the loop. - for (unsigned rci = 0; rci != RegClasses.size(); ++rci) { - CodeGenRegisterClass *RC = RegClasses[rci]; + // Watch out for iterator invalidation here. + for (auto I = RegClasses.begin(), E = RegClasses.end(); I != E; ++I) { + CodeGenRegisterClass *RC = &*I; // Synthesize answers for getSubClassWithSubReg(). inferSubClassWithSubReg(RC); @@ -1905,10 +2014,11 @@ void CodeGenRegBank::computeInferredRegisterClasses() { // after inferMatchingSuperRegClass was called. At this point, // inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC = // [0..FirstNewRC). We need to cover SubRC = [FirstNewRC..rci]. - if (rci + 1 == FirstNewRC) { - unsigned NextNewRC = RegClasses.size(); - for (unsigned rci2 = 0; rci2 != FirstNewRC; ++rci2) - inferMatchingSuperRegClass(RegClasses[rci2], FirstNewRC); + if (I == FirstNewRC) { + auto NextNewRC = std::prev(RegClasses.end()); + for (auto I2 = RegClasses.begin(), E2 = std::next(FirstNewRC); I2 != E2; + ++I2) + inferMatchingSuperRegClass(&*I2, E2); FirstNewRC = NextNewRC; } } @@ -1922,10 +2032,8 @@ void CodeGenRegBank::computeInferredRegisterClasses() { const CodeGenRegisterClass* CodeGenRegBank::getRegClassForRegister(Record *R) { const CodeGenRegister *Reg = getReg(R); - ArrayRef RCs = getRegClasses(); const CodeGenRegisterClass *FoundRC = nullptr; - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RCs[i]; + for (const auto &RC : getRegClasses()) { if (!RC.contains(Reg)) continue; diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 278315b..87a0dcf 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_REGISTERS_H -#define CODEGEN_REGISTERS_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H +#define LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/BitVector.h" @@ -24,14 +24,30 @@ #include "llvm/TableGen/Record.h" #include "llvm/TableGen/SetTheory.h" #include +#include #include #include #include #include +#include namespace llvm { class CodeGenRegBank; + /// Used to encode a step in a register lane mask transformation. + /// Mask the bits specified in Mask, then rotate them Rol bits to the left + /// assuming a wraparound at 32bits. + struct MaskRolPair { + unsigned Mask; + uint8_t RotateLeft; + bool operator==(const MaskRolPair Other) { + return Mask == Other.Mask && RotateLeft == Other.RotateLeft; + } + bool operator!=(const MaskRolPair Other) { + return Mask != Other.Mask || RotateLeft != Other.RotateLeft; + } + }; + /// CodeGenSubRegIndex - Represents a sub-register index. class CodeGenSubRegIndex { Record *const TheDef; @@ -42,7 +58,8 @@ namespace llvm { uint16_t Size; uint16_t Offset; const unsigned EnumValue; - unsigned LaneMask; + mutable unsigned LaneMask; + mutable SmallVector CompositionLaneMaskTransform; // Are all super-registers containing this SubRegIndex covered by their // sub-registers? @@ -101,7 +118,7 @@ namespace llvm { const CompMap &getComposites() const { return Composed; } // Compute LaneMask from Composed. Return LaneMask. - unsigned computeLaneMask(); + unsigned computeLaneMask() const; private: CompMap Composed; @@ -181,6 +198,7 @@ namespace llvm { // List of register units in ascending order. typedef SmallVector RegUnitList; + typedef SmallVector RegUnitLaneMaskList; // How many entries in RegUnitList are native? unsigned NumNativeRegUnits; @@ -189,11 +207,19 @@ namespace llvm { // This is only valid after computeSubRegs() completes. const RegUnitList &getRegUnits() const { return RegUnits; } + ArrayRef getRegUnitLaneMasks() const { + return makeArrayRef(RegUnitLaneMasks).slice(0, NumNativeRegUnits); + } + // Get the native register units. This is a prefix of getRegUnits(). ArrayRef getNativeRegUnits() const { return makeArrayRef(RegUnits).slice(0, NumNativeRegUnits); } + void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) { + RegUnitLaneMasks = LaneMasks; + } + // Inherit register units from subregisters. // Return true if the RegUnits changed. bool inheritRegUnits(CodeGenRegBank &RegBank); @@ -236,6 +262,7 @@ namespace llvm { SuperRegList SuperRegs; DenseMap SubReg2Idx; RegUnitList RegUnits; + RegUnitLaneMaskList RegUnitLaneMasks; }; @@ -257,15 +284,16 @@ namespace llvm { // Map SubRegIndex -> sub-class. This is the largest sub-class where all // registers have a SubRegIndex sub-register. - DenseMap SubClassWithSubReg; + DenseMap + SubClassWithSubReg; // Map SubRegIndex -> set of super-reg classes. This is all register // classes SuperRC such that: // // R:SubRegIndex in this RC for all R in SuperRC. // - DenseMap > SuperRegClasses; + DenseMap> + SuperRegClasses; // Bit vector of TopoSigs for the registers in this class. This will be // very sparse on regular architectures. @@ -280,6 +308,8 @@ namespace llvm { int CopyCost; bool Allocatable; std::string AltOrderSelect; + /// Contains the combination of the lane masks of all subregisters. + unsigned LaneMask; // Return the Record that defined this class, or NULL if the class was // created by TableGen. @@ -314,19 +344,20 @@ namespace llvm { // getSubClassWithSubReg - Returns the largest sub-class where all // registers have a SubIdx sub-register. - CodeGenRegisterClass* - getSubClassWithSubReg(CodeGenSubRegIndex *SubIdx) const { + CodeGenRegisterClass * + getSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx) const { return SubClassWithSubReg.lookup(SubIdx); } - void setSubClassWithSubReg(CodeGenSubRegIndex *SubIdx, + void setSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx, CodeGenRegisterClass *SubRC) { SubClassWithSubReg[SubIdx] = SubRC; } // getSuperRegClasses - Returns a bit vector of all register classes // containing only SubIdx super-registers of this class. - void getSuperRegClasses(CodeGenSubRegIndex *SubIdx, BitVector &Out) const; + void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx, + BitVector &Out) const; // addSuperRegClass - Add a class containing only SudIdx super-registers. void addSuperRegClass(CodeGenSubRegIndex *SubIdx, @@ -446,8 +477,7 @@ namespace llvm { class CodeGenRegBank { SetTheory Sets; - // SubRegIndices. - std::vector SubRegIndices; + std::deque SubRegIndices; DenseMap Def2SubRegIdx; CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace); @@ -457,7 +487,7 @@ namespace llvm { ConcatIdxMap ConcatIdx; // Registers. - std::vector Registers; + std::deque Registers; StringMap RegistersByName; DenseMap Def2Reg; unsigned NumNativeRegUnits; @@ -468,7 +498,7 @@ namespace llvm { SmallVector RegUnits; // Register classes. - std::vector RegClasses; + std::list RegClasses; DenseMap Def2RC; typedef std::map RCKeyMap; RCKeyMap Key2RC; @@ -501,8 +531,13 @@ namespace llvm { void computeInferredRegisterClasses(); void inferCommonSubClass(CodeGenRegisterClass *RC); void inferSubClassWithSubReg(CodeGenRegisterClass *RC); - void inferMatchingSuperRegClass(CodeGenRegisterClass *RC, - unsigned FirstSubRegRC = 0); + void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) { + inferMatchingSuperRegClass(RC, RegClasses.begin()); + } + + void inferMatchingSuperRegClass( + CodeGenRegisterClass *RC, + std::list::iterator FirstSubRegRC); // Iteratively prune unit sets. void pruneUnitSets(); @@ -517,7 +552,11 @@ namespace llvm { void computeComposites(); // Compute a lane mask for each sub-register index. - void computeSubRegIndexLaneMasks(); + void computeSubRegLaneMasks(); + + /// Computes a lane mask for each register unit enumerated by a physical + /// register. + void computeRegUnitLaneMasks(); public: CodeGenRegBank(RecordKeeper&); @@ -527,7 +566,9 @@ namespace llvm { // Sub-register indices. The first NumNamedIndices are defined by the user // in the .td files. The rest are synthesized such that all sub-registers // have a unique name. - ArrayRef getSubRegIndices() { return SubRegIndices; } + const std::deque &getSubRegIndices() const { + return SubRegIndices; + } // Find a SubRegIndex form its Record def. CodeGenSubRegIndex *getSubRegIdx(Record*); @@ -547,7 +588,7 @@ namespace llvm { ConcatIdx.insert(std::make_pair(Parts, Idx)); } - const std::vector &getRegisters() { return Registers; } + const std::deque &getRegisters() { return Registers; } const StringMap &getRegistersByName() { return RegistersByName; } @@ -604,7 +645,9 @@ namespace llvm { RegUnit &getRegUnit(unsigned RUID) { return RegUnits[RUID]; } const RegUnit &getRegUnit(unsigned RUID) const { return RegUnits[RUID]; } - ArrayRef getRegClasses() const { + std::list &getRegClasses() { return RegClasses; } + + const std::list &getRegClasses() const { return RegClasses; } diff --git a/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp index 79d60ac..bfdf8dc 100644 --- a/utils/TableGen/CodeGenSchedule.cpp +++ b/utils/TableGen/CodeGenSchedule.cpp @@ -74,11 +74,10 @@ struct InstRegexOp : public SetTheory::Operator { } RegexList.push_back(Regex(pat)); } - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { + for (const CodeGenInstruction *Inst : Target.instructions()) { for (auto &R : RegexList) { - if (R.match((*I)->TheDef->getName())) - Elts.insert((*I)->TheDef); + if (R.match(Inst->TheDef->getName())) + Elts.insert(Inst->TheDef); } } } @@ -182,7 +181,7 @@ void CodeGenSchedModels::addProcModel(Record *ProcDef) { // Recursively find all reachable SchedReadWrite records. static void scanSchedRW(Record *RWDef, RecVec &RWDefs, SmallPtrSet &RWSet) { - if (!RWSet.insert(RWDef)) + if (!RWSet.insert(RWDef).second) return; RWDefs.push_back(RWDef); // Reads don't current have sequence records, but it can be added later. @@ -214,9 +213,8 @@ void CodeGenSchedModels::collectSchedRW() { // Find all SchedReadWrites referenced by instruction defs. RecVec SWDefs, SRDefs; - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - Record *SchedDef = (*I)->TheDef; + for (const CodeGenInstruction *Inst : Target.instructions()) { + Record *SchedDef = Inst->TheDef; if (SchedDef->isValueUnset("SchedRW")) continue; RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW"); @@ -509,18 +507,17 @@ void CodeGenSchedModels::collectSchedClasses() { // Create a SchedClass for each unique combination of itinerary class and // SchedRW list. - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - Record *ItinDef = (*I)->TheDef->getValueAsDef("Itinerary"); + for (const CodeGenInstruction *Inst : Target.instructions()) { + Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary"); IdxVec Writes, Reads; - if (!(*I)->TheDef->isValueUnset("SchedRW")) - findRWs((*I)->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); + if (!Inst->TheDef->isValueUnset("SchedRW")) + findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads); // ProcIdx == 0 indicates the class applies to all processors. IdxVec ProcIndices(1, 0); unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices); - InstrClassMap[(*I)->TheDef] = SCIdx; + InstrClassMap[Inst->TheDef] = SCIdx; } // Create classes for InstRW defs. RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW"); @@ -535,18 +532,16 @@ void CodeGenSchedModels::collectSchedClasses() { if (!EnableDump) return; - for (CodeGenTarget::inst_iterator I = Target.inst_begin(), - E = Target.inst_end(); I != E; ++I) { - - std::string InstName = (*I)->TheDef->getName(); - unsigned SCIdx = InstrClassMap.lookup((*I)->TheDef); + for (const CodeGenInstruction *Inst : Target.instructions()) { + std::string InstName = Inst->TheDef->getName(); + unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef); if (!SCIdx) { - dbgs() << "No machine model for " << (*I)->TheDef->getName() << '\n'; + dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n'; continue; } CodeGenSchedClass &SC = getSchedClass(SCIdx); if (SC.ProcIndices[0] != 0) - PrintFatalError((*I)->TheDef->getLoc(), "Instruction's sched class " + PrintFatalError(Inst->TheDef->getLoc(), "Instruction's sched class " "must not be subtarget specific."); IdxVec ProcIndices; @@ -584,7 +579,7 @@ void CodeGenSchedModels::collectSchedClasses() { for (std::vector::iterator PI = ProcModels.begin(), PE = ProcModels.end(); PI != PE; ++PI) { if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index)) - dbgs() << "No machine model for " << (*I)->TheDef->getName() + dbgs() << "No machine model for " << Inst->TheDef->getName() << " on processor " << PI->ModelName << '\n'; } } @@ -751,7 +746,7 @@ void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) { for (ArrayRef::const_iterator II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) { unsigned OldSCIdx = InstrClassMap[*II]; - if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx)) { + if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) { for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(), RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) { if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) { @@ -781,9 +776,7 @@ bool CodeGenSchedModels::hasItineraries() const { // Gather the processor itineraries. void CodeGenSchedModels::collectProcItins() { - for (std::vector::iterator PI = ProcModels.begin(), - PE = ProcModels.end(); PI != PE; ++PI) { - CodeGenProcModel &ProcModel = *PI; + for (CodeGenProcModel &ProcModel : ProcModels) { if (!ProcModel.hasItineraries()) continue; @@ -1502,8 +1495,7 @@ void CodeGenSchedModels::collectProcResources() { PM.ProcResourceDefs.push_back(*RI); } // Finalize each ProcModel by sorting the record arrays. - for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) { - CodeGenProcModel &PM = ProcModels[PIdx]; + for (CodeGenProcModel &PM : ProcModels) { std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(), LessRecord()); std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(), diff --git a/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h index 3fef8ad..e5241b9 100644 --- a/utils/TableGen/CodeGenSchedule.h +++ b/utils/TableGen/CodeGenSchedule.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_SCHEDULE_H -#define CODEGEN_SCHEDULE_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H +#define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringMap.h" diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp index d1b5711..e727a0e 100644 --- a/utils/TableGen/CodeGenTarget.cpp +++ b/utils/TableGen/CodeGenTarget.cpp @@ -133,7 +133,7 @@ std::string llvm::getQualifiedName(const Record *R) { /// getTarget - Return the current instance of the Target class. /// CodeGenTarget::CodeGenTarget(RecordKeeper &records) - : Records(records), RegBank(nullptr), SchedModels(nullptr) { + : Records(records) { std::vector Targets = Records.getAllDerivedDefinitions("Target"); if (Targets.size() == 0) PrintFatalError("ERROR: No 'Target' subclasses defined!"); @@ -143,9 +143,6 @@ CodeGenTarget::CodeGenTarget(RecordKeeper &records) } CodeGenTarget::~CodeGenTarget() { - DeleteContainerSeconds(Instructions); - delete RegBank; - delete SchedModels; } const std::string &CodeGenTarget::getName() const { @@ -153,11 +150,11 @@ const std::string &CodeGenTarget::getName() const { } std::string CodeGenTarget::getInstNamespace() const { - for (inst_iterator i = inst_begin(), e = inst_end(); i != e; ++i) { + for (const CodeGenInstruction *Inst : instructions()) { // Make sure not to pick up "TargetOpcode" by accidentally getting // the namespace off the PHI instruction or something. - if ((*i)->Namespace != "TargetOpcode") - return (*i)->Namespace; + if (Inst->Namespace != "TargetOpcode") + return Inst->Namespace; } return ""; @@ -211,7 +208,7 @@ Record *CodeGenTarget::getAsmWriter() const { CodeGenRegBank &CodeGenTarget::getRegBank() const { if (!RegBank) - RegBank = new CodeGenRegBank(Records); + RegBank = llvm::make_unique(Records); return *RegBank; } @@ -234,9 +231,7 @@ std::vector CodeGenTarget:: getRegisterVTs(Record *R) const { const CodeGenRegister *Reg = getRegBank().getReg(R); std::vector Result; - ArrayRef RCs = getRegBank().getRegClasses(); - for (unsigned i = 0, e = RCs.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RCs[i]; + for (const auto &RC : getRegBank().getRegClasses()) { if (RC.contains(Reg)) { ArrayRef InVTs = RC.getValueTypes(); Result.insert(Result.end(), InVTs.begin(), InVTs.end()); @@ -251,10 +246,8 @@ getRegisterVTs(Record *R) const { void CodeGenTarget::ReadLegalValueTypes() const { - ArrayRef RCs = getRegBank().getRegClasses(); - for (unsigned i = 0, e = RCs.size(); i != e; ++i) - for (unsigned ri = 0, re = RCs[i]->VTs.size(); ri != re; ++ri) - LegalValueTypes.push_back(RCs[i]->VTs[ri]); + for (const auto &RC : getRegBank().getRegClasses()) + LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end()); // Remove duplicates. std::sort(LegalValueTypes.begin(), LegalValueTypes.end()); @@ -265,7 +258,7 @@ void CodeGenTarget::ReadLegalValueTypes() const { CodeGenSchedModels &CodeGenTarget::getSchedModels() const { if (!SchedModels) - SchedModels = new CodeGenSchedModels(Records, *this); + SchedModels = llvm::make_unique(Records, *this); return *SchedModels; } @@ -276,20 +269,20 @@ void CodeGenTarget::ReadInstructions() const { // Parse the instructions defined in the .td file. for (unsigned i = 0, e = Insts.size(); i != e; ++i) - Instructions[Insts[i]] = new CodeGenInstruction(Insts[i]); + Instructions[Insts[i]] = llvm::make_unique(Insts[i]); } static const CodeGenInstruction * GetInstByName(const char *Name, - const DenseMap &Insts, + const DenseMap> &Insts, RecordKeeper &Records) { const Record *Rec = Records.getDef(Name); - DenseMap::const_iterator - I = Insts.find(Rec); + const auto I = Insts.find(Rec); if (!Rec || I == Insts.end()) PrintFatalError(Twine("Could not find '") + Name + "' instruction!"); - return I->second; + return I->second.get(); } /// \brief Return all of the instructions defined by the target, ordered by @@ -301,8 +294,10 @@ void CodeGenTarget::ComputeInstrsByEnum() const { "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG", "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE", "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START", - "LIFETIME_END", "STACKMAP", "PATCHPOINT", nullptr}; - const DenseMap &Insts = getInstructions(); + "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD", + "STATEPOINT", "FRAME_ALLOC", + nullptr}; + const auto &Insts = getInstructions(); for (const char *const *p = FixedInstrs; *p; ++p) { const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records); assert(Instr && "Missing target independent instruction"); @@ -311,9 +306,8 @@ void CodeGenTarget::ComputeInstrsByEnum() const { } unsigned EndOfPredefines = InstrsByEnum.size(); - for (DenseMap::const_iterator - I = Insts.begin(), E = Insts.end(); I != E; ++I) { - const CodeGenInstruction *CGI = I->second; + for (const auto &I : Insts) { + const CodeGenInstruction *CGI = I.second.get(); if (CGI->Namespace != "TargetOpcode") InstrsByEnum.push_back(CGI); } @@ -343,9 +337,7 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() { return; std::vector Insts = Records.getAllDerivedDefinitions("Instruction"); - for (std::vector::iterator I = Insts.begin(), E = Insts.end(); - I != E; ++I) { - Record *R = *I; + for (Record *R : Insts) { if (R->getValueAsString("Namespace") == "TargetOpcode" || R->getValueAsBit("isPseudo")) continue; @@ -538,7 +530,9 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { // variants with iAny types; otherwise, if the intrinsic is not // overloaded, all the types can be specified directly. assert(((!TyEl->isSubClassOf("LLVMExtendedType") && - !TyEl->isSubClassOf("LLVMTruncatedType")) || + !TyEl->isSubClassOf("LLVMTruncatedType") && + !TyEl->isSubClassOf("LLVMVectorSameWidth") && + !TyEl->isSubClassOf("LLVMPointerToElt")) || VT == MVT::iAny || VT == MVT::vAny) && "Expected iAny or vAny type"); } else diff --git a/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h index 5414310..24b3851 100644 --- a/utils/TableGen/CodeGenTarget.h +++ b/utils/TableGen/CodeGenTarget.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_TARGET_H -#define CODEGEN_TARGET_H +#ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H +#define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H #include "CodeGenInstruction.h" #include "CodeGenRegisters.h" @@ -65,15 +65,16 @@ class CodeGenTarget { RecordKeeper &Records; Record *TargetRec; - mutable DenseMap Instructions; - mutable CodeGenRegBank *RegBank; + mutable DenseMap> Instructions; + mutable std::unique_ptr RegBank; mutable std::vector RegAltNameIndices; mutable SmallVector LegalValueTypes; void ReadRegAltNameIndices() const; void ReadInstructions() const; void ReadLegalValueTypes() const; - mutable CodeGenSchedModels *SchedModels; + mutable std::unique_ptr SchedModels; mutable std::vector InstrsByEnum; public: @@ -146,7 +147,8 @@ public: CodeGenSchedModels &getSchedModels() const; private: - DenseMap &getInstructions() const { + DenseMap> & + getInstructions() const { if (Instructions.empty()) ReadInstructions(); return Instructions; } @@ -154,8 +156,7 @@ public: CodeGenInstruction &getInstruction(const Record *InstRec) const { if (Instructions.empty()) ReadInstructions(); - DenseMap::iterator I = - Instructions.find(InstRec); + auto I = Instructions.find(InstRec); assert(I != Instructions.end() && "Not an instruction"); return *I->second; } diff --git a/utils/TableGen/DAGISelEmitter.cpp b/utils/TableGen/DAGISelEmitter.cpp index 82682cd..0fe3bbd 100644 --- a/utils/TableGen/DAGISelEmitter.cpp +++ b/utils/TableGen/DAGISelEmitter.cpp @@ -94,8 +94,8 @@ struct PatternSortingPredicate { // Otherwise, if the patterns might both match, sort based on complexity, // which means that we prefer to match patterns that cover more nodes in the // input over nodes that cover fewer. - unsigned LHSSize = LHS->getPatternComplexity(CGP); - unsigned RHSSize = RHS->getPatternComplexity(CGP); + int LHSSize = LHS->getPatternComplexity(CGP); + int RHSSize = RHS->getPatternComplexity(CGP); if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost if (LHSSize < RHSSize) return false; @@ -157,12 +157,12 @@ void DAGISelEmitter::run(raw_ostream &OS) { } } - Matcher *TheMatcher = new ScopeMatcher(PatternMatchers); + std::unique_ptr TheMatcher = + llvm::make_unique(PatternMatchers); - TheMatcher = OptimizeMatcher(TheMatcher, CGP); + OptimizeMatcher(TheMatcher, CGP); //Matcher->dump(); - EmitMatcherTable(TheMatcher, CGP, OS); - delete TheMatcher; + EmitMatcherTable(TheMatcher.get(), CGP, OS); } namespace llvm { diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index f8f6c54..9df3b41 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -1,4 +1,4 @@ -//===- DAGISelMatcher.h - Representation of DAG pattern matcher -----------===// +//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_DAGISELMATCHER_H -#define TBLGEN_DAGISELMATCHER_H +#ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H +#define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" @@ -30,7 +30,8 @@ namespace llvm { Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant, const CodeGenDAGPatterns &CGP); -Matcher *OptimizeMatcher(Matcher *Matcher, const CodeGenDAGPatterns &CGP); +void OptimizeMatcher(std::unique_ptr &Matcher, + const CodeGenDAGPatterns &CGP); void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP, raw_ostream &OS); diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 0059570..302f27b 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -630,7 +630,7 @@ void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) { for (CodeGenDAGPatterns::pf_iterator I = CGP.pf_begin(), E = CGP.pf_end(); I != E; ++I) - PFsByName[I->first->getName()] = I->second; + PFsByName[I->first->getName()] = I->second.get(); if (!NodePredicates.empty()) { OS << "bool CheckNodePredicate(SDNode *Node,\n"; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 97e37ba..eb80619 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -27,10 +27,8 @@ static MVT::SimpleValueType getRegisterValueType(Record *R, bool FoundRC = false; MVT::SimpleValueType VT = MVT::Other; const CodeGenRegister *Reg = T.getRegBank().getReg(R); - ArrayRef RCs = T.getRegBank().getRegClasses(); - for (unsigned rc = 0, e = RCs.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RCs[rc]; + for (const auto &RC : T.getRegBank().getRegClasses()) { if (!RC.contains(Reg)) continue; @@ -718,7 +716,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, CodeGenInstruction &II = CGT.getInstruction(Op); const DAGInstruction &Inst = CGP.getInstruction(Op); - // If we can, get the pattern for the instruction we're generating. We derive + // If we can, get the pattern for the instruction we're generating. We derive // a variety of information from this pattern, such as whether it has a chain. // // FIXME2: This is extremely dubious for several reasons, not the least of @@ -755,16 +753,21 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // the "outs" list. unsigned NumResults = Inst.getNumResults(); - // Loop over all of the operands of the instruction pattern, emitting code - // to fill them all in. The node 'N' usually has number children equal to - // the number of input operands of the instruction. However, in cases - // where there are predicate operands for an instruction, we need to fill - // in the 'execute always' values. Match up the node operands to the - // instruction operands to do this. + // Number of operands we know the output instruction must have. If it is + // variadic, we could have more operands. + unsigned NumFixedOperands = II.Operands.size(); + SmallVector InstOps; - for (unsigned ChildNo = 0, InstOpNo = NumResults, e = II.Operands.size(); - InstOpNo != e; ++InstOpNo) { + // Loop over all of the fixed operands of the instruction pattern, emitting + // code to fill them all in. The node 'N' usually has number children equal to + // the number of input operands of the instruction. However, in cases where + // there are predicate operands for an instruction, we need to fill in the + // 'execute always' values. Match up the node operands to the instruction + // operands to do this. + unsigned ChildNo = 0; + for (unsigned InstOpNo = NumResults, e = NumFixedOperands; + InstOpNo != e; ++InstOpNo) { // Determine what to emit for this operand. Record *OperandNode = II.Operands[InstOpNo].Rec; if (OperandNode->isSubClassOf("OperandWithDefaultOps") && @@ -807,6 +810,16 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, } } + // If this is a variadic output instruction (i.e. REG_SEQUENCE), we can't + // expand suboperands, use default operands, or other features determined from + // the CodeGenInstruction after the fixed operands, which were handled + // above. Emit the remaining instructions implicitly added by the use for + // variable_ops. + if (II.Operands.isVariadic) { + for (unsigned I = ChildNo, E = N->getNumChildren(); I < E; ++I) + EmitResultOperand(N->getChild(I), InstOps); + } + // If this node has input glue or explicitly specified input physregs, we // need to add chained and glued copyfromreg nodes and materialize the glue // input. @@ -852,7 +865,7 @@ EmitResultInstructionAsOperand(const TreePatternNode *N, // gets the excess operands from the input DAG. int NumFixedArityOperands = -1; if (isRoot && - (Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))) + Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP)) NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren(); // If this is the root node and multiple matched nodes in the input pattern diff --git a/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp index da6a957..c9ee371 100644 --- a/utils/TableGen/DAGISelMatcherOpt.cpp +++ b/utils/TableGen/DAGISelMatcherOpt.cpp @@ -185,7 +185,7 @@ static void ContractNodes(std::unique_ptr &MatcherPtr, /// Conceptually, we'd like to sink these predicates all the way to the last /// matcher predicate in the series. However, it turns out that some /// ComplexPatterns have side effects on the graph, so we really don't want to -/// run a the complex pattern if the pattern predicate will fail. For this +/// run a complex pattern if the pattern predicate will fail. For this /// reason, we refuse to sink the pattern predicate past a ComplexPattern. /// static void SinkPatternPredicates(std::unique_ptr &MatcherPtr) { @@ -454,7 +454,7 @@ static void FactorNodes(std::unique_ptr &MatcherPtr) { SmallVector, 8> Cases; for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) { CheckOpcodeMatcher *COM = cast(NewOptionsToMatch[i]); - assert(Opcodes.insert(COM->getOpcode().getEnumName()) && + assert(Opcodes.insert(COM->getOpcode().getEnumName()).second && "Duplicate opcodes not factored?"); Cases.push_back(std::make_pair(&COM->getOpcode(), COM->getNext())); } @@ -511,11 +511,10 @@ static void FactorNodes(std::unique_ptr &MatcherPtr) { Scope->resetChild(i, NewOptionsToMatch[i]); } -Matcher *llvm::OptimizeMatcher(Matcher *TheMatcher, - const CodeGenDAGPatterns &CGP) { - std::unique_ptr MatcherPtr(TheMatcher); +void +llvm::OptimizeMatcher(std::unique_ptr &MatcherPtr, + const CodeGenDAGPatterns &CGP) { ContractNodes(MatcherPtr, CGP); SinkPatternPredicates(MatcherPtr); FactorNodes(MatcherPtr); - return MatcherPtr.release(); } diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp index 154f96d..748c923 100644 --- a/utils/TableGen/FastISelEmitter.cpp +++ b/utils/TableGen/FastISelEmitter.cpp @@ -19,6 +19,7 @@ #include "CodeGenDAGPatterns.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/TableGen/Error.h" @@ -36,6 +37,7 @@ struct InstructionMemo { const CodeGenRegisterClass *RC; std::string SubRegNo; std::vector* PhysRegs; + std::string PredicateCheck; }; } // End anonymous namespace @@ -347,7 +349,7 @@ struct OperandsSignature { // Implicit physical register operand. e.g. Instruction::Mul expect to // select to a binary op. On x86, mul may take a single operand with // the other operand being implicit. We must emit something that looks - // like a binary instruction except for the very inner FastEmitInst_* + // like a binary instruction except for the very inner fastEmitInst_* // call. continue; Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes); @@ -364,7 +366,9 @@ struct OperandsSignature { namespace { class FastISelMap { - typedef std::map PredMap; + // A multimap is needed instead of a "plain" map because the key is + // the instruction's complexity (an int) and they are not unique. + typedef std::multimap PredMap; typedef std::map RetPredMap; typedef std::map TypeRetPredMap; typedef std::map OpcodeTypeRetPredMap; @@ -373,6 +377,16 @@ class FastISelMap { OperandsOpcodeTypeRetPredMap SimplePatterns; + // This is used to check that there are no duplicate predicates + typedef std::multimap PredCheckMap; + typedef std::map RetPredCheckMap; + typedef std::map TypeRetPredCheckMap; + typedef std::map OpcodeTypeRetPredCheckMap; + typedef std::map + OperandsOpcodeTypeRetPredCheckMap; + + OperandsOpcodeTypeRetPredCheckMap SimplePatternsCheck; + std::map > SignaturesWithConstantForms; @@ -384,6 +398,11 @@ public: void collectPatterns(CodeGenDAGPatterns &CGP); void printImmediatePredicates(raw_ostream &OS); void printFunctionDefinitions(raw_ostream &OS); +private: + void emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName); }; } // End anonymous namespace @@ -541,6 +560,17 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { continue; } + // Check if the operands match one of the patterns handled by FastISel. + std::string ManglingSuffix; + raw_string_ostream SuffixOS(ManglingSuffix); + Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true); + SuffixOS.flush(); + if (!StringSwitch(ManglingSuffix) + .Cases("", "r", "rr", "ri", "rf", true) + .Cases("rri", "i", "f", true) + .Default(false)) + continue; + // Get the predicate that guards this pattern. std::string PredicateCheck = Pattern.getPredicateCheck(); @@ -549,14 +579,24 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) { Pattern.getDstPattern()->getOperator()->getName(), DstRC, SubRegNo, - PhysRegInputs + PhysRegInputs, + PredicateCheck }; + + int complexity = Pattern.getPatternComplexity(CGP); - if (SimplePatterns[Operands][OpcodeName][VT][RetVT].count(PredicateCheck)) + if (SimplePatternsCheck[Operands][OpcodeName][VT] + [RetVT].count(PredicateCheck)) { PrintFatalError(Pattern.getSrcRecord()->getLoc(), - "Duplicate record in FastISel table!"); + "Duplicate predicate in FastISel table!"); + } + SimplePatternsCheck[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(PredicateCheck, true)); - SimplePatterns[Operands][OpcodeName][VT][RetVT][PredicateCheck] = Memo; + // Note: Instructions with the same complexity will appear in the order + // that they are encountered. + SimplePatterns[Operands][OpcodeName][VT][RetVT].insert( + std::make_pair(complexity, Memo)); // If any of the operands were immediates with predicates on them, strip // them down to a signature that doesn't have predicates so that we can @@ -582,6 +622,72 @@ void FastISelMap::printImmediatePredicates(raw_ostream &OS) { OS << "\n\n"; } +void FastISelMap::emitInstructionCode(raw_ostream &OS, + const OperandsSignature &Operands, + const PredMap &PM, + const std::string &RetVTName) { + // Emit code for each possible instruction. There may be + // multiple if there are subtarget concerns. A reverse iterator + // is used to produce the ones with highest complexity first. + + bool OneHadNoPredicate = false; + for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend(); + PI != PE; ++PI) { + const InstructionMemo &Memo = PI->second; + std::string PredicateCheck = Memo.PredicateCheck; + + if (PredicateCheck.empty()) { + assert(!OneHadNoPredicate && + "Multiple instructions match and more than one had " + "no predicate!"); + OneHadNoPredicate = true; + } else { + if (OneHadNoPredicate) { + // FIXME: This should be a PrintError once the x86 target + // fixes PR21575. + PrintWarning("Multiple instructions match and one with no " + "predicate came before one with a predicate! " + "name:" + Memo.Name + " predicate: " + + PredicateCheck); + } + OS << " if (" + PredicateCheck + ") {\n"; + OS << " "; + } + + for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { + if ((*Memo.PhysRegs)[i] != "") + OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " + << "TII.get(TargetOpcode::COPY), " + << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; + } + + OS << " return fastEmitInst_"; + if (Memo.SubRegNo.empty()) { + Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, + ImmediatePredicates, true); + OS << "(" << InstNS << Memo.Name << ", "; + OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; + if (!Operands.empty()) + OS << ", "; + Operands.PrintArguments(OS, *Memo.PhysRegs); + OS << ");\n"; + } else { + OS << "extractsubreg(" << RetVTName + << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; + } + + if (!PredicateCheck.empty()) { + OS << " }\n"; + } + } + // Return 0 if all of the possibilities had predicates but none + // were satisfied. + if (!OneHadNoPredicate) + OS << " return 0;\n"; + OS << "}\n"; + OS << "\n"; +} + void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Now emit code for all the patterns that we collected. @@ -608,9 +714,8 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; const PredMap &PM = RI->second; - bool HasPred = false; - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; @@ -619,58 +724,11 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { Operands.PrintParameters(OS); OS << ") {\n"; - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); - PI != PE; ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(" << getName(RetVT); - OS << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n"; - } - - if (HasPred) - OS << " }\n"; - - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, getName(RetVT)); } // Emit one function for the type that demultiplexes on return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -682,7 +740,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end(); RI != RE; ++RI) { MVT::SimpleValueType RetVT = RI->first; - OS << " case " << getName(RetVT) << ": return FastEmit_" + OS << " case " << getName(RetVT) << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_" << getLegalCName(getName(RetVT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -694,7 +752,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { } else { // Non-variadic return type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT)) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); @@ -708,63 +766,13 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { << ")\n return 0;\n"; const PredMap &PM = RM.begin()->second; - bool HasPred = false; - - // Emit code for each possible instruction. There may be - // multiple if there are subtarget concerns. - for (PredMap::const_iterator PI = PM.begin(), PE = PM.end(); PI != PE; - ++PI) { - std::string PredicateCheck = PI->first; - const InstructionMemo &Memo = PI->second; - - if (PredicateCheck.empty()) { - assert(!HasPred && - "Multiple instructions match, at least one has " - "a predicate and at least one doesn't!"); - } else { - OS << " if (" + PredicateCheck + ") {\n"; - OS << " "; - HasPred = true; - } - - for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) { - if ((*Memo.PhysRegs)[i] != "") - OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, " - << "TII.get(TargetOpcode::COPY), " - << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n"; - } - - OS << " return FastEmitInst_"; - - if (Memo.SubRegNo.empty()) { - Operands.PrintManglingSuffix(OS, *Memo.PhysRegs, - ImmediatePredicates, true); - OS << "(" << InstNS << Memo.Name << ", "; - OS << "&" << InstNS << Memo.RC->getName() << "RegClass"; - if (!Operands.empty()) - OS << ", "; - Operands.PrintArguments(OS, *Memo.PhysRegs); - OS << ");\n"; - } else { - OS << "extractsubreg(RetVT, Op0, Op0IsKill, "; - OS << Memo.SubRegNo; - OS << ");\n"; - } - - if (HasPred) - OS << " }\n"; - } - // Return 0 if none of the predicates were satisfied. - if (HasPred) - OS << " return 0;\n"; - OS << "}\n"; - OS << "\n"; + emitInstructionCode(OS, Operands, PM, "RetVT"); } } // Emit one function for the opcode that demultiplexes based on the type. - OS << "unsigned FastEmit_" + OS << "unsigned fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT"; @@ -777,7 +785,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { TI != TE; ++TI) { MVT::SimpleValueType VT = TI->first; std::string TypeName = getName(VT); - OS << " case " << TypeName << ": return FastEmit_" + OS << " case " << TypeName << ": return fastEmit_" << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(RetVT"; @@ -797,13 +805,16 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { // Emit one function for the operand signature that demultiplexes based // on opcode and type. - OS << "unsigned FastEmit_"; + OS << "unsigned fastEmit_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(MVT VT, MVT RetVT, unsigned Opcode"; if (!Operands.empty()) OS << ", "; Operands.PrintParameters(OS); - OS << ") {\n"; + OS << ") "; + if (!Operands.hasAnyImmediateCodes()) + OS << "override "; + OS << "{\n"; // If there are any forms of this signature available that operate on // constrained forms of the immediate (e.g., 32-bit sext immediate in a @@ -823,7 +834,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { for (unsigned i = 0, e = MI->second.size(); i != e; ++i) { OS << " if ("; MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates); - OS << ")\n if (unsigned Reg = FastEmit_"; + OS << ")\n if (unsigned Reg = fastEmit_"; MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT, Opcode"; if (!MI->second[i].empty()) @@ -841,7 +852,7 @@ void FastISelMap::printFunctionDefinitions(raw_ostream &OS) { I != E; ++I) { const std::string &Opcode = I->first; - OS << " case " << Opcode << ": return FastEmit_" + OS << " case " << Opcode << ": return fastEmit_" << getLegalCName(Opcode) << "_"; Operands.PrintManglingSuffix(OS, ImmediatePredicates); OS << "(VT, RetVT"; diff --git a/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp index 42639cc..7c29422 100644 --- a/utils/TableGen/FixedLenDecoderEmitter.cpp +++ b/utils/TableGen/FixedLenDecoderEmitter.cpp @@ -230,7 +230,7 @@ protected: std::vector VariableInstructions; // Map of well-known segment value to its delegate. - std::map FilterChooserMap; + std::map> FilterChooserMap; // Number of instructions which fall under FilteredInstructions category. unsigned NumFiltered; @@ -252,7 +252,7 @@ public: return *(FilterChooserMap.find((unsigned)-1)->second); } - Filter(const Filter &f); + Filter(Filter &&f); Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed); ~Filter(); @@ -333,13 +333,9 @@ protected: // Parent emitter const FixedLenDecoderEmitter *Emitter; + FilterChooser(const FilterChooser &) LLVM_DELETED_FUNCTION; + void operator=(const FilterChooser &) LLVM_DELETED_FUNCTION; public: - FilterChooser(const FilterChooser &FC) - : AllInstructions(FC.AllInstructions), Opcodes(FC.Opcodes), - Operands(FC.Operands), Filters(FC.Filters), - FilterBitValues(FC.FilterBitValues), Parent(FC.Parent), - BestIndex(FC.BestIndex), BitWidth(FC.BitWidth), - Emitter(FC.Emitter) { } FilterChooser(const std::vector &Insts, const std::vector &IDs, @@ -347,10 +343,8 @@ public: unsigned BW, const FixedLenDecoderEmitter *E) : AllInstructions(Insts), Opcodes(IDs), Operands(Ops), Filters(), - Parent(nullptr), BestIndex(-1), BitWidth(BW), Emitter(E) { - for (unsigned i = 0; i < BitWidth; ++i) - FilterBitValues.push_back(BIT_UNFILTERED); - + FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1), + BitWidth(BW), Emitter(E) { doFilter(); } @@ -490,11 +484,11 @@ public: // // /////////////////////////// -Filter::Filter(const Filter &f) +Filter::Filter(Filter &&f) : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed), - FilteredInstructions(f.FilteredInstructions), - VariableInstructions(f.VariableInstructions), - FilterChooserMap(f.FilterChooserMap), NumFiltered(f.NumFiltered), + FilteredInstructions(std::move(f.FilteredInstructions)), + VariableInstructions(std::move(f.VariableInstructions)), + FilterChooserMap(std::move(f.FilterChooserMap)), NumFiltered(f.NumFiltered), LastOpcFiltered(f.LastOpcFiltered) { } @@ -534,12 +528,6 @@ Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, } Filter::~Filter() { - std::map::iterator filterIterator; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { - delete filterIterator->second; - } } // Divides the decoding task into sub tasks and delegates them to the @@ -549,8 +537,6 @@ Filter::~Filter() { // instructions. In order to unambiguously decode the singleton, we need to // match the remaining undecoded encoding bits against the singleton. void Filter::recurse() { - std::map >::const_iterator mapIterator; - // Starts by inheriting our parent filter chooser's filter bit values. std::vector BitValueArray(Owner->FilterBitValues); @@ -561,14 +547,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // group of instructions whose segment values are variable. - FilterChooserMap.insert(std::pair( - (unsigned)-1, - new FilterChooser(Owner->AllInstructions, - VariableInstructions, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert( + std::make_pair(-1U, llvm::make_unique( + Owner->AllInstructions, VariableInstructions, + Owner->Operands, BitValueArray, *Owner))); } // No need to recurse for a singleton filtered instruction. @@ -580,13 +562,11 @@ void Filter::recurse() { } // Otherwise, create sub choosers. - for (mapIterator = FilteredInstructions.begin(); - mapIterator != FilteredInstructions.end(); - mapIterator++) { + for (const auto &Inst : FilteredInstructions) { // Marks all the segment positions with either BIT_TRUE or BIT_FALSE. for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) { - if (mapIterator->first & (1ULL << bitIndex)) + if (Inst.first & (1ULL << bitIndex)) BitValueArray[StartBit + bitIndex] = BIT_TRUE; else BitValueArray[StartBit + bitIndex] = BIT_FALSE; @@ -594,14 +574,10 @@ void Filter::recurse() { // Delegates to an inferior filter chooser for further processing on this // category of instructions. - FilterChooserMap.insert(std::pair( - mapIterator->first, - new FilterChooser(Owner->AllInstructions, - mapIterator->second, - Owner->Operands, - BitValueArray, - *Owner) - )); + FilterChooserMap.insert(std::make_pair( + Inst.first, llvm::make_unique( + Owner->AllInstructions, Inst.second, + Owner->Operands, BitValueArray, *Owner))); } } @@ -636,18 +612,14 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // A new filter entry begins a new scope for fixup resolution. TableInfo.FixupStack.push_back(FixupList()); - std::map::const_iterator filterIterator; - DecoderTable &Table = TableInfo.Table; size_t PrevFilter = 0; bool HasFallthrough = false; - for (filterIterator = FilterChooserMap.begin(); - filterIterator != FilterChooserMap.end(); - filterIterator++) { + for (auto &Filter : FilterChooserMap) { // Field value -1 implies a non-empty set of variable instructions. // See also recurse(). - if (filterIterator->first == (unsigned)-1) { + if (Filter.first == (unsigned)-1) { HasFallthrough = true; // Each scope should always have at least one filter value to check @@ -662,7 +634,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { Table.push_back(MCD::OPC_FilterValue); // Encode and emit the value to filter against. uint8_t Buffer[8]; - unsigned Len = encodeULEB128(filterIterator->first, Buffer); + unsigned Len = encodeULEB128(Filter.first, Buffer); Table.insert(Table.end(), Buffer, Buffer + Len); // Reserve space for the NumToSkip entry. We'll backpatch the value // later. @@ -675,7 +647,7 @@ void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const { // Now delegate to the sub filter chooser for further decodings. // The case may fallthrough, which happens if the remaining well-known // encoding bits do not match exactly. - filterIterator->second->emitTableEntries(TableInfo); + Filter.second->emitTableEntries(TableInfo); // Now that we've emitted the body of the handler, update the NumToSkip // of the filter itself to be able to skip forward when false. Subtract @@ -882,10 +854,9 @@ emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates, OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; unsigned Index = 0; - for (PredicateSet::const_iterator I = Predicates.begin(), E = Predicates.end(); - I != E; ++I, ++Index) { - OS.indent(Indentation) << "case " << Index << ":\n"; - OS.indent(Indentation+2) << "return (" << *I << ");\n"; + for (const auto &Predicate : Predicates) { + OS.indent(Indentation) << "case " << Index++ << ":\n"; + OS.indent(Indentation+2) << "return (" << Predicate << ");\n"; } OS.indent(Indentation) << "}\n"; } else { @@ -911,10 +882,9 @@ emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders, OS.indent(Indentation) << "switch (Idx) {\n"; OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n"; unsigned Index = 0; - for (DecoderSet::const_iterator I = Decoders.begin(), E = Decoders.end(); - I != E; ++I, ++Index) { - OS.indent(Indentation) << "case " << Index << ":\n"; - OS << *I; + for (const auto &Decoder : Decoders) { + OS.indent(Indentation) << "case " << Index++ << ":\n"; + OS << Decoder; OS.indent(Indentation+2) << "return S;\n"; } OS.indent(Indentation) << "}\n"; @@ -1066,19 +1036,17 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, const OperandInfo &OpInfo) const { const std::string &Decoder = OpInfo.Decoder; - if (OpInfo.numFields() == 1) { - OperandInfo::const_iterator OI = OpInfo.begin(); - o.indent(Indentation) << "tmp = fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ");\n"; - } else { + if (OpInfo.numFields() != 1) o.indent(Indentation) << "tmp = 0;\n"; - for (OperandInfo::const_iterator OI = OpInfo.begin(), OE = OpInfo.end(); - OI != OE; ++OI) { - o.indent(Indentation) << "tmp |= (fieldFromInstruction" - << "(insn, " << OI->Base << ", " << OI->Width - << ") << " << OI->Offset << ");\n"; - } + + for (const EncodingField &EF : OpInfo) { + o.indent(Indentation) << "tmp "; + if (OpInfo.numFields() != 1) o << '|'; + o << "= fieldFromInstruction" + << "(insn, " << EF.Base << ", " << EF.Width << ')'; + if (OpInfo.numFields() != 1 || EF.Offset != 0) + o << " << " << EF.Offset; + o << ";\n"; } if (Decoder != "") @@ -1092,20 +1060,16 @@ void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation, void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc) const { - std::map >::const_iterator OpIter = - Operands.find(Opc); - const std::vector& InsnOperands = OpIter->second; - for (std::vector::const_iterator - I = InsnOperands.begin(), E = InsnOperands.end(); I != E; ++I) { + for (const auto &Op : Operands.find(Opc)->second) { // If a custom instruction decoder was specified, use that. - if (I->numFields() == 0 && I->Decoder.size()) { - OS.indent(Indentation) << Emitter->GuardPrefix << I->Decoder + if (Op.numFields() == 0 && Op.Decoder.size()) { + OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder << "(MI, insn, Address, Decoder)" << Emitter->GuardPostfix << "\n"; break; } - emitBinaryParser(OS, Indentation, *I); + emitBinaryParser(OS, Indentation, Op); } } @@ -1384,8 +1348,7 @@ void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo, void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit, bool mixed) { Filters.clear(); - Filter F(*this, startBit, numBit, true); - Filters.push_back(F); + Filters.push_back(Filter(*this, startBit, numBit, true)); BestIndex = 0; // Sole Filter instance to choose from. bestFilter().recurse(); } @@ -1886,20 +1849,20 @@ static bool populateInstruction(CodeGenTarget &Target, } // For each operand, see if we can figure out where it is encoded. - for (std::vector >::const_iterator - NI = InOutOperands.begin(), NE = InOutOperands.end(); NI != NE; ++NI) { - if (!NumberedInsnOperands[NI->second].empty()) { + for (const auto &Op : InOutOperands) { + if (!NumberedInsnOperands[Op.second].empty()) { InsnOperands.insert(InsnOperands.end(), - NumberedInsnOperands[NI->second].begin(), - NumberedInsnOperands[NI->second].end()); + NumberedInsnOperands[Op.second].begin(), + NumberedInsnOperands[Op.second].end()); continue; - } else if (!NumberedInsnOperands[TiedNames[NI->second]].empty()) { - if (!NumberedInsnOperandsNoTie.count(TiedNames[NI->second])) { + } + if (!NumberedInsnOperands[TiedNames[Op.second]].empty()) { + if (!NumberedInsnOperandsNoTie.count(TiedNames[Op.second])) { // Figure out to which (sub)operand we're tied. - unsigned i = CGI.Operands.getOperandNamed(TiedNames[NI->second]); + unsigned i = CGI.Operands.getOperandNamed(TiedNames[Op.second]); int tiedTo = CGI.Operands[i].getTiedRegister(); if (tiedTo == -1) { - i = CGI.Operands.getOperandNamed(NI->second); + i = CGI.Operands.getOperandNamed(Op.second); tiedTo = CGI.Operands[i].getTiedRegister(); } @@ -1907,7 +1870,7 @@ static bool populateInstruction(CodeGenTarget &Target, std::pair SO = CGI.Operands.getSubOperandNumber(tiedTo); - InsnOperands.push_back(NumberedInsnOperands[TiedNames[NI->second]] + InsnOperands.push_back(NumberedInsnOperands[TiedNames[Op.second]] [SO.second]); } } @@ -1921,7 +1884,7 @@ static bool populateInstruction(CodeGenTarget &Target, // for decoding register classes. // FIXME: This need to be extended to handle instructions with custom // decoder methods, and operands with (simple) MIOperandInfo's. - TypedInit *TI = cast(NI->first); + TypedInit *TI = cast(Op.first); RecordRecTy *Type = cast(TI->getType()); Record *TypeRecord = Type->getRecord(); bool isReg = false; @@ -1965,8 +1928,8 @@ static bool populateInstruction(CodeGenTarget &Target, continue; } - if (Var->getName() != NI->second && - Var->getName() != TiedNames[NI->second]) { + if (Var->getName() != Op.second && + Var->getName() != TiedNames[Op.second]) { if (Base != ~0U) { OpInfo.addField(Base, Width, Offset); Base = ~0U; @@ -2203,12 +2166,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { } DecoderTableInfo TableInfo; - for (std::map, - std::vector >::const_iterator - I = OpcMap.begin(), E = OpcMap.end(); I != E; ++I) { + for (const auto &Opc : OpcMap) { // Emit the decoder for this namespace+width combination. - FilterChooser FC(*NumberedInstructions, I->second, Operands, - 8*I->first.second, this); + FilterChooser FC(*NumberedInstructions, Opc.second, Operands, + 8*Opc.first.second, this); // The decode table is cleared for each top level decoder function. The // predicates and decoders themselves, however, are shared across all @@ -2229,7 +2190,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) { TableInfo.Table.push_back(MCD::OPC_Fail); // Print the table to the output stream. - emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), I->first.first); + emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), Opc.first.first); OS.flush(); } diff --git a/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp index 76f05ce..fe30d60 100644 --- a/utils/TableGen/InstrInfoEmitter.cpp +++ b/utils/TableGen/InstrInfoEmitter.cpp @@ -143,7 +143,7 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) { Res += "|(1<getValueAsBitsInit("TSFlags"); @@ -583,14 +587,16 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) { for (const CodeGenInstruction *Inst : NumberedInstructions) OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n"; OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\n"; - OS << " };\n"; + OS << " };\n\n"; OS << "namespace Sched {\n"; OS << " enum {\n"; Num = 0; for (const auto &Class : SchedModels.explicit_classes()) OS << " " << Class.Name << "\t= " << Num++ << ",\n"; OS << " SCHED_LIST_END = " << SchedModels.numInstrSchedClasses() << "\n"; - OS << " };\n}\n}\n"; + OS << " };\n"; + OS << "} // End Sched namespace\n"; + OS << "} // End " << Namespace << " namespace\n"; OS << "} // End llvm namespace \n"; OS << "#endif // GET_INSTRINFO_ENUM\n\n"; diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 34358c4..c0cf92d 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -244,19 +244,22 @@ enum IIT_Info { IIT_ARG = 15, // Values from 16+ are only encodable with the inefficient encoding. - IIT_MMX = 16, - IIT_METADATA = 17, - IIT_EMPTYSTRUCT = 18, - IIT_STRUCT2 = 19, - IIT_STRUCT3 = 20, - IIT_STRUCT4 = 21, - IIT_STRUCT5 = 22, - IIT_EXTEND_ARG = 23, - IIT_TRUNC_ARG = 24, - IIT_ANYPTR = 25, - IIT_V1 = 26, - IIT_VARARG = 27, - IIT_HALF_VEC_ARG = 28 + IIT_V64 = 16, + IIT_MMX = 17, + IIT_METADATA = 18, + IIT_EMPTYSTRUCT = 19, + IIT_STRUCT2 = 20, + IIT_STRUCT3 = 21, + IIT_STRUCT4 = 22, + IIT_STRUCT5 = 23, + IIT_EXTEND_ARG = 24, + IIT_TRUNC_ARG = 25, + IIT_ANYPTR = 26, + IIT_V1 = 27, + IIT_VARARG = 28, + IIT_HALF_VEC_ARG = 29, + IIT_SAME_VEC_WIDTH_ARG = 30, + IIT_PTR_TO_ARG = 31 }; @@ -304,6 +307,16 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, Sig.push_back(IIT_TRUNC_ARG); else if (R->isSubClassOf("LLVMHalfElementsVectorType")) Sig.push_back(IIT_HALF_VEC_ARG); + else if (R->isSubClassOf("LLVMVectorSameWidth")) { + Sig.push_back(IIT_SAME_VEC_WIDTH_ARG); + Sig.push_back((Number << 2) | ArgCodes[Number]); + MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy")); + EncodeFixedValueType(VT, Sig); + return; + } + else if (R->isSubClassOf("LLVMPointerTo")) { + Sig.push_back(IIT_PTR_TO_ARG); + } else Sig.push_back(IIT_ARG); return Sig.push_back((Number << 2) | ArgCodes[Number]); @@ -356,6 +369,7 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, case 8: Sig.push_back(IIT_V8); break; case 16: Sig.push_back(IIT_V16); break; case 32: Sig.push_back(IIT_V32); break; + case 64: Sig.push_back(IIT_V64); break; } return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig); @@ -680,8 +694,7 @@ EmitAttributes(const std::vector &Ints, raw_ostream &OS) { OS << " }\n"; OS << " }\n"; - OS << " return AttributeSet::get(C, ArrayRef(AS, " - "NumAttrs));\n"; + OS << " return AttributeSet::get(C, makeArrayRef(AS, NumAttrs));\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } diff --git a/utils/TableGen/PseudoLoweringEmitter.cpp b/utils/TableGen/PseudoLoweringEmitter.cpp index 3b74ac4..ebb43f0 100644 --- a/utils/TableGen/PseudoLoweringEmitter.cpp +++ b/utils/TableGen/PseudoLoweringEmitter.cpp @@ -277,11 +277,10 @@ void PseudoLoweringEmitter::run(raw_ostream &o) { assert(InstructionClass && "Instruction class definition missing!"); std::vector Insts; - for (std::map::const_iterator I = - Records.getDefs().begin(), E = Records.getDefs().end(); I != E; ++I) { - if (I->second->isSubClassOf(ExpansionClass) && - I->second->isSubClassOf(InstructionClass)) - Insts.push_back(I->second); + for (const auto &D : Records.getDefs()) { + if (D.second->isSubClassOf(ExpansionClass) && + D.second->isSubClassOf(InstructionClass)) + Insts.push_back(D.second.get()); } // Process the pseudo expansion definitions, validating them as we do so. diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 573c37f..1c3de4a 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -53,27 +53,30 @@ public: void run(raw_ostream &o); private: - void EmitRegMapping(raw_ostream &o, - const std::vector &Regs, bool isCtor); + void EmitRegMapping(raw_ostream &o, const std::deque &Regs, + bool isCtor); void EmitRegMappingTables(raw_ostream &o, - const std::vector &Regs, + const std::deque &Regs, bool isCtor); void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName); void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, const std::string &ClassName); + void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank, + const std::string &ClassName); }; } // End anonymous namespace // runEnums - Print out enum values for all of the registers. void RegisterInfoEmitter::runEnums(raw_ostream &OS, CodeGenTarget &Target, CodeGenRegBank &Bank) { - const std::vector &Registers = Bank.getRegisters(); + const auto &Registers = Bank.getRegisters(); // Register enums are stored as uint16_t in the tables. Make sure we'll fit. assert(Registers.size() <= 0xffff && "Too many regs to fit in tables"); - std::string Namespace = Registers[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = + Registers.front().TheDef->getValueAsString("Namespace"); emitSourceFileHeader("Target Register Enum Values", OS); @@ -90,17 +93,16 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoRegister,\n"; - for (unsigned i = 0, e = Registers.size(); i != e; ++i) - OS << " " << Registers[i]->getName() << " = " << - Registers[i]->EnumValue << ",\n"; - assert(Registers.size() == Registers[Registers.size()-1]->EnumValue && + for (const auto &Reg : Registers) + OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n"; + assert(Registers.size() == Registers.back().EnumValue && "Register enum value mismatch!"); OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n"; OS << "};\n"; if (!Namespace.empty()) OS << "}\n"; - ArrayRef RegisterClasses = Bank.getRegClasses(); + const auto &RegisterClasses = Bank.getRegClasses(); if (!RegisterClasses.empty()) { // RegisterClass enums are stored as uint16_t in the tables. @@ -111,11 +113,9 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - if (i) OS << ",\n"; - OS << " " << RegisterClasses[i]->getName() << "RegClassID"; - OS << " = " << i; - } + for (const auto &RC : RegisterClasses) + OS << " " << RC.getName() << "RegClassID" + << " = " << RC.EnumValue << ",\n"; OS << "\n };\n"; if (!Namespace.empty()) OS << "}\n"; @@ -137,25 +137,38 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS, OS << "}\n"; } - ArrayRef SubRegIndices = Bank.getSubRegIndices(); + auto &SubRegIndices = Bank.getSubRegIndices(); if (!SubRegIndices.empty()) { OS << "\n// Subregister indices\n"; - std::string Namespace = - SubRegIndices[0]->getNamespace(); + std::string Namespace = SubRegIndices.front().getNamespace(); if (!Namespace.empty()) OS << "namespace " << Namespace << " {\n"; OS << "enum {\n NoSubRegister,\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) - OS << " " << SubRegIndices[i]->getName() << ",\t// " << i+1 << "\n"; + unsigned i = 0; + for (const auto &Idx : SubRegIndices) + OS << " " << Idx.getName() << ",\t// " << ++i << "\n"; OS << " NUM_TARGET_SUBREGS\n};\n"; if (!Namespace.empty()) OS << "}\n"; } - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_ENUM\n\n"; } +static void printInt(raw_ostream &OS, int Val) { + OS << Val; +} + +static const char *getMinimalTypeForRange(uint64_t Range) { + assert(Range < 0xFFFFFFFFULL && "Enum too large"); + if (Range > 0xFFFF) + return "uint32_t"; + if (Range > 0xFF) + return "uint16_t"; + return "uint8_t"; +} + void RegisterInfoEmitter:: EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, const std::string &ClassName) { @@ -166,8 +179,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "const RegClassWeight &" << ClassName << "::\n" << "getRegClassWeight(const TargetRegisterClass *RC) const {\n" << " static const RegClassWeight RCWeightTable[] = {\n"; - for (unsigned i = 0, e = NumRCs; i != e; ++i) { - const CodeGenRegisterClass &RC = *RegBank.getRegClasses()[i]; + for (const auto &RC : RegBank.getRegClasses()) { const CodeGenRegister::Set &Regs = RC.getMembers(); if (Regs.empty()) OS << " {0, 0"; @@ -179,7 +191,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, } OS << "}, \t// " << RC.getName() << "\n"; } - OS << " {0, 0} };\n" + OS << " };\n" << " return RCWeightTable[RC->getID()];\n" << "}\n\n"; @@ -204,7 +216,7 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, assert(RU.Weight < 256 && "RegUnit too heavy"); OS << RU.Weight << ", "; } - OS << "0 };\n" + OS << "};\n" << " return RUWeightTable[RegUnit];\n"; } else { @@ -222,8 +234,11 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "const char *" << ClassName << "::\n" << "getRegPressureSetName(unsigned Idx) const {\n" << " static const char *PressureNameTable[] = {\n"; + unsigned MaxRegUnitWeight = 0; for (unsigned i = 0; i < NumSets; ++i ) { - OS << " \"" << RegBank.getRegSetAt(i).Name << "\",\n"; + const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); + MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight); + OS << " \"" << RegUnits.Name << "\",\n"; } OS << " nullptr };\n" << " return PressureNameTable[Idx];\n" @@ -233,63 +248,54 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "// This limit must be adjusted dynamically for reserved registers.\n" << "unsigned " << ClassName << "::\n" << "getRegPressureSetLimit(unsigned Idx) const {\n" - << " static const unsigned PressureLimitTable[] = {\n"; + << " static const " << getMinimalTypeForRange(MaxRegUnitWeight) + << " PressureLimitTable[] = {\n"; for (unsigned i = 0; i < NumSets; ++i ) { const RegUnitSet &RegUnits = RegBank.getRegSetAt(i); OS << " " << RegUnits.Weight << ", \t// " << i << ": " << RegUnits.Name << "\n"; } - OS << " 0 };\n" + OS << " };\n" << " return PressureLimitTable[Idx];\n" << "}\n\n"; + SequenceToOffsetTable> PSetsSeqs; + // This table may be larger than NumRCs if some register units needed a list // of unit sets that did not correspond to a register class. unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists(); - OS << "/// Table of pressure sets per register class or unit.\n" - << "static const int RCSetsTable[] = {\n "; - std::vector RCSetStarts(NumRCUnitSets); - for (unsigned i = 0, StartIdx = 0, e = NumRCUnitSets; i != e; ++i) { - RCSetStarts[i] = StartIdx; + std::vector> PSets(NumRCUnitSets); + + for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) { ArrayRef PSetIDs = RegBank.getRCPressureSetIDs(i); - std::vector PSets; - PSets.reserve(PSetIDs.size()); + PSets[i].reserve(PSetIDs.size()); for (ArrayRef::iterator PSetI = PSetIDs.begin(), PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { - PSets.push_back(RegBank.getRegPressureSet(*PSetI).Order); + PSets[i].push_back(RegBank.getRegPressureSet(*PSetI).Order); } - std::sort(PSets.begin(), PSets.end()); - for (unsigned j = 0, e = PSets.size(); j < e; ++j) { - OS << PSets[j] << ", "; - ++StartIdx; - } - OS << "-1, \t// #" << RCSetStarts[i] << " "; - if (i < NumRCs) - OS << RegBank.getRegClasses()[i]->getName(); - else { - OS << "inferred"; - for (ArrayRef::iterator PSetI = PSetIDs.begin(), - PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) { - OS << "~" << RegBank.getRegSetAt(*PSetI).Name; - } - } - OS << "\n "; - ++StartIdx; + std::sort(PSets[i].begin(), PSets[i].end()); + PSetsSeqs.add(PSets[i]); } - OS << "-1 };\n\n"; + + PSetsSeqs.layout(); + + OS << "/// Table of pressure sets per register class or unit.\n" + << "static const int RCSetsTable[] = {\n"; + PSetsSeqs.emit(OS, printInt, "-1"); + OS << "};\n\n"; OS << "/// Get the dimensions of register pressure impacted by this " << "register class.\n" << "/// Returns a -1 terminated array of pressure set IDs\n" << "const int* " << ClassName << "::\n" << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n"; - OS << " static const unsigned RCSetStartTable[] = {\n "; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + << " RCSetStartTable[] = {\n "; for (unsigned i = 0, e = NumRCs; i != e; ++i) { - OS << RCSetStarts[i] << ","; + OS << PSetsSeqs.get(PSets[i]) << ","; } - OS << "0 };\n" - << " unsigned SetListStart = RCSetStartTable[RC->getID()];\n" - << " return &RCSetsTable[SetListStart];\n" + OS << "};\n" + << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n" << "}\n\n"; OS << "/// Get the dimensions of register pressure impacted by this " @@ -299,29 +305,28 @@ EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank, << "getRegUnitPressureSets(unsigned RegUnit) const {\n" << " assert(RegUnit < " << RegBank.getNumNativeRegUnits() << " && \"invalid register unit\");\n"; - OS << " static const unsigned RUSetStartTable[] = {\n "; + OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size()-1) + << " RUSetStartTable[] = {\n "; for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits(); UnitIdx < UnitEnd; ++UnitIdx) { - OS << RCSetStarts[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx] << ","; + OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx]) + << ","; } - OS << "0 };\n" - << " unsigned SetListStart = RUSetStartTable[RegUnit];\n" - << " return &RCSetsTable[SetListStart];\n" + OS << "};\n" + << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n" << "}\n\n"; } -void -RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, - const std::vector &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMappingTables( + raw_ostream &OS, const std::deque &Regs, bool isCtor) { // Collect all information about dwarf register numbers typedef std::map, LessRecordRegister> DwarfRegNumsMapTy; DwarfRegNumsMapTy DwarfRegNums; // First, just pull all provided information to the map unsigned maxLength = 0; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; std::vector RegNums = Reg->getValueAsListOfInts("DwarfNumbers"); maxLength = std::max((size_t)maxLength, RegNums.size()); if (DwarfRegNums.count(Reg)) @@ -339,7 +344,7 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, for (unsigned i = I->second.size(), e = maxLength; i != e; ++i) I->second.push_back(-1); - std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace"); OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n"; @@ -379,16 +384,16 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize"; if (!isCtor) - OS << " = sizeof(" << Namespace + OS << " = array_lengthof(" << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "Dwarf2L)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + << "Dwarf2L);\n\n"; else OS << ";\n\n"; } } - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; const RecordVal *V = Reg->getValue("DwarfAlias"); if (!V || !V->getValue()) continue; @@ -427,24 +432,21 @@ RegisterInfoEmitter::EmitRegMappingTables(raw_ostream &OS, OS << "extern const unsigned " << Namespace << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize"; if (!isCtor) - OS << " = sizeof(" << Namespace - << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i - << "L2Dwarf)/sizeof(MCRegisterInfo::DwarfLLVMRegPair);\n\n"; + OS << " = array_lengthof(" << Namespace + << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n"; else OS << ";\n\n"; } } } -void -RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, - const std::vector &Regs, - bool isCtor) { +void RegisterInfoEmitter::EmitRegMapping( + raw_ostream &OS, const std::deque &Regs, bool isCtor) { // Emit the initializer so the tables from EmitRegMappingTables get wired up // to the MCRegisterInfo object. unsigned maxLength = 0; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (auto &RE : Regs) { + Record *Reg = RE.TheDef; maxLength = std::max((size_t)maxLength, Reg->getValueAsListOfInts("DwarfNumbers").size()); } @@ -452,7 +454,7 @@ RegisterInfoEmitter::EmitRegMapping(raw_ostream &OS, if (!maxLength) return; - std::string Namespace = Regs[0]->TheDef->getValueAsString("Namespace"); + std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace"); // Emit reverse information about the dwarf register numbers. for (unsigned j = 0; j < 2; ++j) { @@ -566,6 +568,7 @@ static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) { // 0 differential which means we can't encode repeated elements. typedef SmallVector DiffVec; +typedef SmallVector MaskVec; // Differentially encode a sequence of numbers into V. The starting value and // terminating 0 are not added to V, so it will have the same size as List. @@ -598,6 +601,10 @@ static void printDiff16(raw_ostream &OS, uint16_t Val) { OS << Val; } +static void printMask(raw_ostream &OS, unsigned Val) { + OS << format("0x%08X", Val); +} + // Try to combine Idx's compose map into Vec if it is compatible. // Return false if it's not possible. static bool combine(const CodeGenSubRegIndex *Idx, @@ -617,20 +624,11 @@ static bool combine(const CodeGenSubRegIndex *Idx, return true; } -static const char *getMinimalTypeForRange(uint64_t Range) { - assert(Range < 0xFFFFFFFFULL && "Enum too large"); - if (Range > 0xFFFF) - return "uint32_t"; - if (Range > 0xFF) - return "uint16_t"; - return "uint8_t"; -} - void RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank, const std::string &ClName) { - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + const auto &SubRegIndices = RegBank.getSubRegIndices(); OS << "unsigned " << ClName << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n"; @@ -645,10 +643,12 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, SmallVector RowMap; SmallVector, 4> Rows; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + auto SubRegIndicesSize = + std::distance(SubRegIndices.begin(), SubRegIndices.end()); + for (const auto &Idx : SubRegIndices) { unsigned Found = ~0u; for (unsigned r = 0, re = Rows.size(); r != re; ++r) { - if (combine(SubRegIndices[i], Rows[r])) { + if (combine(&Idx, Rows[r])) { Found = r; break; } @@ -656,27 +656,27 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, if (Found == ~0u) { Found = Rows.size(); Rows.resize(Found + 1); - Rows.back().resize(SubRegIndices.size()); - combine(SubRegIndices[i], Rows.back()); + Rows.back().resize(SubRegIndicesSize); + combine(&Idx, Rows.back()); } RowMap.push_back(Found); } // Output the row map if there is multiple rows. if (Rows.size() > 1) { - OS << " static const " << getMinimalTypeForRange(Rows.size()) - << " RowMap[" << SubRegIndices.size() << "] = {\n "; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + OS << " static const " << getMinimalTypeForRange(Rows.size()) << " RowMap[" + << SubRegIndicesSize << "] = {\n "; + for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) OS << RowMap[i] << ", "; OS << "\n };\n"; } // Output the rows. - OS << " static const " << getMinimalTypeForRange(SubRegIndices.size()+1) - << " Rows[" << Rows.size() << "][" << SubRegIndices.size() << "] = {\n"; + OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1) + << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n"; for (unsigned r = 0, re = Rows.size(); r != re; ++r) { OS << " { "; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) + for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i) if (Rows[r][i]) OS << Rows[r][i]->EnumValue << ", "; else @@ -685,8 +685,8 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, } OS << " };\n\n"; - OS << " --IdxA; assert(IdxA < " << SubRegIndices.size() << ");\n" - << " --IdxB; assert(IdxB < " << SubRegIndices.size() << ");\n"; + OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << ");\n" + << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n"; if (Rows.size() > 1) OS << " return Rows[RowMap[IdxA]][IdxB];\n"; else @@ -694,6 +694,95 @@ RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS, OS << "}\n\n"; } +void +RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS, + CodeGenRegBank &RegBank, + const std::string &ClName) { + // See the comments in computeSubRegLaneMasks() for our goal here. + const auto &SubRegIndices = RegBank.getSubRegIndices(); + + // Create a list of Mask+Rotate operations, with equivalent entries merged. + SmallVector SubReg2SequenceIndexMap; + SmallVector, 4> Sequences; + for (const auto &Idx : SubRegIndices) { + const SmallVector &IdxSequence + = Idx.CompositionLaneMaskTransform; + + unsigned Found = ~0u; + unsigned SIdx = 0; + unsigned NextSIdx; + for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) { + SmallVectorImpl &Sequence = Sequences[s]; + NextSIdx = SIdx + Sequence.size() + 1; + if (Sequence.size() != IdxSequence.size()) + continue; + bool Identical = true; + for (size_t o = 0, oe = Sequence.size(); o != oe; ++o) { + if (Sequence[o] != IdxSequence[o]) { + Identical = false; + break; + } + } + if (Identical) { + Found = SIdx; + break; + } + } + if (Found == ~0u) { + Sequences.push_back(IdxSequence); + Found = SIdx; + } + SubReg2SequenceIndexMap.push_back(Found); + } + + OS << "unsigned " << ClName + << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, unsigned LaneMask)" + " const {\n"; + + OS << " struct MaskRolOp {\n" + " unsigned Mask;\n" + " uint8_t RotateLeft;\n" + " };\n" + " static const MaskRolOp Seqs[] = {\n"; + unsigned Idx = 0; + for (size_t s = 0, se = Sequences.size(); s != se; ++s) { + OS << " "; + const SmallVectorImpl &Sequence = Sequences[s]; + for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) { + const MaskRolPair &P = Sequence[p]; + OS << format("{ 0x%08X, %2u }, ", P.Mask, P.RotateLeft); + } + OS << "{ 0, 0 }"; + if (s+1 != se) + OS << ", "; + OS << " // Sequence " << Idx << "\n"; + Idx += Sequence.size() + 1; + } + OS << " };\n" + " static const MaskRolOp *CompositeSequences[] = {\n"; + for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) { + OS << " "; + unsigned Idx = SubReg2SequenceIndexMap[i]; + OS << format("&Seqs[%u]", Idx); + if (i+1 != e) + OS << ","; + OS << " // to " << SubRegIndices[i].getName() << "\n"; + } + OS << " };\n\n"; + + OS << " --IdxA; assert(IdxA < " << SubRegIndices.size() + << " && \"Subregister index out of bounds\");\n" + " unsigned Result = 0;\n" + " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)" + " {\n" + " unsigned Masked = LaneMask & Ops->Mask;\n" + " Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n" + " Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n" + " }\n" + " return Result;\n" + "}\n"; +} + // // runMCDesc - Print out MC register descriptions. // @@ -705,9 +794,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\n#ifdef GET_REGINFO_MC_DESC\n"; OS << "#undef GET_REGINFO_MC_DESC\n"; - const std::vector &Regs = RegBank.getRegisters(); + const auto &Regs = RegBank.getRegisters(); - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + auto &SubRegIndices = RegBank.getSubRegIndices(); // The lists of sub-registers and super-registers go in the same array. That // allows us to share suffixes. typedef std::vector RegVec; @@ -719,6 +808,10 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, SmallVector RegUnitLists(Regs.size()); SmallVector RegUnitInitScale(Regs.size()); + // List of lane masks accompanying register unit sequences. + SequenceToOffsetTable LaneMaskSeqs; + SmallVector RegUnitLaneMasks(Regs.size()); + // Keep track of sub-register names as well. These are not differentially // encoded. typedef SmallVector SubRegIdxVec; @@ -728,27 +821,27 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, SequenceToOffsetTable RegStrings; // Precompute register lists for the SequenceToOffsetTable. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - - RegStrings.add(Reg->getName()); + unsigned i = 0; + for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) { + const auto &Reg = *I; + RegStrings.add(Reg.getName()); // Compute the ordered sub-register list. SetVector SR; - Reg->addSubRegsPreOrder(SR, RegBank); - diffEncode(SubRegLists[i], Reg->EnumValue, SR.begin(), SR.end()); + Reg.addSubRegsPreOrder(SR, RegBank); + diffEncode(SubRegLists[i], Reg.EnumValue, SR.begin(), SR.end()); DiffSeqs.add(SubRegLists[i]); // Compute the corresponding sub-register indexes. SubRegIdxVec &SRIs = SubRegIdxLists[i]; for (unsigned j = 0, je = SR.size(); j != je; ++j) - SRIs.push_back(Reg->getSubRegIndex(SR[j])); + SRIs.push_back(Reg.getSubRegIndex(SR[j])); SubRegIdxSeqs.add(SRIs); // Super-registers are already computed. - const RegVec &SuperRegList = Reg->getSuperRegs(); - diffEncode(SuperRegLists[i], Reg->EnumValue, - SuperRegList.begin(), SuperRegList.end()); + const RegVec &SuperRegList = Reg.getSuperRegs(); + diffEncode(SuperRegLists[i], Reg.EnumValue, SuperRegList.begin(), + SuperRegList.end()); DiffSeqs.add(SuperRegLists[i]); // Differentially encode the register unit list, seeded by register number. @@ -763,22 +856,36 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // // Check the neighboring registers for arithmetic progressions. unsigned ScaleA = ~0u, ScaleB = ~0u; - ArrayRef RUs = Reg->getNativeRegUnits(); - if (i > 0 && Regs[i-1]->getNativeRegUnits().size() == RUs.size()) - ScaleB = RUs.front() - Regs[i-1]->getNativeRegUnits().front(); - if (i+1 != Regs.size() && - Regs[i+1]->getNativeRegUnits().size() == RUs.size()) - ScaleA = Regs[i+1]->getNativeRegUnits().front() - RUs.front(); + ArrayRef RUs = Reg.getNativeRegUnits(); + if (I != Regs.begin() && + std::prev(I)->getNativeRegUnits().size() == RUs.size()) + ScaleB = RUs.front() - std::prev(I)->getNativeRegUnits().front(); + if (std::next(I) != Regs.end() && + std::next(I)->getNativeRegUnits().size() == RUs.size()) + ScaleA = std::next(I)->getNativeRegUnits().front() - RUs.front(); unsigned Scale = std::min(ScaleB, ScaleA); // Default the scale to 0 if it can't be encoded in 4 bits. if (Scale >= 16) Scale = 0; RegUnitInitScale[i] = Scale; - DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg->EnumValue, RUs)); + DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg.EnumValue, RUs)); + + const auto &RUMasks = Reg.getRegUnitLaneMasks(); + MaskVec &LaneMaskVec = RegUnitLaneMasks[i]; + assert(LaneMaskVec.empty()); + LaneMaskVec.insert(LaneMaskVec.begin(), RUMasks.begin(), RUMasks.end()); + // Terminator mask should not be used inside of the list. +#ifndef NDEBUG + for (unsigned M : LaneMaskVec) { + assert(M != ~0u && "terminator mask should not be part of the list"); + } +#endif + LaneMaskSeqs.add(LaneMaskVec); } // Compute the final layout of the sequence table. DiffSeqs.layout(); + LaneMaskSeqs.layout(); SubRegIdxSeqs.layout(); OS << "namespace llvm {\n\n"; @@ -790,6 +897,11 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, DiffSeqs.emit(OS, printDiff16); OS << "};\n\n"; + // Emit the shared table of regunit lane mask sequences. + OS << "extern const unsigned " << TargetName << "LaneMaskLists[] = {\n"; + LaneMaskSeqs.emit(OS, printMask, "~0u"); + OS << "};\n\n"; + // Emit the table of sub-register indexes. OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n"; SubRegIdxSeqs.emit(OS, printSubRegIndex); @@ -799,12 +911,9 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterInfo::SubRegCoveredBits " << TargetName << "SubRegIdxRanges[] = {\n"; OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n"; - for (ArrayRef::const_iterator - SRI = SubRegIndices.begin(), SRE = SubRegIndices.end(); - SRI != SRE; ++SRI) { - OS << " { " << (*SRI)->Offset << ", " - << (*SRI)->Size - << " },\t// " << (*SRI)->getName() << "\n"; + for (const auto &Idx : SubRegIndices) { + OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// " + << Idx.getName() << "\n"; } OS << "};\n\n"; @@ -816,16 +925,17 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[] = { // Descriptors\n"; - OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0 },\n"; + OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n"; // Emit the register descriptors now. - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister *Reg = Regs[i]; - OS << " { " << RegStrings.get(Reg->getName()) << ", " - << DiffSeqs.get(SubRegLists[i]) << ", " - << DiffSeqs.get(SuperRegLists[i]) << ", " - << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " - << (DiffSeqs.get(RegUnitLists[i])*16 + RegUnitInitScale[i]) << " },\n"; + i = 0; + for (const auto &Reg : Regs) { + OS << " { " << RegStrings.get(Reg.getName()) << ", " + << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i]) + << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", " + << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", " + << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n"; + ++i; } OS << "};\n\n"; // End of register descriptors... @@ -843,19 +953,22 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "};\n\n"; - ArrayRef RegisterClasses = RegBank.getRegClasses(); + const auto &RegisterClasses = RegBank.getRegClasses(); // Loop over all of the register classes... emitting each one. OS << "namespace { // Register classes...\n"; + SequenceToOffsetTable RegClassStrings; + // Emit the register enum value arrays for each RegisterClass - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Order = RC.getOrder(); // Give the register class a legal C name if it's anonymous. std::string Name = RC.getName(); + RegClassStrings.add(Name); + // Emit the register list now. OS << " // " << Name << " Register Class...\n" << " const MCPhysReg " << Name @@ -880,20 +993,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "}\n\n"; + RegClassStrings.layout(); + OS << "extern const char " << TargetName << "RegClassStrings[] = {\n"; + RegClassStrings.emit(OS, printChar); + OS << "};\n\n"; + OS << "extern const MCRegisterClass " << TargetName << "MCRegisterClasses[] = {\n"; - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; - + for (const auto &RC : RegisterClasses) { // Asserts to make sure values will fit in table assuming types from // MCRegisterInfo.h assert((RC.SpillSize/8) <= 0xffff && "SpillSize too large."); assert((RC.SpillAlignment/8) <= 0xffff && "SpillAlignment too large."); assert(RC.CopyCost >= -128 && RC.CopyCost <= 127 && "Copy cost too large."); - OS << " { " << '\"' << RC.getName() << "\", " - << RC.getName() << ", " << RC.getName() << "Bits, " + OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, " + << RegClassStrings.get(RC.getName()) << ", " << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), " << RC.getQualifiedName() + "RegClassID" << ", " << RC.SpillSize/8 << ", " @@ -911,8 +1027,8 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "RegEncodingTable[] = {\n"; // Add entry for NoRegister OS << " 0,\n"; - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - Record *Reg = Regs[i]->TheDef; + for (const auto &RE : Regs) { + Record *Reg = RE.TheDef; BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding"); uint64_t Value = 0; for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) { @@ -926,24 +1042,23 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, // MCRegisterInfo initialization routine. OS << "static inline void Init" << TargetName << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, " - << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) {\n" + << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) " + "{\n" << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " - << RegisterClasses.size() << ", " - << TargetName << "RegUnitRoots, " - << RegBank.getNumNativeRegUnits() << ", " - << TargetName << "RegDiffLists, " - << TargetName << "RegStrings, " - << TargetName << "SubRegIdxLists, " - << (SubRegIndices.size() + 1) << ",\n" - << TargetName << "SubRegIdxRanges, " - << " " << TargetName << "RegEncodingTable);\n\n"; + << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, " + << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, " + << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, " + << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, " + << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, " + << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n" + << TargetName << "SubRegIdxRanges, " << TargetName + << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); OS << "}\n\n"; - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_MC_DESC\n\n"; } @@ -970,6 +1085,8 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, if (!RegBank.getSubRegIndices().empty()) { OS << " unsigned composeSubRegIndicesImpl" << "(unsigned, unsigned) const override;\n" + << " unsigned composeSubRegIndexLaneMaskImpl" + << "(unsigned, unsigned) const override;\n" << " const TargetRegisterClass *getSubClassWithSubReg" << "(const TargetRegisterClass*, unsigned) const override;\n"; } @@ -985,14 +1102,13 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, << "unsigned RegUnit) const override;\n" << "};\n\n"; - ArrayRef RegisterClasses = RegBank.getRegClasses(); + const auto &RegisterClasses = RegBank.getRegClasses(); if (!RegisterClasses.empty()) { - OS << "namespace " << RegisterClasses[0]->Namespace + OS << "namespace " << RegisterClasses.front().Namespace << " { // Register classes\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; + for (const auto &RC : RegisterClasses) { const std::string &Name = RC.getName(); // Output the extern for the instance. @@ -1000,7 +1116,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target, } OS << "} // end of namespace " << TargetName << "\n\n"; } - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_HEADER\n\n"; } @@ -1022,15 +1138,14 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "MCRegisterClasses[];\n"; // Start out by emitting each of the register classes. - ArrayRef RegisterClasses = RegBank.getRegClasses(); - ArrayRef SubRegIndices = RegBank.getSubRegIndices(); + const auto &RegisterClasses = RegBank.getRegClasses(); + const auto &SubRegIndices = RegBank.getSubRegIndices(); // Collect all registers belonging to any allocatable class. std::set AllocatableRegs; // Collect allocatable registers. - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Order = RC.getOrder(); if (RC.Allocatable) @@ -1039,8 +1154,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Build a shared array of value types. SequenceToOffsetTable > VTSeqs; - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) - VTSeqs.add(RegisterClasses[rc]->VTs); + for (const auto &RC : RegisterClasses) + VTSeqs.add(RC.VTs); VTSeqs.layout(); OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n"; VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); @@ -1048,18 +1163,17 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit SubRegIndex names, skipping 0. OS << "\nstatic const char *const SubRegIndexNameTable[] = { \""; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - OS << SubRegIndices[i]->getName(); - if (i + 1 != e) - OS << "\", \""; + + for (const auto &Idx : SubRegIndices) { + OS << Idx.getName(); + OS << "\", \""; } OS << "\" };\n\n"; // Emit SubRegIndex lane masks, including 0. OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n"; - for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { - OS << format(" 0x%08x, // ", SubRegIndices[i]->LaneMask) - << SubRegIndices[i]->getName() << '\n'; + for (const auto &Idx : SubRegIndices) { + OS << format(" 0x%08x, // ", Idx.LaneMask) << Idx.getName() << '\n'; } OS << " };\n\n"; @@ -1094,24 +1208,22 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, SequenceToOffsetTable SuperRegIdxSeqs; BitVector MaskBV(RegisterClasses.size()); - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n "; printBitVectorAsHex(OS, RC.getSubClasses(), 32); // Emit super-reg class masks for any relevant SubRegIndices that can // project into RC. - IdxList &SRIList = SuperRegIdxLists[rc]; - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *Idx = SubRegIndices[sri]; + IdxList &SRIList = SuperRegIdxLists[RC.EnumValue]; + for (auto &Idx : SubRegIndices) { MaskBV.reset(); - RC.getSuperRegClasses(Idx, MaskBV); + RC.getSuperRegClasses(&Idx, MaskBV); if (MaskBV.none()) continue; - SRIList.push_back(Idx); + SRIList.push_back(&Idx); OS << "\n "; printBitVectorAsHex(OS, MaskBV, 32); - OS << "// " << Idx->getName(); + OS << "// " << Idx.getName(); } SuperRegIdxSeqs.add(SRIList); OS << "\n};\n\n"; @@ -1123,8 +1235,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "};\n\n"; // Emit NULL terminated super-class lists. - for (unsigned rc = 0, e = RegisterClasses.size(); rc != e; ++rc) { - const CodeGenRegisterClass &RC = *RegisterClasses[rc]; + for (const auto &RC : RegisterClasses) { ArrayRef Supers = RC.getSuperClasses(); // Skip classes without supers. We can reuse NullRegClasses. @@ -1133,14 +1244,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "static const TargetRegisterClass *const " << RC.getName() << "Superclasses[] = {\n"; - for (unsigned i = 0; i != Supers.size(); ++i) - OS << " &" << Supers[i]->getQualifiedName() << "RegClass,\n"; + for (const auto *Super : Supers) + OS << " &" << Super->getQualifiedName() << "RegClass,\n"; OS << " nullptr\n};\n\n"; } // Emit methods. - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; + for (const auto &RC : RegisterClasses) { if (!RC.AltOrderSelect.empty()) { OS << "\nstatic inline unsigned " << RC.getName() << "AltOrderSelect(const MachineFunction &MF) {" @@ -1168,22 +1278,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << ")\n };\n const unsigned Select = " << RC.getName() << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders() << ");\n return Order[Select];\n}\n"; - } + } } // Now emit the actual value-initialized register class instances. - OS << "namespace " << RegisterClasses[0]->Namespace + OS << "\nnamespace " << RegisterClasses.front().Namespace << " { // Register class instances\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) { - const CodeGenRegisterClass &RC = *RegisterClasses[i]; - OS << " extern const TargetRegisterClass " - << RegisterClasses[i]->getName() << "RegClass = {\n " - << '&' << Target.getName() << "MCRegisterClasses[" << RC.getName() - << "RegClassID],\n " - << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " - << RC.getName() << "SubClassMask,\n SuperRegIdxSeqs + " - << SuperRegIdxSeqs.get(SuperRegIdxLists[i]) << ",\n "; + for (const auto &RC : RegisterClasses) { + OS << " extern const TargetRegisterClass " << RC.getName() + << "RegClass = {\n " << '&' << Target.getName() + << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n " + << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName() + << "SubClassMask,\n SuperRegIdxSeqs + " + << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n " + << format("0x%08x,\n ", RC.LaneMask); if (RC.getSuperClasses().empty()) OS << "NullRegClasses,\n "; else @@ -1200,9 +1309,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << "\nnamespace {\n"; OS << " const TargetRegisterClass* const RegisterClasses[] = {\n"; - for (unsigned i = 0, e = RegisterClasses.size(); i != e; ++i) - OS << " &" << RegisterClasses[i]->getQualifiedName() - << "RegClass,\n"; + for (const auto &RC : RegisterClasses) + OS << " &" << RC.getQualifiedName() << "RegClass,\n"; OS << " };\n"; OS << "}\n"; // End of anonymous namespace... @@ -1212,9 +1320,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n"; OS << " { 0, 0 },\n"; - const std::vector &Regs = RegBank.getRegisters(); - for (unsigned i = 0, e = Regs.size(); i != e; ++i) { - const CodeGenRegister &Reg = *Regs[i]; + const auto &Regs = RegBank.getRegisters(); + for (const auto &Reg : Regs) { OS << " { "; OS << Reg.CostPerUse << ", " << int(AllocatableRegs.count(Reg.TheDef)) << " },\n"; @@ -1224,8 +1331,13 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, std::string ClassName = Target.getName() + "GenRegisterInfo"; - if (!SubRegIndices.empty()) + auto SubRegIndicesSize = + std::distance(SubRegIndices.begin(), SubRegIndices.end()); + + if (!SubRegIndices.empty()) { emitComposeSubRegIndices(OS, RegBank, ClassName); + emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName); + } // Emit getSubClassWithSubReg. if (!SubRegIndices.empty()) { @@ -1240,23 +1352,21 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, OS << " static const uint16_t Table["; else PrintFatalError("Too many register classes."); - OS << RegisterClasses.size() << "][" << SubRegIndices.size() << "] = {\n"; - for (unsigned rci = 0, rce = RegisterClasses.size(); rci != rce; ++rci) { - const CodeGenRegisterClass &RC = *RegisterClasses[rci]; + OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n"; + for (const auto &RC : RegisterClasses) { OS << " {\t// " << RC.getName() << "\n"; - for (unsigned sri = 0, sre = SubRegIndices.size(); sri != sre; ++sri) { - CodeGenSubRegIndex *Idx = SubRegIndices[sri]; - if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(Idx)) - OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx->getName() + for (auto &Idx : SubRegIndices) { + if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx)) + OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName() << " -> " << SRC->getName() << "\n"; else - OS << " 0,\t// " << Idx->getName() << "\n"; + OS << " 0,\t// " << Idx.getName() << "\n"; } OS << " },\n"; } OS << " };\n assert(RC && \"Missing regclass\");\n" << " if (!Idx) return RC;\n --Idx;\n" - << " assert(Idx < " << SubRegIndices.size() << " && \"Bad subreg\");\n" + << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n" << " unsigned TV = Table[RC->getID()][Idx];\n" << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n"; } @@ -1266,7 +1376,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, // Emit the constructor of the class... OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n"; + OS << "extern const unsigned " << TargetName << "LaneMaskLists[];\n"; OS << "extern const char " << TargetName << "RegStrings[];\n"; + OS << "extern const char " << TargetName << "RegClassStrings[];\n"; OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n"; OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n"; OS << "extern const MCRegisterInfo::SubRegCoveredBits " @@ -1282,15 +1394,17 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, 0x"; OS.write_hex(RegBank.CoveringLanes); OS << ") {\n" - << " InitMCRegisterInfo(" << TargetName << "RegDesc, " - << Regs.size()+1 << ", RA, PC,\n " << TargetName + << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1 + << ", RA, PC,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" << " " << TargetName << "RegUnitRoots,\n" << " " << RegBank.getNumNativeRegUnits() << ",\n" << " " << TargetName << "RegDiffLists,\n" + << " " << TargetName << "LaneMaskLists,\n" << " " << TargetName << "RegStrings,\n" + << " " << TargetName << "RegClassStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" - << " " << SubRegIndices.size() + 1 << ",\n" + << " " << SubRegIndicesSize + 1 << ",\n" << " " << TargetName << "SubRegIdxRanges,\n" << " " << TargetName << "RegEncodingTable);\n\n"; @@ -1334,7 +1448,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, } OS << "\n\n"; - OS << "} // End llvm namespace \n"; + OS << "} // End llvm namespace\n"; OS << "#endif // GET_REGINFO_TARGET_DESC\n\n"; } diff --git a/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h index e6ab664..66506ea 100644 --- a/utils/TableGen/SequenceToOffsetTable.h +++ b/utils/TableGen/SequenceToOffsetTable.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H -#define TBLGEN_SEQUENCE_TO_OFFSET_TABLE_H +#ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H +#define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H #include "llvm/Support/raw_ostream.h" #include @@ -84,6 +84,11 @@ public: bool empty() const { return Seqs.empty(); } + unsigned size() const { + assert(Entries && "Call layout() before size()"); + return Entries; + } + /// layout - Computes the final table layout. void layout() { assert(Entries == 0 && "Can only call layout() once"); diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp index a59eead..9f2fc92 100644 --- a/utils/TableGen/SubtargetEmitter.cpp +++ b/utils/TableGen/SubtargetEmitter.cpp @@ -386,7 +386,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS, for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(), PE = SchedModels.procModelEnd(); PI != PE; ++PI) { - if (!ItinsDefSet.insert(PI->ItinsDef)) + if (!ItinsDefSet.insert(PI->ItinsDef).second) continue; std::vector FUs = PI->ItinsDef->getValueAsListOfDefs("FU"); @@ -565,7 +565,7 @@ EmitItineraries(raw_ostream &OS, PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) { Record *ItinsDef = PI->ItinsDef; - if (!ItinsDefSet.insert(ItinsDef)) + if (!ItinsDefSet.insert(ItinsDef).second) continue; // Get processor itinerary name @@ -575,12 +575,13 @@ EmitItineraries(raw_ostream &OS, assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator"); std::vector &ItinList = *ProcItinListsIter; + // Empty itineraries aren't referenced anywhere in the tablegen output + // so don't emit them. + if (ItinList.empty()) + continue; + OS << "\n"; OS << "static const llvm::InstrItinerary "; - if (ItinList.empty()) { - OS << '*' << Name << " = nullptr;\n"; - continue; - } // Begin processor itinerary table OS << Name << "[] = {\n"; @@ -1192,7 +1193,7 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { // Begin processor itinerary properties OS << "\n"; - OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n"; + OS << "static const llvm::MCSchedModel " << PI->ModelName << " = {\n"; EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ','); EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ','); EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ','); @@ -1217,10 +1218,10 @@ void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) { - SchedModels.schedClassBegin()) << ",\n"; else OS << " 0, 0, 0, 0, // No instruction-level machine model.\n"; - if (SchedModels.hasItineraries()) - OS << " " << PI->ItinsDef->getName() << ");\n"; + if (PI->hasItineraries()) + OS << " " << PI->ItinsDef->getName() << "};\n"; else - OS << " 0); // No Itinerary\n"; + OS << " nullptr}; // No Itinerary\n"; } } diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index bbd61f5..02fe4dc 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -143,9 +143,8 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { break; case PrintEnums: { - std::vector Recs = Records.getAllDerivedDefinitions(Class); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) - OS << Recs[i]->getName() << ", "; + for (Record *Rec : Records.getAllDerivedDefinitions(Class)) + OS << Rec->getName() << ", "; OS << "\n"; break; } @@ -153,13 +152,12 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { { SetTheory Sets; Sets.addFieldExpander("Set", "Elements"); - std::vector Recs = Records.getAllDerivedDefinitions("Set"); - for (unsigned i = 0, e = Recs.size(); i != e; ++i) { - OS << Recs[i]->getName() << " = ["; - const std::vector *Elts = Sets.expand(Recs[i]); + for (Record *Rec : Records.getAllDerivedDefinitions("Set")) { + OS << Rec->getName() << " = ["; + const std::vector *Elts = Sets.expand(Rec); assert(Elts && "Couldn't expand Set instance"); - for (unsigned ei = 0, ee = Elts->size(); ei != ee; ++ei) - OS << ' ' << (*Elts)[ei]->getName(); + for (Record *Elt : *Elts) + OS << ' ' << Elt->getName(); OS << " ]\n"; } break; diff --git a/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h index 28b626e..2dc03ce 100644 --- a/utils/TableGen/TableGenBackends.h +++ b/utils/TableGen/TableGenBackends.h @@ -13,6 +13,8 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H +#define LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H // A TableGen backend is a function that looks like // @@ -78,3 +80,5 @@ void EmitOptParser(RecordKeeper &RK, raw_ostream &OS); void EmitCTags(RecordKeeper &RK, raw_ostream &OS); } // End llvm namespace + +#endif diff --git a/utils/TableGen/X86DisassemblerShared.h b/utils/TableGen/X86DisassemblerShared.h index 9e79b9c..5895277 100644 --- a/utils/TableGen/X86DisassemblerShared.h +++ b/utils/TableGen/X86DisassemblerShared.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERSHARED_H -#define X86DISASSEMBLERSHARED_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H #include #include diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index fbcc6f2..fbe5502 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -75,13 +75,13 @@ static inline const char* stringForOperandEncoding(OperandEncoding encoding) { /// @return - True if child is a subset of parent, false otherwise. static inline bool inheritsFrom(InstructionContext child, InstructionContext parent, - bool VEX_LIG = false) { + bool VEX_LIG = false, bool AdSize64 = false) { if (child == parent) return true; switch (parent) { case IC: - return(inheritsFrom(child, IC_64BIT) || + return(inheritsFrom(child, IC_64BIT, AdSize64) || inheritsFrom(child, IC_OPSIZE) || inheritsFrom(child, IC_ADSIZE) || inheritsFrom(child, IC_XD) || @@ -89,13 +89,19 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT: return(inheritsFrom(child, IC_64BIT_REXW) || inheritsFrom(child, IC_64BIT_OPSIZE) || - inheritsFrom(child, IC_64BIT_ADSIZE) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_ADSIZE)) || inheritsFrom(child, IC_64BIT_XD) || inheritsFrom(child, IC_64BIT_XS)); case IC_OPSIZE: - return inheritsFrom(child, IC_64BIT_OPSIZE); + return inheritsFrom(child, IC_64BIT_OPSIZE) || + inheritsFrom(child, IC_OPSIZE_ADSIZE); case IC_ADSIZE: + return inheritsFrom(child, IC_OPSIZE_ADSIZE); + case IC_OPSIZE_ADSIZE: + return false; case IC_64BIT_ADSIZE: + return inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE); + case IC_64BIT_OPSIZE_ADSIZE: return false; case IC_XD: return inheritsFrom(child, IC_64BIT_XD); @@ -108,9 +114,12 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW: return(inheritsFrom(child, IC_64BIT_REXW_XS) || inheritsFrom(child, IC_64BIT_REXW_XD) || - inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); + inheritsFrom(child, IC_64BIT_REXW_OPSIZE) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE))); case IC_64BIT_OPSIZE: - return(inheritsFrom(child, IC_64BIT_REXW_OPSIZE)); + return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)) || + (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE)); case IC_64BIT_XD: return(inheritsFrom(child, IC_64BIT_REXW_XD)); case IC_64BIT_XS: @@ -121,6 +130,7 @@ static inline bool inheritsFrom(InstructionContext child, case IC_64BIT_REXW_XD: case IC_64BIT_REXW_XS: case IC_64BIT_REXW_OPSIZE: + case IC_64BIT_REXW_ADSIZE: return false; case IC_VEX: return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) || @@ -171,12 +181,17 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_OPSIZE: return inheritsFrom(child, IC_EVEX_W_OPSIZE) || inheritsFrom(child, IC_EVEX_L_W_OPSIZE); + case IC_EVEX_B: + return false; case IC_EVEX_W: case IC_EVEX_W_XS: case IC_EVEX_W_XD: case IC_EVEX_W_OPSIZE: return false; case IC_EVEX_L: + case IC_EVEX_L_K_B: + case IC_EVEX_L_KZ_B: + case IC_EVEX_L_B: case IC_EVEX_L_XS: case IC_EVEX_L_XD: case IC_EVEX_L_OPSIZE: @@ -205,38 +220,59 @@ static inline bool inheritsFrom(InstructionContext child, case IC_EVEX_XD_K: return inheritsFrom(child, IC_EVEX_W_XD_K) || inheritsFrom(child, IC_EVEX_L_W_XD_K); + case IC_EVEX_K_B: + case IC_EVEX_KZ: + return false; + case IC_EVEX_XS_KZ: + return inheritsFrom(child, IC_EVEX_W_XS_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XS_KZ); + case IC_EVEX_XD_KZ: + return inheritsFrom(child, IC_EVEX_W_XD_KZ) || + inheritsFrom(child, IC_EVEX_L_W_XD_KZ); + case IC_EVEX_KZ_B: case IC_EVEX_OPSIZE_K: case IC_EVEX_OPSIZE_B: + case IC_EVEX_OPSIZE_K_B: + case IC_EVEX_OPSIZE_KZ: + case IC_EVEX_OPSIZE_KZ_B: return false; case IC_EVEX_W_K: case IC_EVEX_W_XS_K: case IC_EVEX_W_XD_K: case IC_EVEX_W_OPSIZE_K: case IC_EVEX_W_OPSIZE_B: + case IC_EVEX_W_OPSIZE_K_B: return false; case IC_EVEX_L_K: case IC_EVEX_L_XS_K: case IC_EVEX_L_XD_K: case IC_EVEX_L_OPSIZE_K: + case IC_EVEX_L_OPSIZE_B: + case IC_EVEX_L_OPSIZE_K_B: return false; case IC_EVEX_W_KZ: case IC_EVEX_W_XS_KZ: case IC_EVEX_W_XD_KZ: case IC_EVEX_W_OPSIZE_KZ: + case IC_EVEX_W_OPSIZE_KZ_B: return false; case IC_EVEX_L_KZ: case IC_EVEX_L_XS_KZ: case IC_EVEX_L_XD_KZ: case IC_EVEX_L_OPSIZE_KZ: + case IC_EVEX_L_OPSIZE_KZ_B: return false; case IC_EVEX_L_W_K: case IC_EVEX_L_W_XS_K: case IC_EVEX_L_W_XD_K: case IC_EVEX_L_W_OPSIZE_K: + case IC_EVEX_L_W_OPSIZE_B: + case IC_EVEX_L_W_OPSIZE_K_B: case IC_EVEX_L_W_KZ: case IC_EVEX_L_W_XS_KZ: case IC_EVEX_L_W_XD_KZ: case IC_EVEX_L_W_OPSIZE_KZ: + case IC_EVEX_L_W_OPSIZE_KZ_B: return false; case IC_EVEX_L2_K: case IC_EVEX_L2_B: @@ -687,6 +723,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_OPSIZE)) o << "IC_64BIT_REXW_OPSIZE"; + else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && + (index & ATTR_ADSIZE)) + o << "IC_64BIT_REXW_ADSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE)) o << "IC_64BIT_XD_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE)) @@ -695,6 +734,9 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { o << "IC_64BIT_XS"; else if ((index & ATTR_64BIT) && (index & ATTR_XD)) o << "IC_64BIT_XD"; + else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE) && + (index & ATTR_ADSIZE)) + o << "IC_64BIT_OPSIZE_ADSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE)) o << "IC_64BIT_OPSIZE"; else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE)) @@ -711,6 +753,8 @@ void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const { o << "IC_XS"; else if (index & ATTR_XD) o << "IC_XD"; + else if ((index & ATTR_OPSIZE) && (index & ATTR_ADSIZE)) + o << "IC_OPSIZE_ADSIZE"; else if (index & ATTR_OPSIZE) o << "IC_OPSIZE"; else if (index & ATTR_ADSIZE) @@ -796,15 +840,6 @@ void DisassemblerTables::setTableFields(ModRMDecision &decision, InstructionSpecifier &previousInfo = InstructionSpecifiers[decision.instructionIDs[index]]; - // Instructions such as MOV8ao8 and MOV8ao8_16 differ only in the - // presence of the AdSize prefix. However, the disassembler doesn't - // care about that difference in the instruction definition; it - // handles 16-bit vs. 32-bit addressing for itself based purely - // on the 0x67 prefix and the CPU mode. So there's no need to - // disambiguate between them; just let them conflict/coexist. - if (previousInfo.name + "_16" == newInfo.name) - continue; - if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" || newInfo.name == "XCHG32ar" || newInfo.name == "XCHG32ar64" || @@ -836,15 +871,19 @@ void DisassemblerTables::setTableFields(OpcodeType type, const ModRMFilter &filter, InstrUID uid, bool is32bit, - bool ignoresVEX_L) { + bool ignoresVEX_L, + unsigned addressSize) { ContextDecision &decision = *Tables[type]; for (unsigned index = 0; index < IC_max; ++index) { - if (is32bit && inheritsFrom((InstructionContext)index, IC_64BIT)) + if ((is32bit || addressSize == 16) && + inheritsFrom((InstructionContext)index, IC_64BIT)) continue; + bool adSize64 = addressSize == 64; if (inheritsFrom((InstructionContext)index, - InstructionSpecifiers[uid].insnContext, ignoresVEX_L)) + InstructionSpecifiers[uid].insnContext, ignoresVEX_L, + adSize64)) setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode], filter, uid, diff --git a/utils/TableGen/X86DisassemblerTables.h b/utils/TableGen/X86DisassemblerTables.h index 1327375..5a8688b 100644 --- a/utils/TableGen/X86DisassemblerTables.h +++ b/utils/TableGen/X86DisassemblerTables.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86DISASSEMBLERTABLES_H -#define X86DISASSEMBLERTABLES_H +#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H +#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H #include "X86DisassemblerShared.h" #include "X86ModRMFilters.h" @@ -245,13 +245,15 @@ public: /// @param uid - The unique ID of the instruction. /// @param is32bit - Instructon is only 32-bit /// @param ignoresVEX_L - Instruction ignores VEX.L + /// @param AddrSize - Instructions address size 16/32/64. 0 is unspecified void setTableFields(OpcodeType type, InstructionContext insnContext, uint8_t opcode, const ModRMFilter &filter, InstrUID uid, bool is32bit, - bool ignoresVEX_L); + bool ignoresVEX_L, + unsigned AddrSize); /// specForUID - Returns the instruction specifier for a given unique /// instruction ID. Used when resolving collisions. diff --git a/utils/TableGen/X86ModRMFilters.h b/utils/TableGen/X86ModRMFilters.h index fac3838..d919c58 100644 --- a/utils/TableGen/X86ModRMFilters.h +++ b/utils/TableGen/X86ModRMFilters.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86MODRMFILTERS_H -#define X86MODRMFILTERS_H +#ifndef LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H +#define LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H #include "llvm/Support/DataTypes.h" diff --git a/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp index b7bd822..198ad10 100644 --- a/utils/TableGen/X86RecognizableInstr.cpp +++ b/utils/TableGen/X86RecognizableInstr.cpp @@ -32,48 +32,50 @@ using namespace llvm; MAP(C9, 38) \ MAP(CA, 39) \ MAP(CB, 40) \ - MAP(D0, 41) \ - MAP(D1, 42) \ - MAP(D4, 43) \ - MAP(D5, 44) \ - MAP(D6, 45) \ - MAP(D8, 46) \ - MAP(D9, 47) \ - MAP(DA, 48) \ - MAP(DB, 49) \ - MAP(DC, 50) \ - MAP(DD, 51) \ - MAP(DE, 52) \ - MAP(DF, 53) \ - MAP(E0, 54) \ - MAP(E1, 55) \ - MAP(E2, 56) \ - MAP(E3, 57) \ - MAP(E4, 58) \ - MAP(E5, 59) \ - MAP(E8, 60) \ - MAP(E9, 61) \ - MAP(EA, 62) \ - MAP(EB, 63) \ - MAP(EC, 64) \ - MAP(ED, 65) \ - MAP(EE, 66) \ - MAP(F0, 67) \ - MAP(F1, 68) \ - MAP(F2, 69) \ - MAP(F3, 70) \ - MAP(F4, 71) \ - MAP(F5, 72) \ - MAP(F6, 73) \ - MAP(F7, 74) \ - MAP(F8, 75) \ - MAP(F9, 76) \ - MAP(FA, 77) \ - MAP(FB, 78) \ - MAP(FC, 79) \ - MAP(FD, 80) \ - MAP(FE, 81) \ - MAP(FF, 82) + MAP(CF, 41) \ + MAP(D0, 42) \ + MAP(D1, 43) \ + MAP(D4, 44) \ + MAP(D5, 45) \ + MAP(D6, 46) \ + MAP(D7, 47) \ + MAP(D8, 48) \ + MAP(D9, 49) \ + MAP(DA, 50) \ + MAP(DB, 51) \ + MAP(DC, 52) \ + MAP(DD, 53) \ + MAP(DE, 54) \ + MAP(DF, 55) \ + MAP(E0, 56) \ + MAP(E1, 57) \ + MAP(E2, 58) \ + MAP(E3, 59) \ + MAP(E4, 60) \ + MAP(E5, 61) \ + MAP(E8, 62) \ + MAP(E9, 63) \ + MAP(EA, 64) \ + MAP(EB, 65) \ + MAP(EC, 66) \ + MAP(ED, 67) \ + MAP(EE, 68) \ + MAP(F0, 69) \ + MAP(F1, 70) \ + MAP(F2, 71) \ + MAP(F3, 72) \ + MAP(F4, 73) \ + MAP(F5, 74) \ + MAP(F6, 75) \ + MAP(F7, 76) \ + MAP(F8, 77) \ + MAP(F9, 78) \ + MAP(FA, 79) \ + MAP(FB, 80) \ + MAP(FC, 81) \ + MAP(FD, 82) \ + MAP(FE, 83) \ + MAP(FF, 84) // A clone of X86 since we can't depend on something that is generated. namespace X86Local { @@ -117,6 +119,10 @@ namespace X86Local { enum { OpSize16 = 1, OpSize32 = 2 }; + + enum { + AdSize16 = 1, AdSize32 = 2, AdSize64 = 3 + }; } using namespace X86Disassembler; @@ -192,7 +198,7 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables, Encoding = byteFromRec(Rec, "OpEncBits"); OpSize = byteFromRec(Rec, "OpSizeBits"); - HasAdSizePrefix = Rec->getValueAsBit("hasAdSizePrefix"); + AdSize = byteFromRec(Rec, "AdSizeBits"); HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix"); HasVEX_4V = Rec->getValueAsBit("hasVEX_4V"); HasVEX_4VOp3 = Rec->getValueAsBit("hasVEX_4VOp3"); @@ -399,16 +405,20 @@ InstructionContext RecognizableInstr::insnContext() const { errs() << "Instruction does not use a prefix: " << Name << "\n"; llvm_unreachable("Invalid prefix"); } - } else if (Is64Bit || HasREX_WPrefix) { + } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) { if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)) insnContext = IC_64BIT_REXW_OPSIZE; + else if (HasREX_WPrefix && AdSize == X86Local::AdSize32) + insnContext = IC_64BIT_REXW_ADSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD) insnContext = IC_64BIT_XD_OPSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) insnContext = IC_64BIT_XS_OPSIZE; + else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize32) + insnContext = IC_64BIT_OPSIZE_ADSIZE; else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) insnContext = IC_64BIT_OPSIZE; - else if (HasAdSizePrefix) + else if (AdSize == X86Local::AdSize32) insnContext = IC_64BIT_ADSIZE; else if (HasREX_WPrefix && OpPrefix == X86Local::XS) insnContext = IC_64BIT_REXW_XS; @@ -427,9 +437,11 @@ InstructionContext RecognizableInstr::insnContext() const { insnContext = IC_XD_OPSIZE; else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS) insnContext = IC_XS_OPSIZE; + else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize16) + insnContext = IC_OPSIZE_ADSIZE; else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD) insnContext = IC_OPSIZE; - else if (HasAdSizePrefix) + else if (AdSize == X86Local::AdSize16) insnContext = IC_ADSIZE; else if (OpPrefix == X86Local::XD) insnContext = IC_XD; @@ -539,6 +551,14 @@ void RecognizableInstr::emitInstructionSpecifier() { // physicalOperandIndex should always be < numPhysicalOperands unsigned physicalOperandIndex = 0; + // Given the set of prefix bits, how many additional operands does the + // instruction have? + unsigned additionalOperands = 0; + if (HasVEX_4V || HasVEX_4VOp3) + ++additionalOperands; + if (HasEVEX_K) + ++additionalOperands; + switch (Form) { default: llvm_unreachable("Unhandled form"); case X86Local::RawFrmSrc: @@ -573,17 +593,17 @@ void RecognizableInstr::emitInstructionSpecifier() { break; case X86Local::MRMDestReg: // Operand 1 is a register operand in the R/M field. + // - In AVX512 there may be a mask operand here - // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestRegFrm"); HANDLE_OPERAND(rmRegister) + if (HasEVEX_K) + HANDLE_OPERAND(writemaskRegister) if (HasVEX_4V) // FIXME: In AVX, the register below becomes the one encoded @@ -598,12 +618,10 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 2 is a register operand in the Reg/Opcode field. // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMDestMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMDestMemFrm with VEX_4V"); + HANDLE_OPERAND(memory) if (HasEVEX_K) @@ -624,12 +642,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // Operand 3 (optional) is an immediate. // Operand 4 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcRegFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 4 && - "Unexpected number of operands for MRMSrcRegFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcRegFrm"); HANDLE_OPERAND(roRegister) @@ -660,12 +675,9 @@ void RecognizableInstr::emitInstructionSpecifier() { // - In AVX, there is a register operand in the VEX.vvvv field here - // Operand 3 (optional) is an immediate. - if (HasVEX_4V || HasVEX_4VOp3) - assert(numPhysicalOperands >= 3 && numPhysicalOperands <= 5 && - "Unexpected number of operands for MRMSrcMemFrm with VEX_4V"); - else - assert(numPhysicalOperands >= 2 && numPhysicalOperands <= 3 && - "Unexpected number of operands for MRMSrcMemFrm"); + assert(numPhysicalOperands >= 2 + additionalOperands && + numPhysicalOperands <= 4 + additionalOperands && + "Unexpected number of operands for MRMSrcMemFrm"); HANDLE_OPERAND(roRegister) @@ -698,15 +710,13 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5r: case X86Local::MRM6r: case X86Local::MRM7r: - { - // Operand 1 is a register operand in the R/M field. - // Operand 2 (optional) is an immediate or relocation. - // Operand 3 (optional) is an immediate. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands > 3 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnr"); - } + // Operand 1 is a register operand in the R/M field. + // Operand 2 (optional) is an immediate or relocation. + // Operand 3 (optional) is an immediate. + assert(numPhysicalOperands >= 0 + additionalOperands && + numPhysicalOperands <= 3 + additionalOperands && + "Unexpected number of operands for MRMnr"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) @@ -725,15 +735,12 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM5m: case X86Local::MRM6m: case X86Local::MRM7m: - { - // Operand 1 is a memory operand (possibly SIB-extended) - // Operand 2 (optional) is an immediate or relocation. - unsigned kOp = (HasEVEX_K) ? 1:0; - unsigned Op4v = (HasVEX_4V) ? 1:0; - if (numPhysicalOperands < 1 + kOp + Op4v || - numPhysicalOperands > 2 + kOp + Op4v) - llvm_unreachable("Unexpected number of operands for MRMnm"); - } + // Operand 1 is a memory operand (possibly SIB-extended) + // Operand 2 (optional) is an immediate or relocation. + assert(numPhysicalOperands >= 1 + additionalOperands && + numPhysicalOperands <= 2 + additionalOperands && + "Unexpected number of operands for MRMnm"); + if (HasVEX_4V) HANDLE_OPERAND(vvvvRegister) if (HasEVEX_K) @@ -769,20 +776,21 @@ void RecognizableInstr::emitInstructionSpecifier() { case X86Local::MRM_C0: case X86Local::MRM_C1: case X86Local::MRM_C2: case X86Local::MRM_C3: case X86Local::MRM_C4: case X86Local::MRM_C8: case X86Local::MRM_C9: case X86Local::MRM_CA: case X86Local::MRM_CB: - case X86Local::MRM_D0: case X86Local::MRM_D1: case X86Local::MRM_D4: - case X86Local::MRM_D5: case X86Local::MRM_D6: case X86Local::MRM_D8: - case X86Local::MRM_D9: case X86Local::MRM_DA: case X86Local::MRM_DB: - case X86Local::MRM_DC: case X86Local::MRM_DD: case X86Local::MRM_DE: - case X86Local::MRM_DF: case X86Local::MRM_E0: case X86Local::MRM_E1: - case X86Local::MRM_E2: case X86Local::MRM_E3: case X86Local::MRM_E4: - case X86Local::MRM_E5: case X86Local::MRM_E8: case X86Local::MRM_E9: - case X86Local::MRM_EA: case X86Local::MRM_EB: case X86Local::MRM_EC: - case X86Local::MRM_ED: case X86Local::MRM_EE: case X86Local::MRM_F0: - case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3: - case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6: - case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA: - case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD: - case X86Local::MRM_FE: case X86Local::MRM_FF: + case X86Local::MRM_CF: case X86Local::MRM_D0: case X86Local::MRM_D1: + case X86Local::MRM_D4: case X86Local::MRM_D5: case X86Local::MRM_D6: + case X86Local::MRM_D7: case X86Local::MRM_D8: case X86Local::MRM_D9: + case X86Local::MRM_DA: case X86Local::MRM_DB: case X86Local::MRM_DC: + case X86Local::MRM_DD: case X86Local::MRM_DE: case X86Local::MRM_DF: + case X86Local::MRM_E0: case X86Local::MRM_E1: case X86Local::MRM_E2: + case X86Local::MRM_E3: case X86Local::MRM_E4: case X86Local::MRM_E5: + case X86Local::MRM_E8: case X86Local::MRM_E9: case X86Local::MRM_EA: + case X86Local::MRM_EB: case X86Local::MRM_EC: case X86Local::MRM_ED: + case X86Local::MRM_EE: case X86Local::MRM_F0: case X86Local::MRM_F1: + case X86Local::MRM_F2: case X86Local::MRM_F3: case X86Local::MRM_F4: + case X86Local::MRM_F5: case X86Local::MRM_F6: case X86Local::MRM_F7: + case X86Local::MRM_F9: case X86Local::MRM_FA: case X86Local::MRM_FB: + case X86Local::MRM_FC: case X86Local::MRM_FD: case X86Local::MRM_FE: + case X86Local::MRM_FF: // Ignored. break; } @@ -852,6 +860,13 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { break; } // switch (OpMap) + unsigned AddressSize = 0; + switch (AdSize) { + case X86Local::AdSize16: AddressSize = 16; break; + case X86Local::AdSize32: AddressSize = 32; break; + case X86Local::AdSize64: AddressSize = 64; break; + } + assert(opcodeType != (OpcodeType)-1 && "Opcode type not set"); assert(filter && "Filter not set"); @@ -869,13 +884,13 @@ void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const { insnContext(), currentOpcode, *filter, - UID, Is32Bit, IgnoresVEX_L); + UID, Is32Bit, IgnoresVEX_L, AddressSize); } else { tables.setTableFields(opcodeType, insnContext(), opcodeToSet, *filter, - UID, Is32Bit, IgnoresVEX_L); + UID, Is32Bit, IgnoresVEX_L, AddressSize); } delete filter; @@ -909,7 +924,6 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("i32mem", TYPE_Mv) TYPE("i32imm", TYPE_IMMv) TYPE("i32i8imm", TYPE_IMM32) - TYPE("u32u8imm", TYPE_IMM32) TYPE("GR32", TYPE_R32) TYPE("GR32orGR64", TYPE_R32) TYPE("i64mem", TYPE_Mv) @@ -942,15 +956,15 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("SSECC", TYPE_IMM3) TYPE("AVXCC", TYPE_IMM5) TYPE("AVX512RC", TYPE_IMM32) - TYPE("brtarget", TYPE_RELv) - TYPE("uncondbrtarget", TYPE_RELv) + TYPE("brtarget32", TYPE_RELv) + TYPE("brtarget16", TYPE_RELv) TYPE("brtarget8", TYPE_REL8) TYPE("f80mem", TYPE_M80FP) - TYPE("lea32mem", TYPE_LEA) TYPE("lea64_32mem", TYPE_LEA) TYPE("lea64mem", TYPE_LEA) TYPE("VR64", TYPE_MM64) TYPE("i64imm", TYPE_IMMv) + TYPE("anymem", TYPE_M) TYPE("opaque32mem", TYPE_M1616) TYPE("opaque48mem", TYPE_M1632) TYPE("opaque80mem", TYPE_M1664) @@ -966,10 +980,17 @@ OperandType RecognizableInstr::typeFromString(const std::string &s, TYPE("dstidx16", TYPE_DSTIDX16) TYPE("dstidx32", TYPE_DSTIDX32) TYPE("dstidx64", TYPE_DSTIDX64) - TYPE("offset8", TYPE_MOFFS8) - TYPE("offset16", TYPE_MOFFS16) - TYPE("offset32", TYPE_MOFFS32) - TYPE("offset64", TYPE_MOFFS64) + TYPE("offset16_8", TYPE_MOFFS8) + TYPE("offset16_16", TYPE_MOFFS16) + TYPE("offset16_32", TYPE_MOFFS32) + TYPE("offset32_8", TYPE_MOFFS8) + TYPE("offset32_16", TYPE_MOFFS16) + TYPE("offset32_32", TYPE_MOFFS32) + TYPE("offset32_64", TYPE_MOFFS64) + TYPE("offset64_8", TYPE_MOFFS8) + TYPE("offset64_16", TYPE_MOFFS16) + TYPE("offset64_32", TYPE_MOFFS32) + TYPE("offset64_64", TYPE_MOFFS64) TYPE("VR256", TYPE_XMM256) TYPE("VR256X", TYPE_XMM256) TYPE("VR512", TYPE_XMM512) @@ -1012,7 +1033,6 @@ RecognizableInstr::immediateEncodingFromString(const std::string &s, ENCODING("i16imm", ENCODING_IW) } ENCODING("i32i8imm", ENCODING_IB) - ENCODING("u32u8imm", ENCODING_IB) ENCODING("SSECC", ENCODING_IB) ENCODING("AVXCC", ENCODING_IB) ENCODING("AVX512RC", ENCODING_IB) @@ -1059,6 +1079,8 @@ RecognizableInstr::rmRegisterEncodingFromString(const std::string &s, ENCODING("VK1", ENCODING_RM) ENCODING("VK8", ENCODING_RM) ENCODING("VK16", ENCODING_RM) + ENCODING("VK32", ENCODING_RM) + ENCODING("VK64", ENCODING_RM) errs() << "Unhandled R/M register encoding " << s << "\n"; llvm_unreachable("Unhandled R/M register encoding"); } @@ -1085,8 +1107,12 @@ RecognizableInstr::roRegisterEncodingFromString(const std::string &s, ENCODING("FR32X", ENCODING_REG) ENCODING("VR512", ENCODING_REG) ENCODING("VK1", ENCODING_REG) + ENCODING("VK2", ENCODING_REG) + ENCODING("VK4", ENCODING_REG) ENCODING("VK8", ENCODING_REG) ENCODING("VK16", ENCODING_REG) + ENCODING("VK32", ENCODING_REG) + ENCODING("VK64", ENCODING_REG) ENCODING("VK1WM", ENCODING_REG) ENCODING("VK8WM", ENCODING_REG) ENCODING("VK16WM", ENCODING_REG) @@ -1113,6 +1139,8 @@ RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s, ENCODING("VK4", ENCODING_VVVV) ENCODING("VK8", ENCODING_VVVV) ENCODING("VK16", ENCODING_VVVV) + ENCODING("VK32", ENCODING_VVVV) + ENCODING("VK64", ENCODING_VVVV) errs() << "Unhandled VEX.vvvv register encoding " << s << "\n"; llvm_unreachable("Unhandled VEX.vvvv register encoding"); } @@ -1149,9 +1177,9 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s, ENCODING("i256mem", ENCODING_RM) ENCODING("i512mem", ENCODING_RM) ENCODING("f80mem", ENCODING_RM) - ENCODING("lea32mem", ENCODING_RM) ENCODING("lea64_32mem", ENCODING_RM) ENCODING("lea64mem", ENCODING_RM) + ENCODING("anymem", ENCODING_RM) ENCODING("opaque32mem", ENCODING_RM) ENCODING("opaque48mem", ENCODING_RM) ENCODING("opaque80mem", ENCODING_RM) @@ -1185,13 +1213,21 @@ RecognizableInstr::relocationEncodingFromString(const std::string &s, ENCODING("i64i32imm_pcrel", ENCODING_ID) ENCODING("i16imm_pcrel", ENCODING_IW) ENCODING("i32imm_pcrel", ENCODING_ID) - ENCODING("brtarget", ENCODING_Iv) + ENCODING("brtarget32", ENCODING_Iv) + ENCODING("brtarget16", ENCODING_Iv) ENCODING("brtarget8", ENCODING_IB) ENCODING("i64imm", ENCODING_IO) - ENCODING("offset8", ENCODING_Ia) - ENCODING("offset16", ENCODING_Ia) - ENCODING("offset32", ENCODING_Ia) - ENCODING("offset64", ENCODING_Ia) + ENCODING("offset16_8", ENCODING_Ia) + ENCODING("offset16_16", ENCODING_Ia) + ENCODING("offset16_32", ENCODING_Ia) + ENCODING("offset32_8", ENCODING_Ia) + ENCODING("offset32_16", ENCODING_Ia) + ENCODING("offset32_32", ENCODING_Ia) + ENCODING("offset32_64", ENCODING_Ia) + ENCODING("offset64_8", ENCODING_Ia) + ENCODING("offset64_16", ENCODING_Ia) + ENCODING("offset64_32", ENCODING_Ia) + ENCODING("offset64_64", ENCODING_Ia) ENCODING("srcidx8", ENCODING_SI) ENCODING("srcidx16", ENCODING_SI) ENCODING("srcidx32", ENCODING_SI) diff --git a/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h index 4bc52eb..28e1053 100644 --- a/utils/TableGen/X86RecognizableInstr.h +++ b/utils/TableGen/X86RecognizableInstr.h @@ -14,8 +14,8 @@ // //===----------------------------------------------------------------------===// -#ifndef X86RECOGNIZABLEINSTR_H -#define X86RECOGNIZABLEINSTR_H +#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H +#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H #include "CodeGenTarget.h" #include "X86DisassemblerTables.h" @@ -50,8 +50,8 @@ private: uint8_t Encoding; /// The OpSize field from the record uint8_t OpSize; - /// The hasAdSizePrefix field from the record - bool HasAdSizePrefix; + /// The AdSize field from the record + uint8_t AdSize; /// The hasREX_WPrefix field from the record bool HasREX_WPrefix; /// The hasVEX_4V field from the record diff --git a/utils/bisect b/utils/bisect new file mode 100755 index 0000000..d1b1257 --- /dev/null +++ b/utils/bisect @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import os +import sys +import argparse +import subprocess + +parser = argparse.ArgumentParser() + +parser.add_argument('--start', type=int, default=0) +parser.add_argument('--end', type=int, default=(1 << 32)) +parser.add_argument('command', nargs='+') + +args = parser.parse_args() + +start = args.start +end = args.end + +print("Bisect Starting!") +print("Start: %d" % start) +print("End: %d" % end) + +last = None +while start != end and start != end-1: + count = start + (end - start)/2 + print("Visiting Count: %d with (Start, End) = (%d,%d)" % (count, start, end)) + cmd = [x % {'count':count} for x in args.command] + print cmd + result = subprocess.call(cmd) + if result == 0: + print(" PASSES! Setting start to count") + start = count + else: + print(" FAILS! Setting end to count") + end = count + +print("Last good count: %d" % start) diff --git a/utils/emacs/emacs.el b/utils/emacs/emacs.el index 969f538..2ebc3c6 100644 --- a/utils/emacs/emacs.el +++ b/utils/emacs/emacs.el @@ -1,25 +1,20 @@ ;; LLVM coding style guidelines in emacs ;; Maintainer: LLVM Team, http://llvm.org/ -;; Modified: 2009-07-28 -;; Max 80 cols per line, indent by two spaces, no tabs. -;; Apparently, this does not affect tabs in Makefiles. -(custom-set-variables - '(fill-column 80) - '(c++-indent-level 2) - '(c-basic-offset 2) - '(indent-tabs-mode nil)) - - -;; Alternative to setting the global style. Only files with "llvm" in -;; their names will automatically set to the llvm.org coding style. +;; Add a cc-mode style for editing LLVM C++ code (c-add-style "llvm.org" '((fill-column . 80) (c++-indent-level . 2) (c-basic-offset . 2) (indent-tabs-mode . nil) - (c-offsets-alist . ((innamespace 0))))) + (c-offsets-alist . ((arglist-intro . ++) + (innamespace . 0) + (member-init-intro . ++) + )) + )) +;; Files with "llvm" in their names will automatically be set to the +;; llvm.org coding style. (add-hook 'c-mode-hook (function (lambda nil diff --git a/utils/emacs/llvm-mode.el b/utils/emacs/llvm-mode.el index 99d3294..6d8395c 100644 --- a/utils/emacs/llvm-mode.el +++ b/utils/emacs/llvm-mode.el @@ -1,8 +1,13 @@ +;;; llvm-mode.el --- Major mode for the LLVM assembler language. + ;; Maintainer: The LLVM team, http://llvm.org/ -;; Description: Major mode for the LLVM assembler language. -;; Updated: 2007-09-19 -;; Create mode-specific tables. +;;; Commentary: + +;; Major mode for editing LLVM IR files. + +;;; Code: + (defvar llvm-mode-syntax-table nil "Syntax table used while in LLVM mode.") (defvar llvm-font-lock-keywords @@ -48,9 +53,13 @@ `(,(regexp-opt '("extractelement" "insertelement" "shufflevector") 'words) . font-lock-keyword-face) ;; Aggregate ops `(,(regexp-opt '("extractvalue" "insertvalue") 'words) . font-lock-keyword-face) + ;; Metadata types + `(,(regexp-opt '("distinct") 'words) . font-lock-keyword-face) + ;; Use-list order directives + `(,(regexp-opt '("uselistorder" "uselistorder_bb") 'words) . font-lock-keyword-face) ) - "Syntax highlighting for LLVM" + "Syntax highlighting for LLVM." ) ;; ---------------------- Syntax table --------------------------- @@ -60,40 +69,40 @@ (if (not llvm-mode-syntax-table) (progn (setq llvm-mode-syntax-table (make-syntax-table)) - (mapcar (function (lambda (n) - (modify-syntax-entry (aref n 0) - (aref n 1) - llvm-mode-syntax-table))) - '( - ;; whitespace (` ') - [?\^m " "] - [?\f " "] - [?\n " "] - [?\t " "] - [?\ " "] - ;; word constituents (`w') - ;;[?< "w"] - ;;[?> "w"] - [?\% "w"] - ;;[?_ "w "] - ;; comments - [?\; "< "] - [?\n "> "] - ;;[?\r "> "] - ;;[?\^m "> "] - ;; symbol constituents (`_') - ;; punctuation (`.') - ;; open paren (`(') - [?\( "("] - [?\[ "("] - [?\{ "("] - ;; close paren (`)') - [?\) ")"] - [?\] ")"] - [?\} ")"] - ;; string quote ('"') - [?\" "\""] - )))) + (mapc (function (lambda (n) + (modify-syntax-entry (aref n 0) + (aref n 1) + llvm-mode-syntax-table))) + '( + ;; whitespace (` ') + [?\^m " "] + [?\f " "] + [?\n " "] + [?\t " "] + [?\ " "] + ;; word constituents (`w') + ;;[?< "w"] + ;;[?> "w"] + [?\% "w"] + ;;[?_ "w "] + ;; comments + [?\; "< "] + [?\n "> "] + ;;[?\r "> "] + ;;[?\^m "> "] + ;; symbol constituents (`_') + ;; punctuation (`.') + ;; open paren (`(') + [?\( "("] + [?\[ "("] + [?\{ "("] + ;; close paren (`)') + [?\) ")"] + [?\] ")"] + [?\} ")"] + ;; string quote ('"') + [?\" "\""] + )))) ;; --------------------- Abbrev table ----------------------------- @@ -111,11 +120,11 @@ (define-key llvm-mode-map "\es" 'center-line) (define-key llvm-mode-map "\eS" 'center-paragraph)) - +;;;###autoload (defun llvm-mode () "Major mode for editing LLVM source files. - \\{llvm-mode-map} - Runs llvm-mode-hook on startup." +\\{llvm-mode-map} + Runs `llvm-mode-hook' on startup." (interactive) (kill-all-local-variables) (use-local-map llvm-mode-map) ; Provides the local keymap. @@ -134,8 +143,9 @@ ; customize the mode with a hook. ;; Associate .ll files with llvm-mode -(setq auto-mode-alist - (append '(("\\.ll$" . llvm-mode)) auto-mode-alist)) +;;;###autoload +(add-to-list 'auto-mode-alist (cons (purecopy "\\.ll\\'") 'llvm-mode)) (provide 'llvm-mode) -;; end of llvm-mode.el + +;;; llvm-mode.el ends here diff --git a/utils/emacs/tablegen-mode.el b/utils/emacs/tablegen-mode.el index c0ae751..035455d 100644 --- a/utils/emacs/tablegen-mode.el +++ b/utils/emacs/tablegen-mode.el @@ -1,12 +1,17 @@ +;;; tablegen-mode.el --- Major mode for TableGen description files (part of LLVM project) + ;; Maintainer: The LLVM team, http://llvm.org/ -;; Description: Major mode for TableGen description files (part of LLVM project) -;; Updated: 2007-12-18 + +;;; Commentary: +;; A major mode for TableGen description files in LLVM. (require 'comint) (require 'custom) (require 'ansi-color) ;; Create mode-specific tables. +;;; Code: + (defvar td-decorators-face 'td-decorators-face "Face method decorators.") (make-face 'td-decorators-face) @@ -93,10 +98,11 @@ (define-key tablegen-mode-map "\es" 'center-line) (define-key tablegen-mode-map "\eS" 'center-paragraph)) +;;;###autoload (defun tablegen-mode () "Major mode for editing TableGen description files. - \\{tablegen-mode-map} - Runs tablegen-mode-hook on startup." +\\{tablegen-mode-map} + Runs `tablegen-mode-hook' on startup." (interactive) (kill-all-local-variables) (use-local-map tablegen-mode-map) ; Provides the local keymap. @@ -117,7 +123,9 @@ ; customize the mode with a hook. ;; Associate .td files with tablegen-mode -(setq auto-mode-alist (append '(("\\.td$" . tablegen-mode)) auto-mode-alist)) +;;;###autoload +(add-to-list 'auto-mode-alist (cons (purecopy "\\.td\\'") 'tablegen-mode)) (provide 'tablegen-mode) -;; end of tablegen-mode.el + +;;; tablegen-mode.el ends here diff --git a/utils/findmisopt b/utils/findmisopt index 88f991a..2405220 100755 --- a/utils/findmisopt +++ b/utils/findmisopt @@ -74,8 +74,8 @@ echo "Unoptimized program: $prog" echo " Optimized program: $optprog" # Define the list of optimizations to run. This comprises the same set of -# optimizations that opt -std-compile-opts and gccld run, in the same order. -opt_switches=`llvm-as < /dev/null -o - | opt -std-compile-opts -disable-output -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'` +# optimizations that opt -O3 runs, in the same order. +opt_switches=`llvm-as < /dev/null -o - | opt -O3 -disable-output -debug-pass=Arguments 2>&1 | sed 's/Pass Arguments: //'` all_switches="$opt_switches" echo "Passes : $all_switches" diff --git a/utils/git-svn/git-svnrevert b/utils/git-svn/git-svnrevert index 06a9c44..f15e7ab 100755 --- a/utils/git-svn/git-svnrevert +++ b/utils/git-svn/git-svnrevert @@ -2,7 +2,7 @@ if [ $# -ne 1 ]; then echo "Invalid arguments!" - echo "$0 " + echo "$0 " exit 1 fi @@ -13,20 +13,27 @@ if [ -n "$(git status -uno -s --porcelain)" ]; then fi COMMIT=$1 - -SVN_REVISION=$(git svn find-rev "$COMMIT") +OTHER=$(git svn find-rev "$COMMIT") if [ $? -ne 0 ]; then - echo "Error! Could not find an svn revision for commit $COMMIT!" + echo "Error! Could not find an svn/git revision for commit $COMMIT!" exit 1 fi +if [ -n "$(echo $COMMIT | grep '^r[0-9]\+')" ]; then + SVN=`echo $COMMIT | sed -e 's/^r//'` + GIT=$OTHER +else + SVN=$OTHER + GIT=$COMMIT +fi + # Grab the one line message for our revert commit message. -ONE_LINE_MSG=$(git log --oneline $COMMIT -1 | cut -f2- -d " ") +ONE_LINE_MSG=$(git log --oneline $GIT -1 | cut -f2- -d " ") # Revert the commit. -git revert --no-commit $COMMIT 2>/dev/null +git revert --no-commit $GIT 2>/dev/null if [ $? -ne 0 ]; then - echo "Error! Failed to revert commit $COMMIT. Resetting to head." + echo "Error! Failed to revert commit r$SVN. Resetting to head." git reset --hard HEAD exit 1 fi @@ -36,13 +43,13 @@ TEMPLATE="`git rev-parse --git-dir`/git-svn-revert-template" cat > $TEMPLATE <". @@ -147,7 +147,7 @@ class TerminalController: if cap is None: cap = '' else: - cap = cap.decode('ascii') + cap = cap.decode('utf-8') return re.sub(r'\$<\d+>[/*]?', '', cap) def render(self, template): diff --git a/utils/lit/lit/Test.py b/utils/lit/lit/Test.py index 2e0f478..b810230 100644 --- a/utils/lit/lit/Test.py +++ b/utils/lit/lit/Test.py @@ -1,5 +1,6 @@ import os from xml.sax.saxutils import escape +from json import JSONEncoder # Test result codes. @@ -73,6 +74,41 @@ class RealMetricValue(MetricValue): def todata(self): return self.value +class JSONMetricValue(MetricValue): + """ + JSONMetricValue is used for types that are representable in the output + but that are otherwise uninterpreted. + """ + def __init__(self, value): + # Ensure the value is a serializable by trying to encode it. + # WARNING: The value may change before it is encoded again, and may + # not be encodable after the change. + try: + e = JSONEncoder() + e.encode(value) + except TypeError: + raise + self.value = value + + def format(self): + return str(self.value) + + def todata(self): + return self.value + +def toMetricValue(value): + if isinstance(value, MetricValue): + return value + elif isinstance(value, int) or isinstance(value, long): + return IntMetricValue(value) + elif isinstance(value, float): + return RealMetricValue(value) + else: + # Try to create a JSONMetricValue and let the constructor throw + # if value is not a valid type. + return JSONMetricValue(value) + + # Test results. class Result(object): @@ -200,12 +236,20 @@ class Test: def getJUnitXML(self): test_name = self.path_in_suite[-1] test_path = self.path_in_suite[:-1] - - xml = "\n") xunit_output_file.write("\n") for suite_name, suite in by_suite.items(): - xunit_output_file.write(" %t.out # RUN: FileCheck < %t.results.out %s diff --git a/utils/lit/tests/xunit-output.py b/utils/lit/tests/xunit-output.py new file mode 100644 index 0000000..8765229 --- /dev/null +++ b/utils/lit/tests/xunit-output.py @@ -0,0 +1,10 @@ +# Check xunit output +# RUN: %{lit} --xunit-xml-output %t.xunit.xml %{inputs}/test-data +# RUN: FileCheck < %t.xunit.xml %s + +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: \ No newline at end of file diff --git a/utils/lldbDataFormatters.py b/utils/lldbDataFormatters.py index 352448d..f570fb4 100644 --- a/utils/lldbDataFormatters.py +++ b/utils/lldbDataFormatters.py @@ -12,6 +12,9 @@ def __lldb_init_module(debugger, internal_dict): debugger.HandleCommand('type synthetic add -w llvm ' '-l lldbDataFormatters.SmallVectorSynthProvider ' '-x "^llvm::SmallVector<.+,.+>$"') + debugger.HandleCommand('type synthetic add -w llvm ' + '-l lldbDataFormatters.ArrayRefSynthProvider ' + '-x "^llvm::ArrayRef<.+>$"') # Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl class SmallVectorSynthProvider: @@ -53,3 +56,33 @@ class SmallVectorSynthProvider: self.data_type = the_type.GetTemplateArgumentType(0) self.type_size = self.data_type.GetByteSize() assert self.type_size != 0 + +class ArrayRefSynthProvider: + """ Provider for llvm::ArrayRef """ + def __init__(self, valobj, dict): + self.valobj = valobj; + self.update() # initialize this provider + + def num_children(self): + return self.length + + def get_child_index(self, name): + try: + return int(name.lstrip('[').rstrip(']')) + except: + return -1; + + def get_child_at_index(self, index): + if index < 0 or index >= self.num_children(): + return None; + offset = index * self.type_size + return self.data.CreateChildAtOffset('[' + str(index) + ']', + offset, self.data_type) + + def update(self): + self.data = self.valobj.GetChildMemberWithName('Data') + length_obj = self.valobj.GetChildMemberWithName('Length') + self.length = length_obj.GetValueAsUnsigned(0) + self.data_type = self.data.GetType().GetPointeeType() + self.type_size = self.data_type.GetByteSize() + assert self.type_size != 0 diff --git a/utils/llvm-build/llvmbuild/main.py b/utils/llvm-build/llvmbuild/main.py index 37aa5d8..353741f 100644 --- a/utils/llvm-build/llvmbuild/main.py +++ b/utils/llvm-build/llvmbuild/main.py @@ -1,4 +1,5 @@ from __future__ import absolute_import +import filecmp import os import sys @@ -41,7 +42,7 @@ def mk_quote_string_for_target(value): """ mk_quote_string_for_target(target_name) -> str - Return a quoted form of the given target_name suitable for including in a + Return a quoted form of the given target_name suitable for including in a Makefile as a target name. """ @@ -340,7 +341,7 @@ subdirectories = %s # Compute the llvm-config "component name". For historical reasons, # this is lowercased based on the library name. llvmconfig_component_name = c.get_llvmconfig_component_name() - + # Get the library name, or None for LibraryGroups. if c.type_name == 'Library' or c.type_name == 'OptionalLibrary': library_name = c.get_prefixed_library_name() @@ -382,7 +383,7 @@ subdirectories = %s # Write out the library table. make_install_dir(os.path.dirname(output_path)) - f = open(output_path, 'w') + f = open(output_path+'.new', 'w') f.write("""\ //===- llvm-build generated file --------------------------------*- C++ -*-===// // @@ -420,6 +421,14 @@ subdirectories = %s f.write('};\n') f.close() + if not os.path.isfile(output_path): + os.rename(output_path+'.new', output_path) + elif filecmp.cmp(output_path, output_path+'.new'): + os.remove(output_path+'.new') + else: + os.remove(output_path) + os.rename(output_path+'.new', output_path) + def get_required_libraries_for_component(self, ci, traverse_groups = False): """ get_required_libraries_for_component(component_info) -> iter @@ -430,14 +439,14 @@ subdirectories = %s traversed to include their required libraries. """ - assert ci.type_name in ('Library', 'LibraryGroup', 'TargetGroup') + assert ci.type_name in ('Library', 'OptionalLibrary', 'LibraryGroup', 'TargetGroup') for name in ci.required_libraries: # Get the dependency info. dep = self.component_info_map[name] # If it is a library, yield it. - if dep.type_name == 'Library': + if dep.type_name == 'Library' or dep.type_name == 'OptionalLibrary': yield dep continue @@ -492,7 +501,7 @@ subdirectories = %s if (path.startswith(self.source_root) and os.path.exists(path)): yield path - def write_cmake_fragment(self, output_path): + def write_cmake_fragment(self, output_path, enabled_optional_components): """ write_cmake_fragment(output_path) -> None @@ -561,8 +570,13 @@ configure_file(\"%s\" # names to required libraries, in a way that is easily accessed from CMake. """) for ci in self.ordered_component_infos: - # We only write the information for libraries currently. - if ci.type_name != 'Library': + # Skip optional components which are not enabled. + if ci.type_name == 'OptionalLibrary' \ + and ci.name not in enabled_optional_components: + continue + + # We only write the information for certain components currently. + if ci.type_name not in ('Library', 'OptionalLibrary'): continue f.write("""\ @@ -573,7 +587,7 @@ set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)\n""" % ( f.close() - def write_cmake_exports_fragment(self, output_path): + def write_cmake_exports_fragment(self, output_path, enabled_optional_components): """ write_cmake_exports_fragment(output_path) -> None @@ -595,8 +609,13 @@ set_property(GLOBAL PROPERTY LLVMBUILD_LIB_DEPS_%s %s)\n""" % ( # dependencies of libraries imported from LLVM. """) for ci in self.ordered_component_infos: + # Skip optional components which are not enabled. + if ci.type_name == 'OptionalLibrary' \ + and ci.name not in enabled_optional_components: + continue + # We only write the information for libraries currently. - if ci.type_name != 'Library': + if ci.type_name not in ('Library', 'OptionalLibrary'): continue # Skip disabled targets. @@ -783,7 +802,7 @@ def add_magic_target_components(parser, project, opts): # If we have a native target with a JIT, use that for the engine. Otherwise, # use the interpreter. if native_target and native_target.enabled and native_target.has_jit: - engine_group.required_libraries.append('JIT') + engine_group.required_libraries.append('MCJIT') engine_group.required_libraries.append(native_group.name) else: engine_group.required_libraries.append('Interpreter') @@ -905,9 +924,11 @@ given by --build-root) at the same SUBPATH""", # Write out the cmake fragment, if requested. if opts.write_cmake_fragment: - project_info.write_cmake_fragment(opts.write_cmake_fragment) + project_info.write_cmake_fragment(opts.write_cmake_fragment, + opts.optional_components) if opts.write_cmake_exports_fragment: - project_info.write_cmake_exports_fragment(opts.write_cmake_exports_fragment) + project_info.write_cmake_exports_fragment(opts.write_cmake_exports_fragment, + opts.optional_components) # Configure target definition files, if requested. if opts.configure_target_def_files: diff --git a/utils/not/not.cpp b/utils/not/not.cpp index a5c7183..23062fb 100644 --- a/utils/not/not.cpp +++ b/utils/not/not.cpp @@ -6,6 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// Usage: +// not cmd +// Will return true if cmd doesn't crash and returns false. +// not --crash cmd +// Will return true if cmd crashes (e.g. for testing crash reporting). #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" @@ -27,10 +32,15 @@ int main(int argc, const char **argv) { if (argc == 0) return 1; - std::string Program = sys::FindProgramByName(argv[0]); + auto Program = sys::findProgramByName(argv[0]); + if (!Program) { + errs() << "Error: Unable to find `" << argv[0] + << "' in PATH: " << Program.getError().message() << "\n"; + return 1; + } std::string ErrMsg; - int Result = sys::ExecuteAndWait(Program, argv, nullptr, nullptr, 0, 0, + int Result = sys::ExecuteAndWait(*Program, argv, nullptr, nullptr, 0, 0, &ErrMsg); #ifdef _WIN32 // Handle abort() in msvcrt -- It has exit code as 3. abort(), aka diff --git a/utils/release/export.sh b/utils/release/export.sh index f25a193..38e5a81 100755 --- a/utils/release/export.sh +++ b/utils/release/export.sh @@ -14,7 +14,7 @@ set -e -projects="llvm cfe dragonegg test-suite compiler-rt libcxx clang-tools-extra polly lldb" +projects="llvm cfe dragonegg test-suite compiler-rt libcxx libcxxabi clang-tools-extra polly lldb lld openmp" base_url="https://llvm.org/svn/llvm-project" release="" @@ -44,7 +44,7 @@ function export_sources() { $proj-$release$rc.src echo "Creating tarball ..." - tar cfz $proj-$release$rc.src.tar.gz $proj-$release$rc.src + tar cfJ $proj-$release$rc.src.tar.xz $proj-$release$rc.src done } diff --git a/utils/release/merge.sh b/utils/release/merge.sh index 2cf39b2..949c298 100755 --- a/utils/release/merge.sh +++ b/utils/release/merge.sh @@ -66,9 +66,11 @@ svn log -c $rev http://llvm.org/svn/llvm-project/$proj/trunk >> $tempfile 2>&1 cd $proj.src echo "# Updating tree" svn up -echo "# Merging r$rev into $proj" +echo "# Merging r$rev into $proj locally" svn merge -c $rev https://llvm.org/svn/llvm-project/$proj/trunk . || exit 1 -echo "# Committing changes" -svn commit -F $tempfile || exit 1 -rm -f $tempfile + +echo +echo "# To commit the merge, run the following in $proj.src/:" +echo svn commit -F $tempfile + exit 0 diff --git a/utils/release/tag.sh b/utils/release/tag.sh index 6c5039d..2dfba04 100755 --- a/utils/release/tag.sh +++ b/utils/release/tag.sh @@ -17,33 +17,38 @@ set -e release="" rc="" rebranch="no" -projects="llvm cfe dragonegg test-suite compiler-rt libcxx clang-tools-extra polly lldb lld" +projects="llvm cfe dragonegg test-suite compiler-rt libcxx libcxxabi clang-tools-extra polly lldb lld openmp" +dryrun="" +revision="HEAD" base_url="https://llvm.org/svn/llvm-project" function usage() { - echo "usage: `basename $0` -release [-rebranch]" - echo "usage: `basename $0` -release -rc " + echo "usage: `basename $0` -release [-rebranch] [-revision ] [-dry-run]" + echo "usage: `basename $0` -release -rc [-dry-run]" echo " " - echo " -release The version number of the release" - echo " -rc The release candidate number" - echo " -rebranch Remove existing branch, if present, before branching" - echo " -final Tag final release candidate" + echo " -release The version number of the release" + echo " -rc The release candidate number" + echo " -rebranch Remove existing branch, if present, before branching" + echo " -final Tag final release candidate" + echo " -revision Revision to branch off (default: HEAD)" + echo " -dry-run Make no changes to the repository, just print the commands" } function tag_version() { set -x for proj in $projects; do - if svn ls $base_url/$proj/branches/release_$release > /dev/null 2>&1 ; then + if svn ls $base_url/$proj/branches/release_$branch_release > /dev/null 2>&1 ; then if [ $rebranch = "no" ]; then continue fi - svn remove -m "Removing old release_$release branch for rebranching." \ - $base_url/$proj/branches/release_$release + ${dryrun} svn remove -m "Removing old release_$branch_release branch for rebranching." \ + $base_url/$proj/branches/release_$branch_release fi - svn copy -m "Creating release_$release branch" \ + ${dryrun} svn copy -m "Creating release_$branch_release branch off revision ${revision}" \ + -r ${revision} \ $base_url/$proj/trunk \ - $base_url/$proj/branches/release_$release + $base_url/$proj/branches/release_$branch_release done set +x } @@ -51,13 +56,13 @@ function tag_version() { function tag_release_candidate() { set -x for proj in $projects ; do - if ! svn ls $base_url/$proj/tags/RELEASE_$release > /dev/null 2>&1 ; then - svn mkdir -m "Creating release directory for release_$release." $base_url/$proj/tags/RELEASE_$release + if ! svn ls $base_url/$proj/tags/RELEASE_$tag_release > /dev/null 2>&1 ; then + ${dryrun} svn mkdir -m "Creating release directory for release_$tag_release." $base_url/$proj/tags/RELEASE_$tag_release fi - if ! svn ls $base_url/$proj/tags/RELEASE_$release/$rc > /dev/null 2>&1 ; then - svn copy -m "Creating release candidate $rc from release_$release branch" \ - $base_url/$proj/branches/release_$release \ - $base_url/$proj/tags/RELEASE_$release/$rc + if ! svn ls $base_url/$proj/tags/RELEASE_$tag_release/$rc > /dev/null 2>&1 ; then + ${dryrun} svn copy -m "Creating release candidate $rc from release_$tag_release branch" \ + $base_url/$proj/branches/release_$branch_release \ + $base_url/$proj/tags/RELEASE_$tag_release/$rc fi done set +x @@ -79,6 +84,13 @@ while [ $# -gt 0 ]; do -final | --final ) rc="final" ;; + -revision | --revision ) + shift + revision="$1" + ;; + -dry-run | --dry-run ) + dryrun="echo" + ;; -h | --help | -help ) usage exit 0 @@ -99,11 +111,19 @@ if [ "x$release" = "x" ]; then exit 1 fi -release=`echo $release | sed -e 's,\.,,g'` +branch_release=`echo $release | sed -e 's,\([0-9]*\.[0-9]*\).*,\1,' | sed -e 's,\.,,g'` +tag_release=`echo $release | sed -e 's,\.,,g'` if [ "x$rc" = "x" ]; then tag_version else + if [ "x$revision" != "x" ]; then + echo "error: cannot use -revision with -rc" + echo + usage + exit 1 + fi + tag_release_candidate fi diff --git a/utils/release/test-release.sh b/utils/release/test-release.sh index 83d3e52..20f8d97 100755 --- a/utils/release/test-release.sh +++ b/utils/release/test-release.sh @@ -18,7 +18,7 @@ else MAKE=make fi -projects="llvm cfe dragonegg compiler-rt libcxx test-suite clang-tools-extra" +projects="llvm cfe dragonegg compiler-rt libcxx libcxxabi test-suite clang-tools-extra" # Base SVN URL for the sources. Base_url="http://llvm.org/svn/llvm-project" @@ -39,27 +39,30 @@ do_debug="no" do_asserts="no" do_compare="yes" BuildDir="`pwd`" +BuildTriple="" function usage() { echo "usage: `basename $0` -release X.Y -rc NUM [OPTIONS]" echo "" - echo " -release X.Y The release number to test." - echo " -rc NUM The pre-release candidate number." - echo " -final The final release candidate." - echo " -triple TRIPLE The target triple for this machine." - echo " -j NUM Number of compile jobs to run. [default: 3]" - echo " -build-dir DIR Directory to perform testing in. [default: pwd]" - echo " -no-checkout Don't checkout the sources from SVN." - echo " -no-64bit Don't test the 64-bit version. [default: yes]" - echo " -enable-ada Build Ada. [default: disable]" - echo " -disable-clang Do not test clang. [default: enable]" - echo " -enable-dragonegg Test dragonegg. [default: disable]" - echo " -enable-fortran Enable Fortran build. [default: disable]" - echo " -disable-objc Disable ObjC build. [default: enable]" - echo " -test-debug Test the debug build. [default: no]" - echo " -test-asserts Test with asserts on. [default: no]" - echo " -no-compare-files Don't test that phase 2 and 3 files are identical." - echo " -use-gzip Use gzip instead of xz." + echo " -release X.Y The release number to test." + echo " -rc NUM The pre-release candidate number." + echo " -final The final release candidate." + echo " -triple TRIPLE The target triple for this machine." + echo " -j NUM Number of compile jobs to run. [default: 3]" + echo " -build-dir DIR Directory to perform testing in. [default: pwd]" + echo " -no-checkout Don't checkout the sources from SVN." + echo " -no-64bit Don't test the 64-bit version. [default: yes]" + echo " -enable-ada Build Ada. [default: disable]" + echo " -disable-clang Do not test clang. [default: enable]" + echo " -enable-dragonegg Test dragonegg. [default: disable]" + echo " -enable-fortran Enable Fortran build. [default: disable]" + echo " -disable-objc Disable ObjC build. [default: enable]" + echo " -test-debug Test the debug build. [default: no]" + echo " -test-asserts Test with asserts on. [default: no]" + echo " -no-compare-files Don't test that phase 2 and 3 files are identical." + echo " -use-gzip Use gzip instead of xz." + echo " -build-triple TRIPLE The build triple for this machine" + echo " [default: use config.guess]" } while [ $# -gt 0 ]; do @@ -80,6 +83,10 @@ while [ $# -gt 0 ]; do shift Triple="$1" ;; + -build-triple | --build-triple ) + shift + BuildTriple="$1" + ;; -j* ) NumJobs="`echo $1 | sed -e 's,-j\([0-9]*\),\1,g'`" if [ -z "$NumJobs" ]; then @@ -260,6 +267,9 @@ function export_sources() { if [ ! -h libcxx ]; then ln -s ../../libcxx.src libcxx fi + if [ ! -h libcxxabi ]; then + ln -s ../../libcxxabi.src libcxxabi + fi cd $BuildDir } @@ -292,16 +302,21 @@ function configure_llvmCore() { echo "# Using C compiler: $c_compiler" echo "# Using C++ compiler: $cxx_compiler" + build_triple_option="${BuildTriple:+--build=$BuildTriple}" + cd $ObjDir echo "# Configuring llvm $Release-$RC $Flavor" echo "# $BuildDir/llvm.src/configure --prefix=$InstallDir \ --enable-optimized=$Optimized \ - --enable-assertions=$Assertions" + --enable-assertions=$Assertions \ + --disable-timestamps \ + $build_triple_option" env CC="$c_compiler" CXX="$cxx_compiler" \ $BuildDir/llvm.src/configure --prefix=$InstallDir \ --enable-optimized=$Optimized \ --enable-assertions=$Assertions \ --disable-timestamps \ + $build_triple_option \ 2>&1 | tee $LogDir/llvm.configure-Phase$Phase-$Flavor.log cd $BuildDir } diff --git a/utils/shuffle_fuzz.py b/utils/shuffle_fuzz.py new file mode 100755 index 0000000..384a93a --- /dev/null +++ b/utils/shuffle_fuzz.py @@ -0,0 +1,256 @@ +#!/usr/bin/env python + +"""A shuffle vector fuzz tester. + +This is a python program to fuzz test the LLVM shufflevector instruction. It +generates a function with a random sequnece of shufflevectors, maintaining the +element mapping accumulated across the function. It then generates a main +function which calls it with a different value in each element and checks that +the result matches the expected mapping. + +Take the output IR printed to stdout, compile it to an executable using whatever +set of transforms you want to test, and run the program. If it crashes, it found +a bug. +""" + +import argparse +import itertools +import random +import sys +import uuid + +def main(): + element_types=['i8', 'i16', 'i32', 'i64', 'f32', 'f64'] + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('-v', '--verbose', action='store_true', + help='Show verbose output') + parser.add_argument('--seed', default=str(uuid.uuid4()), + help='A string used to seed the RNG') + parser.add_argument('--max-shuffle-height', type=int, default=16, + help='Specify a fixed height of shuffle tree to test') + parser.add_argument('--no-blends', dest='blends', action='store_false', + help='Include blends of two input vectors') + parser.add_argument('--fixed-bit-width', type=int, choices=[128, 256], + help='Specify a fixed bit width of vector to test') + parser.add_argument('--fixed-element-type', choices=element_types, + help='Specify a fixed element type to test') + parser.add_argument('--triple', + help='Specify a triple string to include in the IR') + args = parser.parse_args() + + random.seed(args.seed) + + if args.fixed_element_type is not None: + element_types=[args.fixed_element_type] + + if args.fixed_bit_width is not None: + if args.fixed_bit_width == 128: + width_map={'i64': 2, 'i32': 4, 'i16': 8, 'i8': 16, 'f64': 2, 'f32': 4} + (width, element_type) = random.choice( + [(width_map[t], t) for t in element_types]) + elif args.fixed_bit_width == 256: + width_map={'i64': 4, 'i32': 8, 'i16': 16, 'i8': 32, 'f64': 4, 'f32': 8} + (width, element_type) = random.choice( + [(width_map[t], t) for t in element_types]) + else: + sys.exit(1) # Checked above by argument parsing. + else: + width = random.choice([2, 4, 8, 16, 32, 64]) + element_type = random.choice(element_types) + + element_modulus = { + 'i8': 1 << 8, 'i16': 1 << 16, 'i32': 1 << 32, 'i64': 1 << 64, + 'f32': 1 << 32, 'f64': 1 << 64}[element_type] + + shuffle_range = (2 * width) if args.blends else width + + # Because undef (-1) saturates and is indistinguishable when testing the + # correctness of a shuffle, we want to bias our fuzz toward having a decent + # mixture of non-undef lanes in the end. With a deep shuffle tree, the + # probabilies aren't good so we need to bias things. The math here is that if + # we uniformly select between -1 and the other inputs, each element of the + # result will have the following probability of being undef: + # + # 1 - (shuffle_range/(shuffle_range+1))^max_shuffle_height + # + # More generally, for any probability P of selecting a defined element in + # a single shuffle, the end result is: + # + # 1 - P^max_shuffle_height + # + # The power of the shuffle height is the real problem, as we want: + # + # 1 - shuffle_range/(shuffle_range+1) + # + # So we bias the selection of undef at any given node based on the tree + # height. Below, let 'A' be 'len(shuffle_range)', 'C' be 'max_shuffle_height', + # and 'B' be the bias we use to compensate for + # C '((A+1)*A^(1/C))/(A*(A+1)^(1/C))': + # + # 1 - (B * A)/(A + 1)^C = 1 - A/(A + 1) + # + # So at each node we use: + # + # 1 - (B * A)/(A + 1) + # = 1 - ((A + 1) * A * A^(1/C))/(A * (A + 1) * (A + 1)^(1/C)) + # = 1 - ((A + 1) * A^((C + 1)/C))/(A * (A + 1)^((C + 1)/C)) + # + # This is the formula we use to select undef lanes in the shuffle. + A = float(shuffle_range) + C = float(args.max_shuffle_height) + undef_prob = 1.0 - (((A + 1.0) * pow(A, (C + 1.0)/C)) / + (A * pow(A + 1.0, (C + 1.0)/C))) + + shuffle_tree = [[[-1 if random.random() <= undef_prob + else random.choice(range(shuffle_range)) + for _ in itertools.repeat(None, width)] + for _ in itertools.repeat(None, args.max_shuffle_height - i)] + for i in xrange(args.max_shuffle_height)] + + if args.verbose: + # Print out the shuffle sequence in a compact form. + print >>sys.stderr, ('Testing shuffle sequence "%s" (v%d%s):' % + (args.seed, width, element_type)) + for i, shuffles in enumerate(shuffle_tree): + print >>sys.stderr, ' tree level %d:' % (i,) + for j, s in enumerate(shuffles): + print >>sys.stderr, ' shuffle %d: %s' % (j, s) + print >>sys.stderr, '' + + # Symbolically evaluate the shuffle tree. + inputs = [[int(j % element_modulus) + for j in xrange(i * width + 1, (i + 1) * width + 1)] + for i in xrange(args.max_shuffle_height + 1)] + results = inputs + for shuffles in shuffle_tree: + results = [[((results[i] if j < width else results[i + 1])[j % width] + if j != -1 else -1) + for j in s] + for i, s in enumerate(shuffles)] + if len(results) != 1: + print >>sys.stderr, 'ERROR: Bad results: %s' % (results,) + sys.exit(1) + result = results[0] + + if args.verbose: + print >>sys.stderr, 'Which transforms:' + print >>sys.stderr, ' from: %s' % (inputs,) + print >>sys.stderr, ' into: %s' % (result,) + print >>sys.stderr, '' + + # The IR uses silly names for floating point types. We also need a same-size + # integer type. + integral_element_type = element_type + if element_type == 'f32': + integral_element_type = 'i32' + element_type = 'float' + elif element_type == 'f64': + integral_element_type = 'i64' + element_type = 'double' + + # Now we need to generate IR for the shuffle function. + subst = {'N': width, 'T': element_type, 'IT': integral_element_type} + print """ +define internal fastcc <%(N)d x %(T)s> @test(%(arguments)s) noinline nounwind { +entry:""" % dict(subst, + arguments=', '.join( + ['<%(N)d x %(T)s> %%s.0.%(i)d' % dict(subst, i=i) + for i in xrange(args.max_shuffle_height + 1)])) + + for i, shuffles in enumerate(shuffle_tree): + for j, s in enumerate(shuffles): + print """ + %%s.%(next_i)d.%(j)d = shufflevector <%(N)d x %(T)s> %%s.%(i)d.%(j)d, <%(N)d x %(T)s> %%s.%(i)d.%(next_j)d, <%(N)d x i32> <%(S)s> +""".strip('\n') % dict(subst, i=i, next_i=i + 1, j=j, next_j=j + 1, + S=', '.join(['i32 ' + (str(si) if si != -1 else 'undef') + for si in s])) + + print """ + ret <%(N)d x %(T)s> %%s.%(i)d.0 +} +""" % dict(subst, i=len(shuffle_tree)) + + # Generate some string constants that we can use to report errors. + for i, r in enumerate(result): + if r != -1: + s = ('FAIL(%(seed)s): lane %(lane)d, expected %(result)d, found %%d\\0A' % + {'seed': args.seed, 'lane': i, 'result': r}) + s += ''.join(['\\00' for _ in itertools.repeat(None, 128 - len(s) + 2)]) + print """ +@error.%(i)d = private unnamed_addr global [128 x i8] c"%(s)s" +""".strip() % {'i': i, 's': s} + + # Define a wrapper function which is marked 'optnone' to prevent + # interprocedural optimizations from deleting the test. + print """ +define internal fastcc <%(N)d x %(T)s> @test_wrapper(%(arguments)s) optnone noinline { + %%result = call fastcc <%(N)d x %(T)s> @test(%(arguments)s) + ret <%(N)d x %(T)s> %%result +} +""" % dict(subst, + arguments=', '.join(['<%(N)d x %(T)s> %%s.%(i)d' % dict(subst, i=i) + for i in xrange(args.max_shuffle_height + 1)])) + + # Finally, generate a main function which will trap if any lanes are mapped + # incorrectly (in an observable way). + print """ +define i32 @main() { +entry: + ; Create a scratch space to print error messages. + %%str = alloca [128 x i8] + %%str.ptr = getelementptr inbounds [128 x i8]* %%str, i32 0, i32 0 + + ; Build the input vector and call the test function. + %%v = call fastcc <%(N)d x %(T)s> @test_wrapper(%(inputs)s) + ; We need to cast this back to an integer type vector to easily check the + ; result. + %%v.cast = bitcast <%(N)d x %(T)s> %%v to <%(N)d x %(IT)s> + br label %%test.0 +""" % dict(subst, + inputs=', '.join( + [('<%(N)d x %(T)s> bitcast ' + '(<%(N)d x %(IT)s> <%(input)s> to <%(N)d x %(T)s>)' % + dict(subst, input=', '.join(['%(IT)s %(i)d' % dict(subst, i=i) + for i in input]))) + for input in inputs])) + + # Test that each non-undef result lane contains the expected value. + for i, r in enumerate(result): + if r == -1: + print """ +test.%(i)d: + ; Skip this lane, its value is undef. + br label %%test.%(next_i)d +""" % dict(subst, i=i, next_i=i + 1) + else: + print """ +test.%(i)d: + %%v.%(i)d = extractelement <%(N)d x %(IT)s> %%v.cast, i32 %(i)d + %%cmp.%(i)d = icmp ne %(IT)s %%v.%(i)d, %(r)d + br i1 %%cmp.%(i)d, label %%die.%(i)d, label %%test.%(next_i)d + +die.%(i)d: + ; Capture the actual value and print an error message. + %%tmp.%(i)d = zext %(IT)s %%v.%(i)d to i2048 + %%bad.%(i)d = trunc i2048 %%tmp.%(i)d to i32 + call i32 (i8*, i8*, ...)* @sprintf(i8* %%str.ptr, i8* getelementptr inbounds ([128 x i8]* @error.%(i)d, i32 0, i32 0), i32 %%bad.%(i)d) + %%length.%(i)d = call i32 @strlen(i8* %%str.ptr) + %%size.%(i)d = add i32 %%length.%(i)d, 1 + call i32 @write(i32 2, i8* %%str.ptr, i32 %%size.%(i)d) + call void @llvm.trap() + unreachable +""" % dict(subst, i=i, next_i=i + 1, r=r) + + print """ +test.%d: + ret i32 0 +} + +declare i32 @strlen(i8*) +declare i32 @write(i32, i8*, i32) +declare i32 @sprintf(i8*, i8*, ...) +declare void @llvm.trap() noreturn nounwind +""" % (len(result),) + +if __name__ == '__main__': + main() diff --git a/utils/update_llc_test_checks.py b/utils/update_llc_test_checks.py new file mode 100755 index 0000000..4125ea9 --- /dev/null +++ b/utils/update_llc_test_checks.py @@ -0,0 +1,207 @@ +#!/usr/bin/env python2.7 + +"""A test case update script. + +This script is a utility to update LLVM X86 'llc' based test cases with new +FileCheck patterns. It can either update all of the tests in the file or +a single test function. +""" + +import argparse +import itertools +import string +import subprocess +import sys +import tempfile +import re + + +def llc(args, cmd_args, ir): + with open(ir) as ir_file: + stdout = subprocess.check_output(args.llc_binary + ' ' + cmd_args, + shell=True, stdin=ir_file) + return stdout + + +ASM_SCRUB_WHITESPACE_RE = re.compile(r'(?!^(| \w))[ \t]+', flags=re.M) +ASM_SCRUB_SHUFFLES_RE = ( + re.compile( + r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem) = .*)$', + flags=re.M)) +ASM_SCRUB_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)') +ASM_SCRUB_RIP_RE = re.compile(r'[.\w]+\(%rip\)') +ASM_SCRUB_KILL_COMMENT_RE = re.compile(r'^ *#+ +kill:.*\n') + + +def scrub_asm(asm): + # Scrub runs of whitespace out of the assembly, but leave the leading + # whitespace in place. + asm = ASM_SCRUB_WHITESPACE_RE.sub(r' ', asm) + # Expand the tabs used for indentation. + asm = string.expandtabs(asm, 2) + # Detect shuffle asm comments and hide the operands in favor of the comments. + asm = ASM_SCRUB_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm) + # Generically match the stack offset of a memory operand. + asm = ASM_SCRUB_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm) + # Generically match a RIP-relative memory operand. + asm = ASM_SCRUB_RIP_RE.sub(r'{{.*}}(%rip)', asm) + # Strip kill operands inserted into the asm. + asm = ASM_SCRUB_KILL_COMMENT_RE.sub('', asm) + return asm + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('-v', '--verbose', action='store_true', + help='Show verbose output') + parser.add_argument('--llc-binary', default='llc', + help='The "llc" binary to use to generate the test case') + parser.add_argument( + '--function', help='The function in the test file to update') + parser.add_argument('tests', nargs='+') + args = parser.parse_args() + + run_line_re = re.compile('^\s*;\s*RUN:\s*(.*)$') + ir_function_re = re.compile('^\s*define\s+(?:internal\s+)?[^@]*@(\w+)\s*\(') + asm_function_re = re.compile( + r'^_?(?P[^:]+):[ \t]*#+[ \t]*@(?P=f)\n[^:]*?' + r'(?P^##?[ \t]+[^:]+:.*?)\s*' + r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.(?:sub)?section)', + flags=(re.M | re.S)) + check_prefix_re = re.compile('--check-prefix=(\S+)') + check_re = re.compile(r'^\s*;\s*([^:]+?)(?:-NEXT|-NOT|-DAG|-LABEL)?:') + + for test in args.tests: + if args.verbose: + print >>sys.stderr, 'Scanning for RUN lines in test file: %s' % (test,) + with open(test) as f: + test_lines = [l.rstrip() for l in f] + + run_lines = [m.group(1) + for m in [run_line_re.match(l) for l in test_lines] if m] + if args.verbose: + print >>sys.stderr, 'Found %d RUN lines:' % (len(run_lines),) + for l in run_lines: + print >>sys.stderr, ' RUN: ' + l + + checks = [] + for l in run_lines: + (llc_cmd, filecheck_cmd) = tuple([cmd.strip() for cmd in l.split('|', 1)]) + if not llc_cmd.startswith('llc '): + print >>sys.stderr, 'WARNING: Skipping non-llc RUN line: ' + l + continue + + if not filecheck_cmd.startswith('FileCheck '): + print >>sys.stderr, 'WARNING: Skipping non-FileChecked RUN line: ' + l + continue + + llc_cmd_args = llc_cmd[len('llc'):].strip() + llc_cmd_args = llc_cmd_args.replace('< %s', '').replace('%s', '').strip() + + check_prefixes = [m.group(1) + for m in check_prefix_re.finditer(filecheck_cmd)] + if not check_prefixes: + check_prefixes = ['CHECK'] + + # FIXME: We should use multiple check prefixes to common check lines. For + # now, we just ignore all but the last. + checks.append((check_prefixes, llc_cmd_args)) + + asm = {} + for prefixes, _ in checks: + for prefix in prefixes: + asm.update({prefix: dict()}) + for prefixes, llc_args in checks: + if args.verbose: + print >>sys.stderr, 'Extracted LLC cmd: llc ' + llc_args + print >>sys.stderr, 'Extracted FileCheck prefixes: ' + str(prefixes) + raw_asm = llc(args, llc_args, test) + # Build up a dictionary of all the function bodies. + for m in asm_function_re.finditer(raw_asm): + if not m: + continue + f = m.group('f') + f_asm = scrub_asm(m.group('body')) + if args.verbose: + print >>sys.stderr, 'Processing asm for function: ' + f + for l in f_asm.splitlines(): + print >>sys.stderr, ' ' + l + for prefix in prefixes: + if f in asm[prefix] and asm[prefix][f] != f_asm: + if prefix == prefixes[-1]: + print >>sys.stderr, ('WARNING: Found conflicting asm under the ' + 'same prefix!') + else: + asm[prefix][f] = None + continue + + asm[prefix][f] = f_asm + + is_in_function = False + is_in_function_start = False + prefix_set = set([prefix for prefixes, _ in checks for prefix in prefixes]) + if args.verbose: + print >>sys.stderr, 'Rewriting FileCheck prefixes: %s' % (prefix_set,) + fixed_lines = [] + for l in test_lines: + if is_in_function_start: + if l.lstrip().startswith(';'): + m = check_re.match(l) + if not m or m.group(1) not in prefix_set: + fixed_lines.append(l) + continue + + # Print out the various check lines here + printed_prefixes = [] + for prefixes, _ in checks: + for prefix in prefixes: + if prefix in printed_prefixes: + break + if not asm[prefix][name]: + continue + if len(printed_prefixes) != 0: + fixed_lines.append(';') + printed_prefixes.append(prefix) + fixed_lines.append('; %s-LABEL: %s:' % (prefix, name)) + asm_lines = asm[prefix][name].splitlines() + fixed_lines.append('; %s: %s' % (prefix, asm_lines[0])) + for asm_line in asm_lines[1:]: + fixed_lines.append('; %s-NEXT: %s' % (prefix, asm_line)) + break + is_in_function_start = False + + if is_in_function: + # Skip any blank comment lines in the IR. + if l.strip() == ';': + continue + # And skip any CHECK lines. We'll build our own. + m = check_re.match(l) + if m and m.group(1) in prefix_set: + continue + # Collect the remaining lines in the function body and look for the end + # of the function. + fixed_lines.append(l) + if l.strip() == '}': + is_in_function = False + continue + + fixed_lines.append(l) + + m = ir_function_re.match(l) + if not m: + continue + name = m.group(1) + if args.function is not None and name != args.function: + # When filtering on a specific function, skip all others. + continue + is_in_function = is_in_function_start = True + + if args.verbose: + print>>sys.stderr, 'Writing %d fixed lines to %s...' % ( + len(fixed_lines), test) + with open(test, 'w') as f: + f.writelines([l + '\n' for l in fixed_lines]) + + +if __name__ == '__main__': + main() diff --git a/utils/valgrind/x86_64-pc-linux-gnu.supp b/utils/valgrind/x86_64-pc-linux-gnu.supp index c8e5cd0..d6af2dd 100644 --- a/utils/valgrind/x86_64-pc-linux-gnu.supp +++ b/utils/valgrind/x86_64-pc-linux-gnu.supp @@ -33,6 +33,14 @@ } { + We don't care if bash leaks + Memcheck:Leak + fun:malloc + fun:xmalloc + obj:/bin/bash +} + +{ We don't care of cmp Memcheck:Cond obj:/usr/bin/cmp @@ -52,6 +60,14 @@ } { + We don't care if sed leaks + Memcheck:Leak + fun:calloc + fun:malloc + obj:/bin/sed +} + +{ We don't care about anything ld.so does. Memcheck:Cond obj:/lib/ld*.so diff --git a/utils/vim/llvm.vim b/utils/vim/llvm.vim index f5447a0..f767fda 100644 --- a/utils/vim/llvm.vim +++ b/utils/vim/llvm.vim @@ -1,7 +1,7 @@ " Vim syntax file " Language: llvm " Maintainer: The LLVM team, http://llvm.org/ -" Version: $Revision: 203866 $ +" Version: $Revision: 225830 $ if version < 600 syntax clear @@ -41,28 +41,28 @@ syn keyword llvmKeyword alignstack alwaysinline appending arm_aapcs_vfpcc syn keyword llvmKeyword arm_aapcscc arm_apcscc asm atomic available_externally syn keyword llvmKeyword blockaddress byval c catch cc ccc cleanup coldcc common syn keyword llvmKeyword constant datalayout declare default define deplibs -syn keyword llvmKeyword dllexport dllimport except extern_weak external fastcc -syn keyword llvmKeyword filter gc global hidden initialexec inlinehint inreg -syn keyword llvmKeyword intel_ocl_bicc inteldialect internal -syn keyword llvmKeyword linkonce linkonce_odr -syn keyword llvmKeyword localdynamic localexec minsize module monotonic -syn keyword llvmKeyword msp430_intrcc naked nest noalias nocapture -syn keyword llvmKeyword noimplicitfloat noinline nonlazybind noredzone noreturn -syn keyword llvmKeyword nounwind optnone optsize personality private protected -syn keyword llvmKeyword ptx_device ptx_kernel readnone readonly release -syn keyword llvmKeyword returns_twice sanitize_thread sanitize_memory -syn keyword llvmKeyword section seq_cst sideeffect signext singlethread -syn keyword llvmKeyword spir_func spir_kernel sret ssp sspreq sspstrong -syn keyword llvmKeyword tail target thread_local to triple unnamed_addr -syn keyword llvmKeyword unordered uwtable volatile weak weak_odr -syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc x86_64_sysvcc -syn keyword llvmKeyword x86_64_win64cc zeroext +syn keyword llvmKeyword distinct dllexport dllimport except extern_weak external +syn keyword llvmKeyword externally_initialized fastcc filter gc global hidden +syn keyword llvmKeyword initialexec inlinehint inreg intel_ocl_bicc inteldialect +syn keyword llvmKeyword internal linkonce linkonce_odr localdynamic localexec +syn keyword llvmKeyword minsize module monotonic msp430_intrcc naked nest +syn keyword llvmKeyword noalias nocapture noimplicitfloat noinline nonlazybind +syn keyword llvmKeyword noredzone noreturn nounwind optnone optsize personality +syn keyword llvmKeyword private protected ptx_device ptx_kernel readnone +syn keyword llvmKeyword readonly release returns_twice sanitize_thread +syn keyword llvmKeyword sanitize_memory section seq_cst sideeffect signext +syn keyword llvmKeyword singlethread spir_func spir_kernel sret ssp sspreq +syn keyword llvmKeyword sspstrong tail target thread_local to triple +syn keyword llvmKeyword unnamed_addr unordered uwtable volatile weak weak_odr +syn keyword llvmKeyword x86_fastcallcc x86_stdcallcc x86_thiscallcc +syn keyword llvmKeyword x86_64_sysvcc x86_64_win64cc zeroext uselistorder +syn keyword llvmKeyword uselistorder_bb " Obsolete keywords. syn keyword llvmError getresult begin end " Misc syntax. -syn match llvmNoName /[%@]\d\+\>/ +syn match llvmNoName /[%@!]\d\+\>/ syn match llvmNumber /-\?\<\d\+\>/ syn match llvmFloat /-\?\<\d\+\.\d*\(e[+-]\d\+\)\?\>/ syn match llvmFloat /\<0x\x\+\>/ @@ -73,6 +73,11 @@ syn region llvmString start=/"/ skip=/\\"/ end=/"/ syn match llvmLabel /[-a-zA-Z$._][-a-zA-Z$._0-9]*:/ syn match llvmIdentifier /[%@][-a-zA-Z$._][-a-zA-Z$._0-9]*/ +" Named metadata and specialized metadata keywords. +syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*$/ +syn match llvmIdentifier /![-a-zA-Z$._][-a-zA-Z$._0-9]*\ze\s*[=!]/ +syn match llvmType /!\zs\a\+\ze\s*(/ + " Syntax-highlight dejagnu test commands. syn match llvmSpecialComment /;\s*RUN:.*$/ syn match llvmSpecialComment /;\s*PR\d*\s*$/ diff --git a/utils/yaml-bench/YAMLBench.cpp b/utils/yaml-bench/YAMLBench.cpp index e88ce5d..8bd1ea1 100644 --- a/utils/yaml-bench/YAMLBench.cpp +++ b/utils/yaml-bench/YAMLBench.cpp @@ -192,15 +192,15 @@ int main(int argc, char **argv) { MemoryBuffer::getFileOrSTDIN(Input); if (!BufOrErr) return 1; - std::unique_ptr Buf = std::move(BufOrErr.get()); + MemoryBuffer &Buf = *BufOrErr.get(); llvm::SourceMgr sm; if (DumpTokens) { - yaml::dumpTokens(Buf->getBuffer(), outs()); + yaml::dumpTokens(Buf.getBuffer(), outs()); } if (DumpCanonical) { - yaml::Stream stream(Buf->getBuffer(), sm); + yaml::Stream stream(Buf.getBuffer(), sm); dumpStream(stream); } } -- cgit v1.1 From c86b984ea8ecb3e944dc3de48539f4c1f65851ea Mon Sep 17 00:00:00 2001 From: dim Date: Sun, 18 Jan 2015 16:23:48 +0000 Subject: Vendor import of clang RELEASE_360/rc1 tag r226102 (effectively, 3.6.0 RC1): https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_360/rc1@226102 --- .clang-tidy | 1 + CMakeLists.txt | 62 +- CODE_OWNERS.TXT | 4 +- bindings/python/clang/cindex.py | 265 ++- bindings/python/tests/cindex/test_cursor.py | 58 + cmake/modules/ClangConfig.cmake | 8 + docs/AddressSanitizer.rst | 5 +- docs/ClangFormat.rst | 4 +- docs/ClangFormatStyleOptions.rst | 116 +- docs/CrossCompilation.rst | 1 - docs/InternalsManual.rst | 37 +- docs/LanguageExtensions.rst | 236 +- docs/LibASTMatchersReference.html | 356 ++- docs/MSVCCompatibility.rst | 16 +- docs/Modules.rst | 76 +- docs/RAVFrontendAction.rst | 15 +- docs/ReleaseNotes.rst | 225 +- docs/ThreadSafetyAnalysis.rst | 663 +++--- docs/UsersManual.rst | 72 +- docs/conf.py | 4 +- docs/tools/dump_format_style.py | 1 + examples/PrintFunctionNames/PrintFunctionNames.cpp | 5 +- examples/clang-interpreter/CMakeLists.txt | 3 +- examples/clang-interpreter/Makefile | 6 +- examples/clang-interpreter/main.cpp | 40 +- include/clang-c/BuildSystem.h | 4 +- include/clang-c/CXCompilationDatabase.h | 4 +- include/clang-c/CXErrorCode.h | 4 +- include/clang-c/CXString.h | 4 +- include/clang-c/Documentation.h | 4 +- include/clang-c/Index.h | 201 +- include/clang-c/Platform.h | 4 +- include/clang/ARCMigrate/ARCMTActions.h | 12 +- include/clang/ARCMigrate/FileRemapper.h | 4 +- include/clang/AST/ASTContext.h | 111 +- include/clang/AST/ASTDiagnostic.h | 4 +- include/clang/AST/ASTFwd.h | 5 + include/clang/AST/ASTLambda.h | 6 +- include/clang/AST/ASTMutationListener.h | 6 + include/clang/AST/ASTTypeTraits.h | 111 +- include/clang/AST/ASTVector.h | 23 +- include/clang/AST/Attr.h | 1 + include/clang/AST/CanonicalType.h | 6 +- include/clang/AST/Comment.h | 10 +- include/clang/AST/CommentBriefParser.h | 4 +- include/clang/AST/CommentCommandTraits.h | 10 +- include/clang/AST/CommentDiagnostic.h | 4 +- include/clang/AST/CommentLexer.h | 4 +- include/clang/AST/CommentParser.h | 4 +- include/clang/AST/CommentSema.h | 6 +- include/clang/AST/DataRecursiveASTVisitor.h | 103 +- include/clang/AST/Decl.h | 162 +- include/clang/AST/DeclBase.h | 21 +- include/clang/AST/DeclCXX.h | 109 +- include/clang/AST/DeclLookups.h | 10 +- include/clang/AST/DeclObjC.h | 9 +- include/clang/AST/DeclOpenMP.h | 10 +- include/clang/AST/DeclTemplate.h | 8 +- include/clang/AST/DeclarationName.h | 1 + include/clang/AST/DependentDiagnostic.h | 7 +- include/clang/AST/EvaluatedExprVisitor.h | 11 + include/clang/AST/Expr.h | 128 +- include/clang/AST/ExprCXX.h | 103 +- include/clang/AST/ExprObjC.h | 9 + include/clang/AST/ExternalASTSource.h | 6 +- include/clang/AST/LambdaCapture.h | 12 +- include/clang/AST/Mangle.h | 5 + include/clang/AST/MangleNumberingContext.h | 17 +- include/clang/AST/NSAPI.h | 10 +- include/clang/AST/NestedNameSpecifier.h | 34 +- include/clang/AST/OpenMPClause.h | 261 ++- include/clang/AST/OperationKinds.h | 4 +- include/clang/AST/ParentMap.h | 4 +- include/clang/AST/PrettyPrinter.h | 4 +- include/clang/AST/RawCommentList.h | 4 +- include/clang/AST/RecordLayout.h | 4 +- include/clang/AST/RecursiveASTVisitor.h | 103 +- include/clang/AST/Stmt.h | 99 +- include/clang/AST/StmtGraphTraits.h | 4 +- include/clang/AST/StmtIterator.h | 4 +- include/clang/AST/StmtOpenMP.h | 800 ++++++- include/clang/AST/TemplateBase.h | 16 +- include/clang/AST/Type.h | 160 +- include/clang/AST/TypeLoc.h | 4 +- include/clang/AST/TypeOrdering.h | 4 +- include/clang/AST/UnresolvedSet.h | 2 +- include/clang/ASTMatchers/ASTMatchFinder.h | 69 +- include/clang/ASTMatchers/ASTMatchers.h | 337 ++- include/clang/ASTMatchers/ASTMatchersInternal.h | 636 +++--- include/clang/ASTMatchers/ASTMatchersMacros.h | 17 +- include/clang/ASTMatchers/Dynamic/Diagnostics.h | 4 +- include/clang/ASTMatchers/Dynamic/Parser.h | 130 +- include/clang/ASTMatchers/Dynamic/Registry.h | 51 +- include/clang/ASTMatchers/Dynamic/VariantValue.h | 184 +- .../Analysis/Analyses/CFGReachabilityAnalysis.h | 4 +- include/clang/Analysis/Analyses/Consumed.h | 4 +- include/clang/Analysis/Analyses/Dominators.h | 4 +- include/clang/Analysis/Analyses/FormatString.h | 10 +- include/clang/Analysis/Analyses/LiveVariables.h | 4 +- include/clang/Analysis/Analyses/PostOrderCFGView.h | 12 +- .../Analysis/Analyses/PseudoConstantAnalysis.h | 4 +- include/clang/Analysis/Analyses/ReachableCode.h | 4 +- include/clang/Analysis/Analyses/ThreadSafety.h | 33 +- .../clang/Analysis/Analyses/ThreadSafetyCommon.h | 140 +- .../clang/Analysis/Analyses/ThreadSafetyLogical.h | 12 +- .../clang/Analysis/Analyses/ThreadSafetyOps.def | 3 + include/clang/Analysis/Analyses/ThreadSafetyTIL.h | 1107 ++++----- .../clang/Analysis/Analyses/ThreadSafetyTraverse.h | 450 ++-- include/clang/Analysis/Analyses/ThreadSafetyUtil.h | 68 +- .../clang/Analysis/Analyses/UninitializedValues.h | 4 +- include/clang/Analysis/AnalysisContext.h | 16 +- include/clang/Analysis/AnalysisDiagnostic.h | 4 +- include/clang/Analysis/CFG.h | 11 +- include/clang/Analysis/CFGStmtMap.h | 4 +- include/clang/Analysis/CallGraph.h | 4 +- include/clang/Analysis/CodeInjector.h | 46 + .../Analysis/DomainSpecific/CocoaConventions.h | 4 +- .../clang/Analysis/DomainSpecific/ObjCNoReturn.h | 4 +- include/clang/Analysis/ProgramPoint.h | 4 +- include/clang/Analysis/Support/BumpVector.h | 6 +- include/clang/Basic/ABI.h | 11 +- include/clang/Basic/AddressSpaces.h | 1 + include/clang/Basic/AllDiagnostics.h | 4 +- include/clang/Basic/Attr.td | 246 +- include/clang/Basic/AttrDocs.td | 338 ++- include/clang/Basic/AttrKinds.h | 4 +- include/clang/Basic/Attributes.h | 14 +- include/clang/Basic/Builtins.def | 19 + include/clang/Basic/Builtins.h | 4 +- include/clang/Basic/BuiltinsAArch64.def | 3 + include/clang/Basic/BuiltinsARM.def | 6 + include/clang/Basic/BuiltinsLe64.def | 19 + include/clang/Basic/BuiltinsNVPTX.def | 30 +- include/clang/Basic/BuiltinsPPC.def | 19 + include/clang/Basic/BuiltinsR600.def | 8 +- include/clang/Basic/BuiltinsX86.def | 207 +- include/clang/Basic/CharInfo.h | 4 +- include/clang/Basic/CommentOptions.h | 4 +- include/clang/Basic/Diagnostic.h | 16 +- include/clang/Basic/DiagnosticASTKinds.td | 7 + include/clang/Basic/DiagnosticCommonKinds.td | 14 +- include/clang/Basic/DiagnosticDriverKinds.td | 18 +- include/clang/Basic/DiagnosticFrontendKinds.td | 34 +- include/clang/Basic/DiagnosticGroups.td | 75 +- include/clang/Basic/DiagnosticIDs.h | 6 +- include/clang/Basic/DiagnosticLexKinds.td | 25 +- include/clang/Basic/DiagnosticOptions.def | 3 +- include/clang/Basic/DiagnosticOptions.h | 3 +- include/clang/Basic/DiagnosticParseKinds.td | 115 +- include/clang/Basic/DiagnosticSemaKinds.td | 444 +++- .../clang/Basic/DiagnosticSerializationKinds.td | 10 +- include/clang/Basic/ExceptionSpecificationType.h | 3 +- include/clang/Basic/ExpressionTraits.h | 4 +- include/clang/Basic/FileManager.h | 25 +- include/clang/Basic/FileSystemStatCache.h | 12 +- include/clang/Basic/IdentifierTable.h | 65 +- include/clang/Basic/LLVM.h | 4 +- include/clang/Basic/Lambda.h | 3 +- include/clang/Basic/LangOptions.def | 68 +- include/clang/Basic/LangOptions.h | 26 +- include/clang/Basic/Module.h | 52 +- include/clang/Basic/ObjCRuntime.h | 4 +- include/clang/Basic/OpenMPKinds.def | 79 + include/clang/Basic/OpenMPKinds.h | 6 + include/clang/Basic/OperatorKinds.h | 4 +- include/clang/Basic/OperatorPrecedence.h | 4 +- include/clang/Basic/PartialDiagnostic.h | 4 +- include/clang/Basic/PlistSupport.h | 4 +- include/clang/Basic/PrettyStackTrace.h | 4 +- include/clang/Basic/SanitizerBlacklist.h | 45 + include/clang/Basic/Sanitizers.def | 19 +- include/clang/Basic/Sanitizers.h | 47 + include/clang/Basic/SourceLocation.h | 5 +- include/clang/Basic/SourceManager.h | 31 +- include/clang/Basic/SourceManagerInternals.h | 4 +- include/clang/Basic/Specifiers.h | 11 +- include/clang/Basic/StmtNodes.td | 15 +- include/clang/Basic/TargetBuiltins.h | 15 +- include/clang/Basic/TargetCXXABI.h | 4 +- include/clang/Basic/TargetInfo.h | 52 +- include/clang/Basic/TargetOptions.h | 4 +- include/clang/Basic/TemplateKinds.h | 4 +- include/clang/Basic/TokenKinds.def | 14 +- include/clang/Basic/TokenKinds.h | 10 +- include/clang/Basic/TypeTraits.h | 4 +- include/clang/Basic/VersionTuple.h | 29 +- include/clang/Basic/VirtualFileSystem.h | 36 +- include/clang/Basic/arm_neon.td | 49 +- include/clang/CodeGen/BackendUtil.h | 4 +- include/clang/CodeGen/CGFunctionInfo.h | 35 +- include/clang/CodeGen/CodeGenABITypes.h | 8 +- include/clang/CodeGen/CodeGenAction.h | 14 +- include/clang/CodeGen/ModuleBuilder.h | 4 +- include/clang/Config/config.h.cmake | 6 + include/clang/Config/config.h.in | 9 +- include/clang/Driver/Action.h | 46 +- include/clang/Driver/CC1Options.td | 29 +- include/clang/Driver/CLCompatOptions.td | 30 +- include/clang/Driver/Compilation.h | 6 +- include/clang/Driver/Driver.h | 32 +- include/clang/Driver/DriverDiagnostic.h | 4 +- include/clang/Driver/Job.h | 70 +- include/clang/Driver/Multilib.h | 16 +- include/clang/Driver/Options.h | 4 +- include/clang/Driver/Options.td | 179 +- include/clang/Driver/Phases.h | 5 +- include/clang/Driver/SanitizerArgs.h | 126 +- include/clang/Driver/Tool.h | 62 +- include/clang/Driver/ToolChain.h | 14 +- include/clang/Driver/Types.h | 4 +- include/clang/Driver/Util.h | 4 +- include/clang/Format/Format.h | 99 +- include/clang/Frontend/ASTConsumers.h | 18 +- include/clang/Frontend/ASTUnit.h | 57 +- include/clang/Frontend/ChainedDiagnosticConsumer.h | 17 +- include/clang/Frontend/CodeGenOptions.def | 14 +- include/clang/Frontend/CodeGenOptions.h | 25 +- include/clang/Frontend/CompilerInstance.h | 38 +- include/clang/Frontend/DiagnosticRenderer.h | 4 +- include/clang/Frontend/FrontendAction.h | 41 +- include/clang/Frontend/FrontendActions.h | 51 +- include/clang/Frontend/FrontendDiagnostic.h | 4 +- include/clang/Frontend/FrontendOptions.h | 16 +- include/clang/Frontend/FrontendPluginRegistry.h | 4 +- include/clang/Frontend/LangStandard.h | 6 +- include/clang/Frontend/LangStandards.def | 15 +- include/clang/Frontend/LogDiagnosticPrinter.h | 15 +- include/clang/Frontend/MigratorOptions.h | 4 +- include/clang/Frontend/MultiplexConsumer.h | 8 +- .../clang/Frontend/SerializedDiagnosticPrinter.h | 45 +- .../clang/Frontend/SerializedDiagnosticReader.h | 131 ++ include/clang/Frontend/SerializedDiagnostics.h | 59 + include/clang/Frontend/TextDiagnostic.h | 4 +- include/clang/Frontend/TextDiagnosticBuffer.h | 4 +- include/clang/Frontend/TextDiagnosticPrinter.h | 4 +- include/clang/Frontend/Utils.h | 5 +- include/clang/Frontend/VerifyDiagnosticConsumer.h | 27 +- include/clang/Lex/ExternalPreprocessorSource.h | 6 +- include/clang/Lex/HeaderMap.h | 10 +- include/clang/Lex/HeaderSearch.h | 29 +- include/clang/Lex/HeaderSearchOptions.h | 13 +- include/clang/Lex/LexDiagnostic.h | 4 +- include/clang/Lex/Lexer.h | 10 +- include/clang/Lex/LiteralSupport.h | 4 +- include/clang/Lex/MacroArgs.h | 4 +- include/clang/Lex/MacroInfo.h | 119 +- include/clang/Lex/ModuleLoader.h | 4 +- include/clang/Lex/ModuleMap.h | 116 +- include/clang/Lex/MultipleIncludeOpt.h | 4 +- include/clang/Lex/PPCallbacks.h | 11 +- include/clang/Lex/PTHLexer.h | 4 +- include/clang/Lex/PTHManager.h | 32 +- include/clang/Lex/Pragma.h | 4 +- include/clang/Lex/Preprocessor.h | 103 +- include/clang/Lex/PreprocessorLexer.h | 4 +- include/clang/Lex/ScratchBuffer.h | 4 +- include/clang/Lex/Token.h | 29 +- include/clang/Lex/TokenConcatenation.h | 4 +- include/clang/Lex/TokenLexer.h | 4 +- include/clang/Parse/ParseDiagnostic.h | 4 +- include/clang/Parse/Parser.h | 103 +- include/clang/Rewrite/Core/DeltaTree.h | 4 +- include/clang/Rewrite/Core/HTMLRewrite.h | 4 +- include/clang/Rewrite/Core/RewriteRope.h | 52 +- include/clang/Rewrite/Core/Rewriter.h | 14 +- include/clang/Rewrite/Core/TokenRewriter.h | 4 +- include/clang/Rewrite/Frontend/ASTConsumers.h | 31 +- include/clang/Rewrite/Frontend/FixItRewriter.h | 8 +- include/clang/Rewrite/Frontend/FrontendActions.h | 16 +- include/clang/Rewrite/Frontend/Rewriters.h | 4 +- include/clang/Sema/AnalysisBasedWarnings.h | 4 +- include/clang/Sema/AttributeList.h | 15 +- include/clang/Sema/DeclSpec.h | 58 +- include/clang/Sema/DelayedDiagnostic.h | 4 +- include/clang/Sema/ExternalSemaSource.h | 17 +- include/clang/Sema/IdentifierResolver.h | 4 +- include/clang/Sema/Lookup.h | 27 +- include/clang/Sema/LoopHint.h | 13 +- include/clang/Sema/MultiplexExternalSemaSource.h | 15 +- include/clang/Sema/ObjCMethodList.h | 31 +- include/clang/Sema/Overload.h | 36 +- include/clang/Sema/PrettyDeclStackTrace.h | 4 +- include/clang/Sema/Scope.h | 20 +- include/clang/Sema/ScopeInfo.h | 41 +- include/clang/Sema/Sema.h | 485 +++- include/clang/Sema/SemaDiagnostic.h | 4 +- include/clang/Sema/SemaFixItUtils.h | 6 +- include/clang/Sema/SemaInternal.h | 212 +- include/clang/Sema/SemaLambda.h | 6 +- include/clang/Sema/TemplateDeduction.h | 4 +- include/clang/Sema/TypoCorrection.h | 42 +- include/clang/Serialization/ASTBitCodes.h | 41 +- .../Serialization/ASTDeserializationListener.h | 4 +- include/clang/Serialization/ASTReader.h | 133 +- include/clang/Serialization/ASTWriter.h | 67 +- include/clang/Serialization/ContinuousRangeMap.h | 12 +- include/clang/Serialization/GlobalModuleIndex.h | 6 +- include/clang/Serialization/Module.h | 18 +- include/clang/Serialization/ModuleManager.h | 23 +- .../clang/Serialization/SerializationDiagnostic.h | 4 +- .../clang/StaticAnalyzer/Checkers/LocalCheckers.h | 4 +- .../StaticAnalyzer/Checkers/ObjCRetainCount.h | 14 +- .../clang/StaticAnalyzer/Core/AnalyzerOptions.h | 12 +- .../StaticAnalyzer/Core/BugReporter/BugReporter.h | 21 +- .../Core/BugReporter/BugReporterVisitor.h | 30 +- .../StaticAnalyzer/Core/BugReporter/BugType.h | 4 +- .../Core/BugReporter/CommonBugCategories.h | 4 +- .../Core/BugReporter/PathDiagnostic.h | 12 +- include/clang/StaticAnalyzer/Core/Checker.h | 4 +- include/clang/StaticAnalyzer/Core/CheckerManager.h | 4 +- .../StaticAnalyzer/Core/PathDiagnosticConsumers.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/APSIntType.h | 4 +- .../Core/PathSensitive/AnalysisManager.h | 9 +- .../Core/PathSensitive/BasicValueFactory.h | 4 +- .../Core/PathSensitive/BlockCounter.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/CallEvent.h | 4 +- .../Core/PathSensitive/CheckerContext.h | 4 +- .../Core/PathSensitive/CheckerHelpers.h | 4 +- .../Core/PathSensitive/ConstraintManager.h | 9 +- .../StaticAnalyzer/Core/PathSensitive/CoreEngine.h | 23 +- .../Core/PathSensitive/DynamicTypeInfo.h | 4 +- .../Core/PathSensitive/Environment.h | 4 +- .../Core/PathSensitive/ExplodedGraph.h | 15 +- .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 19 +- .../Core/PathSensitive/FunctionSummary.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/MemRegion.h | 4 +- .../Core/PathSensitive/ProgramState.h | 11 +- .../Core/PathSensitive/ProgramStateTrait.h | 4 +- .../Core/PathSensitive/ProgramState_Fwd.h | 4 +- .../Core/PathSensitive/SValBuilder.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/Store.h | 10 +- .../StaticAnalyzer/Core/PathSensitive/StoreRef.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/SubEngine.h | 14 +- .../Core/PathSensitive/SymbolManager.h | 4 +- .../Core/PathSensitive/TaintManager.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/TaintTag.h | 4 +- .../StaticAnalyzer/Core/PathSensitive/WorkList.h | 4 +- .../StaticAnalyzer/Frontend/AnalysisConsumer.h | 12 +- .../StaticAnalyzer/Frontend/CheckerRegistration.h | 12 +- .../StaticAnalyzer/Frontend/FrontendActions.h | 33 +- .../clang/StaticAnalyzer/Frontend/ModelConsumer.h | 44 + include/clang/Tooling/ArgumentsAdjusters.h | 68 +- include/clang/Tooling/CommonOptionsParser.h | 6 +- include/clang/Tooling/CompilationDatabase.h | 22 +- .../Tooling/CompilationDatabasePluginRegistry.h | 6 +- include/clang/Tooling/Core/Replacement.h | 229 ++ include/clang/Tooling/FileMatchTrie.h | 6 +- include/clang/Tooling/JSONCompilationDatabase.h | 19 +- include/clang/Tooling/Refactoring.h | 176 +- include/clang/Tooling/RefactoringCallbacks.h | 6 +- include/clang/Tooling/ReplacementsYaml.h | 6 +- include/clang/Tooling/Tooling.h | 42 +- include/clang/module.modulemap | 25 +- lib/ARCMigrate/ARCMT.cpp | 15 +- lib/ARCMigrate/FileRemapper.cpp | 34 +- lib/ARCMigrate/Internals.h | 2 +- lib/ARCMigrate/ObjCMT.cpp | 286 ++- lib/ARCMigrate/PlistReporter.cpp | 6 +- lib/ARCMigrate/TransformActions.cpp | 3 +- lib/AST/APValue.cpp | 4 +- lib/AST/ASTContext.cpp | 419 ++-- lib/AST/ASTDiagnostic.cpp | 431 ++-- lib/AST/ASTDumper.cpp | 1144 +++++----- lib/AST/ASTImporter.cpp | 124 +- lib/AST/ASTTypeTraits.cpp | 47 + lib/AST/CMakeLists.txt | 1 - lib/AST/CXXABI.h | 4 +- lib/AST/Comment.cpp | 17 +- lib/AST/CommentCommandTraits.cpp | 4 + lib/AST/CommentLexer.cpp | 4 +- lib/AST/Decl.cpp | 159 +- lib/AST/DeclBase.cpp | 28 +- lib/AST/DeclCXX.cpp | 94 +- lib/AST/DeclObjC.cpp | 66 +- lib/AST/DeclPrinter.cpp | 57 +- lib/AST/Expr.cpp | 205 +- lib/AST/ExprCXX.cpp | 16 +- lib/AST/ExprClassification.cpp | 11 +- lib/AST/ExprConstant.cpp | 579 ++++- lib/AST/ItaniumCXXABI.cpp | 54 +- lib/AST/ItaniumMangle.cpp | 187 +- lib/AST/Mangle.cpp | 92 +- lib/AST/MangleNumberingContext.cpp | 45 - lib/AST/MicrosoftCXXABI.cpp | 21 + lib/AST/MicrosoftMangle.cpp | 174 +- lib/AST/NSAPI.cpp | 31 + lib/AST/NestedNameSpecifier.cpp | 71 +- lib/AST/RecordLayoutBuilder.cpp | 120 +- lib/AST/Stmt.cpp | 454 +++- lib/AST/StmtPrinter.cpp | 91 +- lib/AST/StmtProfile.cpp | 76 +- lib/AST/TemplateBase.cpp | 28 +- lib/AST/Type.cpp | 143 +- lib/AST/TypeLoc.cpp | 8 + lib/AST/TypePrinter.cpp | 19 +- lib/AST/VTTBuilder.cpp | 4 +- lib/AST/VTableBuilder.cpp | 334 ++- lib/ASTMatchers/ASTMatchFinder.cpp | 289 ++- lib/ASTMatchers/ASTMatchersInternal.cpp | 268 ++- lib/ASTMatchers/Dynamic/Marshallers.h | 105 +- lib/ASTMatchers/Dynamic/Parser.cpp | 105 +- lib/ASTMatchers/Dynamic/Registry.cpp | 171 +- lib/ASTMatchers/Dynamic/VariantValue.cpp | 164 +- lib/Analysis/AnalysisDeclContext.cpp | 29 +- lib/Analysis/BodyFarm.cpp | 12 +- lib/Analysis/BodyFarm.h | 8 +- lib/Analysis/CFG.cpp | 354 +-- lib/Analysis/CMakeLists.txt | 1 + lib/Analysis/CallGraph.cpp | 13 +- lib/Analysis/CodeInjector.cpp | 15 + lib/Analysis/FormatString.cpp | 38 +- lib/Analysis/FormatStringParsing.h | 4 +- lib/Analysis/LiveVariables.cpp | 1 - lib/Analysis/PrintfFormatString.cpp | 78 +- lib/Analysis/ReachableCode.cpp | 4 +- lib/Analysis/ScanfFormatString.cpp | 11 + lib/Analysis/ThreadSafety.cpp | 1436 +++++------- lib/Analysis/ThreadSafetyCommon.cpp | 335 ++- lib/Analysis/ThreadSafetyTIL.cpp | 280 ++- lib/Analysis/UninitializedValues.cpp | 32 +- lib/Basic/Attributes.cpp | 4 +- lib/Basic/CMakeLists.txt | 80 +- lib/Basic/Diagnostic.cpp | 42 +- lib/Basic/DiagnosticIDs.cpp | 31 +- lib/Basic/FileManager.cpp | 192 +- lib/Basic/FileSystemStatCache.cpp | 9 +- lib/Basic/IdentifierTable.cpp | 119 +- lib/Basic/LangOptions.cpp | 8 +- lib/Basic/Module.cpp | 58 +- lib/Basic/OpenMPKinds.cpp | 82 +- lib/Basic/SanitizerBlacklist.cpp | 46 + lib/Basic/Sanitizers.cpp | 35 + lib/Basic/SourceLocation.cpp | 8 +- lib/Basic/SourceManager.cpp | 67 +- lib/Basic/TargetInfo.cpp | 37 +- lib/Basic/Targets.cpp | 1116 +++++++--- lib/Basic/Version.cpp | 2 +- lib/Basic/VersionTuple.cpp | 4 +- lib/Basic/VirtualFileSystem.cpp | 100 +- lib/CodeGen/ABIInfo.h | 23 +- lib/CodeGen/BackendUtil.cpp | 88 +- lib/CodeGen/CGAtomic.cpp | 328 ++- lib/CodeGen/CGBlocks.cpp | 48 +- lib/CodeGen/CGBlocks.h | 4 +- lib/CodeGen/CGBuilder.h | 6 +- lib/CodeGen/CGBuiltin.cpp | 530 ++++- lib/CodeGen/CGCUDARuntime.cpp | 3 +- lib/CodeGen/CGCUDARuntime.h | 4 +- lib/CodeGen/CGCXX.cpp | 157 +- lib/CodeGen/CGCXXABI.cpp | 23 - lib/CodeGen/CGCXXABI.h | 102 +- lib/CodeGen/CGCall.cpp | 1512 ++++++++----- lib/CodeGen/CGCall.h | 4 +- lib/CodeGen/CGClass.cpp | 263 ++- lib/CodeGen/CGCleanup.cpp | 12 +- lib/CodeGen/CGCleanup.h | 12 +- lib/CodeGen/CGDebugInfo.cpp | 1569 ++++++------- lib/CodeGen/CGDebugInfo.h | 136 +- lib/CodeGen/CGDecl.cpp | 141 +- lib/CodeGen/CGDeclCXX.cpp | 154 +- lib/CodeGen/CGException.cpp | 106 +- lib/CodeGen/CGExpr.cpp | 547 +++-- lib/CodeGen/CGExprCXX.cpp | 301 +-- lib/CodeGen/CGExprComplex.cpp | 271 ++- lib/CodeGen/CGExprConstant.cpp | 202 +- lib/CodeGen/CGExprScalar.cpp | 240 +- lib/CodeGen/CGLoopInfo.cpp | 27 +- lib/CodeGen/CGLoopInfo.h | 6 +- lib/CodeGen/CGObjC.cpp | 43 +- lib/CodeGen/CGObjCGNU.cpp | 31 +- lib/CodeGen/CGObjCMac.cpp | 424 ++-- lib/CodeGen/CGObjCRuntime.h | 4 +- lib/CodeGen/CGOpenCLRuntime.h | 4 +- lib/CodeGen/CGOpenMPRuntime.cpp | 794 ++++++- lib/CodeGen/CGOpenMPRuntime.h | 315 ++- lib/CodeGen/CGRecordLayout.h | 4 +- lib/CodeGen/CGRecordLayoutBuilder.cpp | 59 +- lib/CodeGen/CGStmt.cpp | 196 +- lib/CodeGen/CGStmtOpenMP.cpp | 639 +++++- lib/CodeGen/CGVTables.cpp | 126 +- lib/CodeGen/CGVTables.h | 4 +- lib/CodeGen/CGValue.h | 4 +- lib/CodeGen/CMakeLists.txt | 15 +- lib/CodeGen/CodeGenABITypes.cpp | 9 +- lib/CodeGen/CodeGenAction.cpp | 89 +- lib/CodeGen/CodeGenFunction.cpp | 232 +- lib/CodeGen/CodeGenFunction.h | 396 ++-- lib/CodeGen/CodeGenModule.cpp | 668 ++++-- lib/CodeGen/CodeGenModule.h | 194 +- lib/CodeGen/CodeGenPGO.cpp | 364 +-- lib/CodeGen/CodeGenPGO.h | 48 +- lib/CodeGen/CodeGenTBAA.h | 4 +- lib/CodeGen/CodeGenTypes.cpp | 30 +- lib/CodeGen/CodeGenTypes.h | 140 +- lib/CodeGen/CoverageMappingGen.cpp | 1174 ++++++++++ lib/CodeGen/CoverageMappingGen.h | 114 + lib/CodeGen/EHScopeStack.h | 6 +- lib/CodeGen/ItaniumCXXABI.cpp | 400 +++- lib/CodeGen/MicrosoftCXXABI.cpp | 457 ++-- lib/CodeGen/ModuleBuilder.cpp | 66 +- lib/CodeGen/SanitizerBlacklist.cpp | 52 - lib/CodeGen/SanitizerBlacklist.h | 46 - lib/CodeGen/SanitizerMetadata.cpp | 92 + lib/CodeGen/SanitizerMetadata.h | 53 + lib/CodeGen/TargetInfo.cpp | 1110 ++++++---- lib/CodeGen/TargetInfo.h | 22 +- lib/Driver/Action.cpp | 74 +- lib/Driver/CMakeLists.txt | 3 +- lib/Driver/Compilation.cpp | 19 +- lib/Driver/CrossWindowsToolChain.cpp | 117 + lib/Driver/Driver.cpp | 506 +++-- lib/Driver/InputInfo.h | 4 +- lib/Driver/Job.cpp | 187 +- lib/Driver/MSVCToolChain.cpp | 496 +++++ lib/Driver/Multilib.cpp | 2 +- lib/Driver/Phases.cpp | 1 + lib/Driver/SanitizerArgs.cpp | 524 +++-- lib/Driver/Tool.cpp | 12 +- lib/Driver/ToolChain.cpp | 36 +- lib/Driver/ToolChains.cpp | 594 ++--- lib/Driver/ToolChains.h | 93 +- lib/Driver/Tools.cpp | 1650 ++++++++------ lib/Driver/Tools.h | 180 +- lib/Driver/Types.cpp | 2 + lib/Driver/WindowsToolChain.cpp | 338 --- lib/Edit/EditedSource.cpp | 6 + lib/Edit/RewriteObjCFoundationAPI.cpp | 3 +- lib/Format/BreakableToken.cpp | 3 +- lib/Format/BreakableToken.h | 11 +- lib/Format/CMakeLists.txt | 3 +- lib/Format/ContinuationIndenter.cpp | 465 ++-- lib/Format/ContinuationIndenter.h | 34 +- lib/Format/Encoding.h | 6 +- lib/Format/Format.cpp | 975 ++------ lib/Format/FormatToken.cpp | 24 +- lib/Format/FormatToken.h | 150 +- lib/Format/TokenAnnotator.cpp | 1041 +++++---- lib/Format/TokenAnnotator.h | 22 +- lib/Format/UnwrappedLineFormatter.cpp | 706 ++++++ lib/Format/UnwrappedLineFormatter.h | 168 ++ lib/Format/UnwrappedLineParser.cpp | 244 +- lib/Format/UnwrappedLineParser.h | 14 +- lib/Format/WhitespaceManager.cpp | 12 +- lib/Format/WhitespaceManager.h | 6 +- lib/Frontend/ASTConsumers.cpp | 40 +- lib/Frontend/ASTMerge.cpp | 10 +- lib/Frontend/ASTUnit.cpp | 355 ++- lib/Frontend/CMakeLists.txt | 3 + lib/Frontend/CacheTokens.cpp | 16 +- lib/Frontend/ChainedIncludesSource.cpp | 33 +- lib/Frontend/CodeGenOptions.cpp | 24 + lib/Frontend/CompilerInstance.cpp | 268 ++- lib/Frontend/CompilerInvocation.cpp | 207 +- lib/Frontend/CreateInvocationFromCommandLine.cpp | 6 +- lib/Frontend/DependencyFile.cpp | 36 +- lib/Frontend/DependencyGraph.cpp | 13 +- lib/Frontend/DiagnosticRenderer.cpp | 4 +- lib/Frontend/FrontendAction.cpp | 80 +- lib/Frontend/FrontendActions.cpp | 168 +- lib/Frontend/HeaderIncludeGen.cpp | 20 +- lib/Frontend/InitHeaderSearch.cpp | 16 +- lib/Frontend/InitPreprocessor.cpp | 166 +- lib/Frontend/LogDiagnosticPrinter.cpp | 26 +- lib/Frontend/ModuleDependencyCollector.cpp | 43 +- lib/Frontend/MultiplexConsumer.cpp | 117 +- lib/Frontend/PrintPreprocessedOutput.cpp | 5 +- lib/Frontend/Rewrite/FixItRewriter.cpp | 26 +- lib/Frontend/Rewrite/FrontendActions.cpp | 14 +- lib/Frontend/Rewrite/HTMLPrint.cpp | 11 +- lib/Frontend/Rewrite/InclusionRewriter.cpp | 153 +- lib/Frontend/Rewrite/RewriteModernObjC.cpp | 102 +- lib/Frontend/Rewrite/RewriteObjC.cpp | 102 +- lib/Frontend/SerializedDiagnosticPrinter.cpp | 257 ++- lib/Frontend/SerializedDiagnosticReader.cpp | 295 +++ lib/Frontend/TextDiagnostic.cpp | 24 +- lib/Frontend/VerifyDiagnosticConsumer.cpp | 69 +- lib/FrontendTool/ExecuteCompilerInvocation.cpp | 2 +- lib/Headers/CMakeLists.txt | 23 +- lib/Headers/Intrin.h | 88 +- lib/Headers/__stddef_max_align_t.h | 40 + lib/Headers/adxintrin.h | 83 + lib/Headers/altivec.h | 411 +++- lib/Headers/arm_acle.h | 113 +- lib/Headers/avx512bwintrin.h | 60 + lib/Headers/avx512erintrin.h | 112 + lib/Headers/avx512fintrin.h | 1036 +++++++++ lib/Headers/avx512vlbwintrin.h | 83 + lib/Headers/avx512vlintrin.h | 83 + lib/Headers/bmiintrin.h | 6 +- lib/Headers/cpuid.h | 84 +- lib/Headers/emmintrin.h | 48 +- lib/Headers/float.h | 2 +- lib/Headers/immintrin.h | 76 + lib/Headers/lzcntintrin.h | 18 +- lib/Headers/module.modulemap | 22 +- lib/Headers/shaintrin.h | 12 +- lib/Headers/stdatomic.h | 190 ++ lib/Headers/stddef.h | 29 +- lib/Headers/unwind.h | 6 +- lib/Headers/vadefs.h | 65 + lib/Headers/xmmintrin.h | 48 +- lib/Index/CMakeLists.txt | 3 +- lib/Index/CommentToXML.cpp | 10 +- lib/Index/SimpleFormatContext.h | 9 +- lib/Index/USRGeneration.cpp | 54 +- lib/Lex/HeaderMap.cpp | 10 +- lib/Lex/HeaderSearch.cpp | 302 +-- lib/Lex/Lexer.cpp | 48 +- lib/Lex/LiteralSupport.cpp | 16 +- lib/Lex/MacroArgs.cpp | 5 +- lib/Lex/ModuleMap.cpp | 408 ++-- lib/Lex/PPDirectives.cpp | 339 ++- lib/Lex/PPExpressions.cpp | 22 +- lib/Lex/PPLexerChange.cpp | 68 +- lib/Lex/PPMacroExpansion.cpp | 357 +-- lib/Lex/PTHLexer.cpp | 74 +- lib/Lex/Pragma.cpp | 23 +- lib/Lex/Preprocessor.cpp | 114 +- lib/Lex/ScratchBuffer.cpp | 9 +- lib/Lex/TokenConcatenation.cpp | 20 +- lib/Lex/TokenLexer.cpp | 29 +- lib/Lex/UnicodeCharSets.h | 4 +- lib/Parse/ParseAST.cpp | 7 +- lib/Parse/ParseCXXInlineMethods.cpp | 203 +- lib/Parse/ParseDecl.cpp | 460 +++- lib/Parse/ParseDeclCXX.cpp | 362 ++- lib/Parse/ParseExpr.cpp | 260 ++- lib/Parse/ParseExprCXX.cpp | 198 +- lib/Parse/ParseInit.cpp | 6 +- lib/Parse/ParseObjc.cpp | 164 +- lib/Parse/ParseOpenMP.cpp | 71 +- lib/Parse/ParsePragma.cpp | 313 ++- lib/Parse/ParseStmt.cpp | 83 +- lib/Parse/ParseStmtAsm.cpp | 61 +- lib/Parse/ParseTemplate.cpp | 25 +- lib/Parse/ParseTentative.cpp | 37 +- lib/Parse/Parser.cpp | 127 +- lib/Parse/RAIIObjectsForParser.h | 4 +- lib/Rewrite/CMakeLists.txt | 1 - lib/Rewrite/RewriteRope.cpp | 14 +- lib/Rewrite/Rewriter.cpp | 33 +- lib/Sema/AnalysisBasedWarnings.cpp | 191 +- lib/Sema/AttributeList.cpp | 8 + lib/Sema/CMakeLists.txt | 1 + lib/Sema/DeclSpec.cpp | 49 +- lib/Sema/IdentifierResolver.cpp | 3 + lib/Sema/JumpDiagnostics.cpp | 22 +- lib/Sema/MultiplexExternalSemaSource.cpp | 6 + lib/Sema/Scope.cpp | 9 +- lib/Sema/ScopeInfo.cpp | 19 + lib/Sema/Sema.cpp | 52 +- lib/Sema/SemaAccess.cpp | 4 +- lib/Sema/SemaAttr.cpp | 26 +- lib/Sema/SemaCUDA.cpp | 263 +++ lib/Sema/SemaCXXScopeSpec.cpp | 65 +- lib/Sema/SemaCast.cpp | 54 +- lib/Sema/SemaChecking.cpp | 716 +++++- lib/Sema/SemaCodeComplete.cpp | 111 +- lib/Sema/SemaDecl.cpp | 784 +++++-- lib/Sema/SemaDeclAttr.cpp | 823 ++++--- lib/Sema/SemaDeclCXX.cpp | 1207 +++++++--- lib/Sema/SemaDeclObjC.cpp | 184 +- lib/Sema/SemaExceptionSpec.cpp | 117 +- lib/Sema/SemaExpr.cpp | 798 ++++--- lib/Sema/SemaExprCXX.cpp | 411 +++- lib/Sema/SemaExprMember.cpp | 132 +- lib/Sema/SemaExprObjC.cpp | 172 +- lib/Sema/SemaInit.cpp | 198 +- lib/Sema/SemaLambda.cpp | 27 +- lib/Sema/SemaLookup.cpp | 759 +++---- lib/Sema/SemaObjCProperty.cpp | 52 +- lib/Sema/SemaOpenMP.cpp | 1694 ++++++++++++-- lib/Sema/SemaOverload.cpp | 616 ++++-- lib/Sema/SemaPseudoObject.cpp | 9 +- lib/Sema/SemaStmt.cpp | 448 ++-- lib/Sema/SemaStmtAsm.cpp | 200 +- lib/Sema/SemaStmtAttr.cpp | 128 +- lib/Sema/SemaTemplate.cpp | 244 +- lib/Sema/SemaTemplateDeduction.cpp | 65 +- lib/Sema/SemaTemplateInstantiate.cpp | 248 ++- lib/Sema/SemaTemplateInstantiateDecl.cpp | 470 ++-- lib/Sema/SemaTemplateVariadic.cpp | 167 +- lib/Sema/SemaType.cpp | 215 +- lib/Sema/TreeTransform.h | 662 ++++-- lib/Sema/TypeLocBuilder.h | 4 +- lib/Serialization/ASTCommon.cpp | 18 +- lib/Serialization/ASTCommon.h | 13 +- lib/Serialization/ASTReader.cpp | 1341 ++++++----- lib/Serialization/ASTReaderDecl.cpp | 630 ++++-- lib/Serialization/ASTReaderInternals.h | 11 +- lib/Serialization/ASTReaderStmt.cpp | 195 +- lib/Serialization/ASTWriter.cpp | 883 +++++--- lib/Serialization/ASTWriterDecl.cpp | 160 +- lib/Serialization/ASTWriterStmt.cpp | 140 +- lib/Serialization/GlobalModuleIndex.cpp | 25 +- lib/Serialization/Module.cpp | 2 +- lib/Serialization/ModuleManager.cpp | 84 +- .../Checkers/AllocationDiagnostics.h | 4 +- .../Checkers/ArrayBoundCheckerV2.cpp | 13 +- .../Checkers/BuiltinFunctionChecker.cpp | 4 +- lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 7 +- lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp | 39 - lib/StaticAnalyzer/Checkers/Checkers.td | 8 +- lib/StaticAnalyzer/Checkers/ClangSACheckers.h | 4 +- .../Checkers/IdenticalExprChecker.cpp | 9 +- lib/StaticAnalyzer/Checkers/InterCheckerAPI.h | 4 +- .../Checkers/MacOSKeychainAPIChecker.cpp | 8 +- lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 186 +- .../Checkers/MallocSizeofChecker.cpp | 4 + .../Checkers/NonNullParamChecker.cpp | 19 +- lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 49 +- lib/StaticAnalyzer/Checkers/SelectorExtras.h | 8 +- .../Checkers/SimpleStreamChecker.cpp | 14 +- .../Checkers/TestAfterDivZeroChecker.cpp | 3 +- .../Checkers/UndefCapturedBlockVarChecker.cpp | 4 +- lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp | 66 +- lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp | 26 +- lib/StaticAnalyzer/Checkers/VirtualCallChecker.cpp | 13 +- lib/StaticAnalyzer/Core/AnalysisManager.cpp | 7 +- lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 19 +- lib/StaticAnalyzer/Core/BugReporter.cpp | 135 +- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 74 +- lib/StaticAnalyzer/Core/CallEvent.cpp | 2 +- lib/StaticAnalyzer/Core/CoreEngine.cpp | 67 +- lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 15 +- lib/StaticAnalyzer/Core/ExprEngine.cpp | 125 +- lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp | 2 +- lib/StaticAnalyzer/Core/MemRegion.cpp | 15 +- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 11 +- lib/StaticAnalyzer/Core/PlistDiagnostics.cpp | 10 +- .../Core/PrettyStackTraceLocationContext.h | 4 +- lib/StaticAnalyzer/Core/ProgramState.cpp | 4 +- lib/StaticAnalyzer/Core/RangeConstraintManager.cpp | 4 +- lib/StaticAnalyzer/Core/RegionStore.cpp | 11 +- lib/StaticAnalyzer/Core/SimpleConstraintManager.h | 4 +- lib/StaticAnalyzer/Core/Store.cpp | 13 +- lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp | 62 +- lib/StaticAnalyzer/Frontend/CMakeLists.txt | 3 + .../Frontend/CheckerRegistration.cpp | 16 +- lib/StaticAnalyzer/Frontend/FrontendActions.cpp | 19 +- lib/StaticAnalyzer/Frontend/ModelConsumer.cpp | 42 + lib/StaticAnalyzer/Frontend/ModelInjector.cpp | 117 + lib/StaticAnalyzer/Frontend/ModelInjector.h | 74 + lib/Tooling/ArgumentsAdjusters.cpp | 83 +- lib/Tooling/CMakeLists.txt | 3 + lib/Tooling/CommonOptionsParser.cpp | 63 +- lib/Tooling/CompilationDatabase.cpp | 38 +- lib/Tooling/Core/CMakeLists.txt | 10 + lib/Tooling/Core/Makefile | 13 + lib/Tooling/Core/Replacement.cpp | 289 +++ lib/Tooling/JSONCompilationDatabase.cpp | 18 +- lib/Tooling/Makefile | 1 + lib/Tooling/Refactoring.cpp | 246 -- lib/Tooling/Tooling.cpp | 162 +- runtime/CMakeLists.txt | 4 +- runtime/compiler-rt/Makefile | 42 +- test/ARCMT/checking.m | 4 +- test/ARCMT/objcmt-boxing.m | 7 +- test/ARCMT/objcmt-boxing.m.result | 7 +- test/ARCMT/objcmt-ns-macros.m | 69 + test/ARCMT/objcmt-ns-macros.m.result | 109 +- test/ARCMT/objcmt-property-dot-syntax.m | 61 + test/ARCMT/objcmt-property-dot-syntax.m.result | 61 + test/ARCMT/objcmt-undefined-ns-macros.m | 24 + test/ARCMT/objcmt-undefined-ns-macros.m.result | 26 + test/Analysis/Inputs/Models/modeledFunction.model | 3 + test/Analysis/Inputs/Models/notzero.model | 3 + .../system-header-simulator-for-pthread-lock.h | 28 + .../Malloc+MismatchedDeallocator+NewDelete.cpp | 2 +- test/Analysis/Malloc+NewDelete_intersections.cpp | 2 +- test/Analysis/NSContainers.m | 2 +- ...wDelete+MismatchedDeallocator_intersections.cpp | 2 +- test/Analysis/NewDelete-checker-test.cpp | 2 +- test/Analysis/NewDelete-custom.cpp | 2 +- test/Analysis/NewDelete-intersections.mm | 2 +- test/Analysis/NewDelete-variadic.cpp | 2 +- test/Analysis/NewDeleteLeaks-PR18394.cpp | 2 +- test/Analysis/NewDeleteLeaks-PR19102.cpp | 43 + test/Analysis/bstring.c | 39 + test/Analysis/builtin-functions.cpp | 28 + test/Analysis/cfg.cpp | 57 +- test/Analysis/debug-CallGraph.c | 23 +- test/Analysis/disable-all-checks.c | 11 + test/Analysis/identical-expressions.cpp | 21 +- test/Analysis/logical-ops.c | 2 +- test/Analysis/malloc-protoype.c | 17 + test/Analysis/malloc-sizeof.cpp | 26 + test/Analysis/misc-ps.m | 13 - test/Analysis/model-file.cpp | 288 +++ test/Analysis/nonnull.m | 118 + test/Analysis/objc-boxing.m | 2 +- test/Analysis/pthreadlock.c | 40 +- test/Analysis/temp-obj-dtors-cfg-output.cpp | 103 +- test/Analysis/temporaries.cpp | 207 +- test/Analysis/unix-api.c | 75 + test/Analysis/virtualcall.cpp | 23 +- test/Analysis/vla.c | 86 + test/CXX/basic/basic.types/p10.cpp | 11 +- test/CXX/class.access/class.friend/p11.cpp | 10 +- test/CXX/class/class.mem/p2.cpp | 30 + .../basic.namespace/namespace.udecl/p8-cxx0x.cpp | 5 + .../dcl.dcl/dcl.attr/dcl.attr.deprecated/p1.cpp | 3 +- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp | 4 +- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 32 +- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p4.cpp | 12 +- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p5.cpp | 2 +- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp | 16 +- test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp | 4 +- test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp | 2 +- .../dcl.fct.def/dcl.fct.def.default/p2.cpp | 4 +- .../dcl.fct.def/dcl.fct.def.general/p8.cpp | 18 + test/CXX/dcl.decl/dcl.init/dcl.init.list/p3-0x.cpp | 15 +- .../dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp | 2 +- test/CXX/dcl.decl/dcl.init/p6.cpp | 6 +- test/CXX/dcl.decl/dcl.meaning/dcl.fct/p13.cpp | 31 + test/CXX/dcl.decl/dcl.meaning/dcl.fct/p14.cpp | 3 +- test/CXX/dcl.decl/dcl.meaning/p1.cpp | 4 + test/CXX/drs/dr0xx.cpp | 40 +- test/CXX/drs/dr10xx.cpp | 21 +- test/CXX/drs/dr13xx.cpp | 3 +- test/CXX/drs/dr14xx.cpp | 3 +- test/CXX/drs/dr15xx.cpp | 7 +- test/CXX/drs/dr16xx.cpp | 19 + test/CXX/drs/dr18xx.cpp | 24 + test/CXX/drs/dr1xx.cpp | 7 +- test/CXX/drs/dr2xx.cpp | 46 +- test/CXX/drs/dr3xx.cpp | 40 +- test/CXX/drs/dr412.cpp | 3 +- test/CXX/drs/dr4xx.cpp | 19 +- test/CXX/drs/dr5xx.cpp | 785 ++++++- test/CXX/drs/dr6xx.cpp | 349 +++ test/CXX/drs/dr9xx.cpp | 3 +- test/CXX/except/except.spec/p1.cpp | 9 +- test/CXX/except/except.spec/p5-delayed.cpp | 15 + test/CXX/expr/expr.const/p2-0x.cpp | 8 +- .../CXX/expr/expr.prim/expr.prim.general/p3-0x.cpp | 5 +- test/CXX/expr/expr.prim/expr.prim.lambda/p19.cpp | 4 +- .../expr.prim.lambda/p2-generic-lambda-1y.cpp | 2 +- test/CXX/expr/expr.prim/expr.prim.lambda/p2.cpp | 2 +- test/CXX/expr/expr.prim/expr.prim.lambda/p3.cpp | 7 +- test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp | 7 +- .../expr/expr.prim/expr.prim.lambda/templates.cpp | 4 +- .../expr/expr.unary/expr.unary.noexcept/sema.cpp | 2 +- test/CXX/lex/lex.literal/lex.ext/p3.cpp | 2 +- test/CXX/lex/lex.trigraph/p1.cpp | 2 +- test/CXX/lex/lex.trigraph/p2.cpp | 2 +- test/CXX/lex/lex.trigraph/p3.cpp | 2 +- test/CXX/stmt.stmt/stmt.dcl/p3-0x.cpp | 4 +- test/CXX/stmt.stmt/stmt.dcl/p3.cpp | 4 +- .../temp/temp.decls/temp.class/temp.static/p1.cpp | 8 +- test/CXX/temp/temp.decls/temp.friend/p5.cpp | 8 +- .../temp.decls/temp.variadic/metafunctions.cpp | 2 +- test/CXX/temp/temp.decls/temp.variadic/p5.cpp | 15 + test/CXX/temp/temp.param/p5.cpp | 8 +- test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp | 2 +- test/CodeGen/2003-08-21-WideString.c | 4 +- .../CodeGen/2005-06-15-ExpandGotoInternalProblem.c | 2 +- test/CodeGen/2005-09-24-AsmUserPrefix.c | 2 +- test/CodeGen/2007-06-18-SextAttrAggregate.c | 4 +- ...2008-07-22-bitfield-init-after-zero-len-array.c | 3 +- test/CodeGen/2009-07-15-pad-wchar_t-array.c | 4 +- test/CodeGen/2009-10-20-GlobalDebug.c | 4 +- test/CodeGen/2010-02-15-DbgStaticVar.c | 3 +- test/CodeGen/2010-07-08-DeclDebugLineNo.c | 4 +- test/CodeGen/24-bit.c | 14 + test/CodeGen/Atomics.c | 43 + test/CodeGen/aarch64-fix-cortex-a53-835769.c | 27 + test/CodeGen/aarch64-poly64.c | 12 + test/CodeGen/aarch64-type-sizes.c | 2 +- test/CodeGen/aarch64-varargs.c | 2 +- test/CodeGen/adc-builtins.c | 33 + test/CodeGen/address-safety-attr.cpp | 70 +- .../CodeGen/address-sanitizer-and-array-cookie.cpp | 55 + test/CodeGen/adx-builtins.c | 18 + test/CodeGen/alias.c | 7 +- test/CodeGen/align_value.cpp | 103 + test/CodeGen/arm-aapcs-vfp.c | 25 +- test/CodeGen/arm-arguments.c | 9 +- test/CodeGen/arm-homogenous.c | 20 +- test/CodeGen/arm-metadata.c | 12 +- test/CodeGen/arm-neon-directed-rounding.c | 75 + test/CodeGen/arm-neon-numeric-maxmin.c | 27 + test/CodeGen/arm64-aapcs-arguments.c | 15 +- test/CodeGen/arm64-arguments.c | 15 +- test/CodeGen/arm64-be-bitfield.c | 12 +- test/CodeGen/arm64-be-hfa-vararg.c | 2 +- test/CodeGen/arm64-lanes.c | 2 +- test/CodeGen/arm_acle.c | 155 +- test/CodeGen/arm_neon_intrinsics.c | 168 +- test/CodeGen/asan-globals.cpp | 45 +- test/CodeGen/asm.c | 14 + test/CodeGen/atomic-ops-libcall.c | 10 +- test/CodeGen/atomic-ops.c | 178 +- test/CodeGen/atomic.c | 10 +- test/CodeGen/atomic_ops.c | 6 +- test/CodeGen/atomics-inlining.c | 24 +- test/CodeGen/attr-naked.c | 10 +- test/CodeGen/attr-optnone.c | 21 +- test/CodeGen/attributes.c | 2 +- test/CodeGen/avx2-builtins.c | 2 +- test/CodeGen/avx512bw-builtins.c | 27 + test/CodeGen/avx512f-builtins.c | 212 ++ test/CodeGen/avx512vl-builtins.c | 51 + test/CodeGen/avx512vlbw-builtins.c | 51 + test/CodeGen/block-with-perdefinedexpr.c | 14 + test/CodeGen/bmi2-builtins.c | 6 +- test/CodeGen/bool_test.c | 2 +- test/CodeGen/builtin-assume-aligned.c | 67 + test/CodeGen/builtin-assume.c | 23 +- test/CodeGen/builtin-recursive.cc | 10 - test/CodeGen/builtin-recursive.cpp | 10 + test/CodeGen/builtins-arm-msvc-compat-error.c | 6 + test/CodeGen/builtins-arm-msvc-compat-only.c | 19 + test/CodeGen/builtins-arm.c | 18 + test/CodeGen/builtins-arm64.c | 14 + test/CodeGen/builtins-nvptx.c | 2 + test/CodeGen/builtins-ppc-altivec.c | 4 +- test/CodeGen/builtins-ppc-vsx.c | 116 + test/CodeGen/builtins-x86.c | 2 +- test/CodeGen/builtins.c | 33 +- test/CodeGen/c11atomics-ios.c | 8 +- test/CodeGen/c11atomics.c | 14 +- test/CodeGen/captured-statements-nested.c | 74 +- test/CodeGen/captured-statements.c | 11 +- test/CodeGen/catch-undef-behavior.c | 417 ++-- test/CodeGen/complex-math.c | 481 ++++ test/CodeGen/complex.c | 16 + test/CodeGen/compound-assign-overflow.c | 2 +- test/CodeGen/const-init.c | 22 + test/CodeGen/debug-info-args.c | 4 +- test/CodeGen/debug-info-block-decl.c | 4 +- test/CodeGen/debug-info-block-out-return.c | 25 + test/CodeGen/debug-info-enum.c | 6 +- test/CodeGen/debug-info-line3.c | 2 +- test/CodeGen/debug-info-line4.c | 2 +- test/CodeGen/debug-info-scope-file.c | 4 +- test/CodeGen/debug-info-scope.c | 12 + test/CodeGen/debug-info-typedef.c | 4 +- test/CodeGen/debug-info-version.c | 4 +- test/CodeGen/debug-info-vla.c | 2 +- test/CodeGen/debug-info.c | 2 +- test/CodeGen/dependent-lib.c | 12 +- test/CodeGen/designated-initializers.c | 3 + test/CodeGen/dllimport.c | 56 +- test/CodeGen/dwarf-version.c | 7 +- test/CodeGen/ext-vector-indexing.c | 14 + test/CodeGen/fp128_complex.c | 9 + test/CodeGen/fsgsbase-builtins.c | 54 + test/CodeGen/lineno-dbginfo.c | 7 +- test/CodeGen/linetable-endscope.c | 4 +- test/CodeGen/link-bitcode-file.c | 2 +- test/CodeGen/lzcnt-builtins.c | 12 + test/CodeGen/mangle-blocks.c | 23 + test/CodeGen/mangle-windows.c | 39 +- test/CodeGen/may-alias.c | 24 +- test/CodeGen/merge-statics.c | 5 +- test/CodeGen/microsoft-call-conv.c | 12 +- test/CodeGen/mips-constraint-regs.c | 6 +- test/CodeGen/mips-constraints-mem.c | 2 +- test/CodeGen/mips-inline-asm-modifiers.c | 6 +- test/CodeGen/mips-transparent-union.c | 27 + test/CodeGen/mips-varargs.c | 115 +- test/CodeGen/mmx-inline-asm-error.c | 6 +- test/CodeGen/mozilla-ms-inline-asm.c | 17 +- test/CodeGen/mrtd.c | 4 +- test/CodeGen/ms-align-tentative.c | 15 + test/CodeGen/ms-declspecs.c | 4 +- test/CodeGen/ms-inline-asm-functions.c | 60 + test/CodeGen/ms-inline-asm.c | 317 +-- test/CodeGen/ms-inline-asm.cpp | 46 +- test/CodeGen/ms-intrinsics.c | 59 +- test/CodeGen/mult-alt-generic.c | 2 +- test/CodeGen/named_reg_global.c | 2 +- test/CodeGen/nonnull.c | 28 + test/CodeGen/nvptx-abi.c | 34 +- test/CodeGen/piclevels.c | 7 + test/CodeGen/ppc-signbit.c | 11 + test/CodeGen/ppc-varargs-struct.c | 112 + test/CodeGen/ppc64-elf-abi.c | 40 + test/CodeGen/ppc64-varargs-struct.c | 30 - test/CodeGen/ppc64le-aggregates.c | 6 +- test/CodeGen/pr5406.c | 2 +- test/CodeGen/pragma-comment.c | 20 +- test/CodeGen/pragma-detect_mismatch.c | 24 +- test/CodeGen/pragma-loop.cpp | 120 +- test/CodeGen/pragma-unroll.cpp | 24 +- test/CodeGen/pragma-weak.c | 20 +- test/CodeGen/predefined-expr.c | 4 +- test/CodeGen/sanitize-address-field-padding.cpp | 237 ++ test/CodeGen/sanitize-init-order.cpp | 34 +- test/CodeGen/sanitize-recover.c | 28 +- test/CodeGen/sections.c | 51 - test/CodeGen/sse-builtins.c | 288 +++ test/CodeGen/target-data.c | 12 +- test/CodeGen/tbaa-class.cpp | 56 +- test/CodeGen/tbaa-for-vptr.cpp | 6 +- test/CodeGen/tbaa-ms-abi.cpp | 8 +- test/CodeGen/tbaa-struct.cpp | 18 +- test/CodeGen/tbaa.cpp | 66 +- test/CodeGen/transparent-union.c | 19 +- test/CodeGen/ubsan-type-blacklist.cpp | 6 +- test/CodeGen/variadic-null-win64.c | 17 + test/CodeGen/vectorcall.c | 77 + test/CodeGen/vlt_to_pointer.c | 30 + test/CodeGen/wchar-const.c | 4 +- test/CodeGen/windows-struct-abi.c | 42 + test/CodeGen/x86-atomic-long_double.c | 469 ++++ test/CodeGen/x86_32-inline-asm.c | 48 + test/CodeGen/x86_64-arguments-win32.c | 16 + test/CodeGen/xcore-stringtype.c | 102 +- test/CodeGenCUDA/launch-bounds.cu | 6 +- test/CodeGenCUDA/ptx-kernels.cu | 2 +- test/CodeGenCXX/2010-07-23-DeclLoc.cpp | 2 +- test/CodeGenCXX/PR20038.cpp | 8 +- test/CodeGenCXX/align-avx-complete-objects.cpp | 57 + test/CodeGenCXX/atomicinit.cpp | 12 +- test/CodeGenCXX/attr-used.cpp | 10 +- test/CodeGenCXX/call-with-static-chain.cpp | 39 + test/CodeGenCXX/catch-undef-behavior.cpp | 49 +- test/CodeGenCXX/class-layout.cpp | 2 +- test/CodeGenCXX/compound-literals.cpp | 15 +- .../constructor-destructor-return-this.cpp | 14 +- test/CodeGenCXX/constructor-init.cpp | 12 +- test/CodeGenCXX/copy-constructor-synthesis-2.cpp | 2 +- test/CodeGenCXX/copy-constructor-synthesis.cpp | 4 +- test/CodeGenCXX/coverage.cpp | 4 +- test/CodeGenCXX/crash.cpp | 11 + test/CodeGenCXX/ctor-dtor-alias.cpp | 107 +- test/CodeGenCXX/ctor-globalopt.cpp | 28 + test/CodeGenCXX/cxx11-exception-spec.cpp | 21 +- test/CodeGenCXX/cxx11-special-members.cpp | 14 + test/CodeGenCXX/cxx11-thread-local.cpp | 4 +- test/CodeGenCXX/cxx1y-initializer-aggregate.cpp | 11 + .../CodeGenCXX/cxx1y-variable-template-linkage.cpp | 40 + test/CodeGenCXX/cxx1z-fold-expression.cpp | 45 + test/CodeGenCXX/debug-info-access.cpp | 39 + test/CodeGenCXX/debug-info-alias.cpp | 6 +- test/CodeGenCXX/debug-info-artificial-arg.cpp | 8 +- test/CodeGenCXX/debug-info-class.cpp | 30 +- test/CodeGenCXX/debug-info-cxx1y.cpp | 17 +- test/CodeGenCXX/debug-info-decl-nested.cpp | 13 +- test/CodeGenCXX/debug-info-enum-class.cpp | 12 +- test/CodeGenCXX/debug-info-enum.cpp | 18 +- test/CodeGenCXX/debug-info-flex-member.cpp | 2 +- test/CodeGenCXX/debug-info-function-context.cpp | 8 +- test/CodeGenCXX/debug-info-global.cpp | 6 +- test/CodeGenCXX/debug-info-globalinit.cpp | 4 +- test/CodeGenCXX/debug-info-line-if.cpp | 65 +- test/CodeGenCXX/debug-info-line.cpp | 187 ++ test/CodeGenCXX/debug-info-method.cpp | 18 +- test/CodeGenCXX/debug-info-namespace.cpp | 78 +- .../debug-info-ptr-to-member-function.cpp | 10 + test/CodeGenCXX/debug-info-qualifiers.cpp | 18 +- test/CodeGenCXX/debug-info-rvalue-ref.cpp | 2 +- test/CodeGenCXX/debug-info-scope.cpp | 67 +- test/CodeGenCXX/debug-info-static-fns.cpp | 2 +- test/CodeGenCXX/debug-info-static-member.cpp | 81 +- ...debug-info-template-explicit-specialization.cpp | 8 + test/CodeGenCXX/debug-info-template-limit.cpp | 4 +- test/CodeGenCXX/debug-info-template-member.cpp | 42 +- .../debug-info-template-partial-specialization.cpp | 4 +- test/CodeGenCXX/debug-info-template-quals.cpp | 14 +- test/CodeGenCXX/debug-info-template.cpp | 116 +- test/CodeGenCXX/debug-info-thunk.cpp | 2 +- test/CodeGenCXX/debug-info-union-template.cpp | 6 +- test/CodeGenCXX/debug-info-uuid.cpp | 24 +- test/CodeGenCXX/debug-info-varargs.cpp | 18 +- test/CodeGenCXX/debug-info-wchar.cpp | 2 +- test/CodeGenCXX/debug-info-windows-dtor.cpp | 22 + test/CodeGenCXX/debug-info-zero-length-arrays.cpp | 8 +- test/CodeGenCXX/debug-info.cpp | 33 +- test/CodeGenCXX/debug-lambda-expressions.cpp | 44 +- test/CodeGenCXX/debug-lambda-this.cpp | 2 +- test/CodeGenCXX/destructor-debug-info.cpp | 2 +- test/CodeGenCXX/destructors.cpp | 362 ++- .../devirtualize-virtual-function-calls-final.cpp | 46 +- test/CodeGenCXX/dllexport-alias.cpp | 18 + test/CodeGenCXX/dllexport-members.cpp | 32 +- test/CodeGenCXX/dllexport.cpp | 166 +- test/CodeGenCXX/dllimport-members.cpp | 408 ++-- test/CodeGenCXX/dllimport-rtti.cpp | 18 +- test/CodeGenCXX/dllimport.cpp | 164 +- test/CodeGenCXX/duplicate-mangled-name.cpp | 2 +- test/CodeGenCXX/explicit-instantiation.cpp | 13 + test/CodeGenCXX/extern-c.cpp | 4 +- test/CodeGenCXX/field-access-debug-info.cpp | 4 +- test/CodeGenCXX/funcsig.cpp | 6 +- .../function-template-specialization.cpp | 19 + test/CodeGenCXX/globalinit-loc.cpp | 4 +- test/CodeGenCXX/homogeneous-aggregates.cpp | 106 + test/CodeGenCXX/lambda-expressions.cpp | 14 +- test/CodeGenCXX/linetable-cleanup.cpp | 18 +- test/CodeGenCXX/linetable-eh.cpp | 12 +- test/CodeGenCXX/linetable-fnbegin.cpp | 6 +- test/CodeGenCXX/lpad-linetable.cpp | 2 +- test/CodeGenCXX/mangle-exprs.cpp | 101 +- test/CodeGenCXX/mangle-literal-suffix.cpp | 17 + test/CodeGenCXX/mangle-local-anonymous-unions.cpp | 42 + test/CodeGenCXX/mangle-ms-cxx11.cpp | 108 +- test/CodeGenCXX/mangle-ms-cxx14.cpp | 4 +- test/CodeGenCXX/mangle-ms-string-literals.cpp | 6 + test/CodeGenCXX/mangle-ms-templates.cpp | 10 + test/CodeGenCXX/mangle-ms.cpp | 15 + test/CodeGenCXX/mangle.cpp | 22 + test/CodeGenCXX/merge-functions.cpp | 14 + test/CodeGenCXX/microsoft-abi-byval-sret.cpp | 61 +- test/CodeGenCXX/microsoft-abi-byval-thunks.cpp | 113 + test/CodeGenCXX/microsoft-abi-dynamic-cast.cpp | 54 +- test/CodeGenCXX/microsoft-abi-member-pointers.cpp | 100 +- ...crosoft-abi-multiple-nonvirtual-inheritance.cpp | 20 +- .../microsoft-abi-nontrivial-covariant-thunk.cpp | 2 +- .../microsoft-abi-static-initializers.cpp | 34 +- .../microsoft-abi-structors-delayed-template.cpp | 12 + test/CodeGenCXX/microsoft-abi-structors.cpp | 70 +- test/CodeGenCXX/microsoft-abi-thunks.cpp | 11 +- test/CodeGenCXX/microsoft-abi-typeid.cpp | 9 +- test/CodeGenCXX/microsoft-abi-vftables.cpp | 8 +- ...microsoft-abi-virtual-inheritance-vtordisps.cpp | 7 +- .../microsoft-abi-virtual-inheritance.cpp | 89 +- .../microsoft-abi-virtual-member-pointers.cpp | 119 +- .../CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp | 101 + test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp | 11 + ...le-nonvirtual-inheritance-return-adjustment.cpp | 67 + ...iple-nonvirtual-inheritance-this-adjustment.cpp | 51 +- .../microsoft-abi-vtables-return-thunks.cpp | 24 + .../microsoft-abi-vtables-single-inheritance.cpp | 10 + ...t-abi-vtables-virtual-inheritance-vtordisps.cpp | 20 +- .../microsoft-abi-vtables-virtual-inheritance.cpp | 45 +- test/CodeGenCXX/microsoft-interface.cpp | 4 +- test/CodeGenCXX/microsoft-no-rtti-data.cpp | 1 + test/CodeGenCXX/microsoft-uuidof-mangling.cpp | 48 + test/CodeGenCXX/mingw-w64-seh-exceptions.cpp | 24 + test/CodeGenCXX/ms-inline-asm-return.cpp | 100 + .../ms-integer-static-data-members-exported.cpp | 4 +- test/CodeGenCXX/ms-integer-static-data-members.cpp | 2 +- test/CodeGenCXX/ms-thread_local.cpp | 28 + test/CodeGenCXX/nrvo-noreturn.cc | 17 - test/CodeGenCXX/nrvo-noreturn.cpp | 17 + test/CodeGenCXX/optnone-def-decl.cpp | 94 + test/CodeGenCXX/pod-member-memcpys.cpp | 13 + test/CodeGenCXX/pointers-to-data-members.cpp | 24 +- test/CodeGenCXX/pr12251.cpp | 19 +- test/CodeGenCXX/pr18635.cpp | 22 + test/CodeGenCXX/pr18962.cpp | 2 +- test/CodeGenCXX/pr20719.cpp | 35 + test/CodeGenCXX/pr20897.cpp | 33 + test/CodeGenCXX/pr21989.cpp | 9 + test/CodeGenCXX/pragma-init_seg.cpp | 12 +- test/CodeGenCXX/predefined-expr-cxx14.cpp | 105 + test/CodeGenCXX/predefined-expr.cpp | 32 +- test/CodeGenCXX/runtimecc.cpp | 22 +- test/CodeGenCXX/sections.cpp | 72 + .../skip-vtable-pointer-initialization.cpp | 16 +- test/CodeGenCXX/split-stacks.cpp | 4 +- test/CodeGenCXX/static-data-member.cpp | 14 +- test/CodeGenCXX/static-init.cpp | 8 +- test/CodeGenCXX/static-local-in-local-class.cpp | 133 +- ...tic-member-variable-explicit-specialization.cpp | 135 +- test/CodeGenCXX/temporaries.cpp | 7 + test/CodeGenCXX/try-catch.cpp | 8 + test/CodeGenCXX/unknown-anytype.cpp | 8 + test/CodeGenCXX/vararg-non-pod-ms-compat.cpp | 28 + test/CodeGenCXX/virtual-base-cast.cpp | 36 +- test/CodeGenCXX/virtual-destructor-calls.cpp | 2 +- test/CodeGenCXX/virtual-operator-call.cpp | 9 +- test/CodeGenCXX/vla-lambda-capturing.cpp | 171 ++ test/CodeGenCXX/vlt_to_reference.cpp | 22 + test/CodeGenCXX/vtable-align.cpp | 14 + test/CodeGenCXX/vtable-holder-self-reference.cpp | 15 + test/CodeGenCXX/vtable-pointer-initialization.cpp | 8 +- test/CodeGenCXX/x86_64-arguments-nacl-x32.cpp | 44 + test/CodeGenCXX/x86_64-arguments.cpp | 15 + test/CodeGenObjC/2010-02-09-DbgSelf.m | 2 +- test/CodeGenObjC/2010-02-15-Dbg-MethodStart.m | 3 +- test/CodeGenObjC/arc-foreach.m | 6 +- test/CodeGenObjC/arc-linetable-autorelease.m | 4 +- test/CodeGenObjC/arc-linetable.m | 34 +- test/CodeGenObjC/arc-literals.m | 14 +- test/CodeGenObjC/arc-loadweakretained-release.m | 2 +- test/CodeGenObjC/arc-precise-lifetime.m | 8 +- test/CodeGenObjC/arc-property.m | 4 +- test/CodeGenObjC/arc.m | 52 +- test/CodeGenObjC/arm-atomic-scalar-setter-getter.m | 4 +- test/CodeGenObjC/block-byref-debuginfo.m | 2 +- test/CodeGenObjC/block-over-align.m | 25 + test/CodeGenObjC/boxing.m | 24 +- test/CodeGenObjC/catch-lexical-block.m | 2 +- test/CodeGenObjC/category-super-class-meth.m | 4 +- test/CodeGenObjC/debug-info-block-captured-self.m | 10 +- test/CodeGenObjC/debug-info-block-type.m | 18 + test/CodeGenObjC/debug-info-blocks.m | 10 +- test/CodeGenObjC/debug-info-getter-name.m | 2 +- test/CodeGenObjC/debug-info-id-with-protocol.m | 7 +- test/CodeGenObjC/debug-info-instancetype.m | 10 +- test/CodeGenObjC/debug-info-ivars-extension.m | 4 +- test/CodeGenObjC/debug-info-lifetime-crash.m | 4 +- test/CodeGenObjC/debug-info-nested-blocks.m | 26 + test/CodeGenObjC/debug-info-property-accessors.m | 2 +- test/CodeGenObjC/debug-info-property3.m | 2 +- test/CodeGenObjC/debug-info-self.m | 6 +- test/CodeGenObjC/debug-info-static-var.m | 2 +- test/CodeGenObjC/debug-info-synthesis.m | 2 +- test/CodeGenObjC/debug-info-variadic-method.m | 16 + test/CodeGenObjC/debug-property-synth.m | 4 +- test/CodeGenObjC/encode-test.m | 2 +- test/CodeGenObjC/exceptions-asm-attribute.m | 8 +- .../CodeGenObjC/externally-initialized-selectors.m | 2 +- .../forward-protocol-metadata-symbols.m | 2 +- test/CodeGenObjC/image-info.m | 16 +- test/CodeGenObjC/ivar-layout-64.m | 26 +- test/CodeGenObjC/mangle-blocks.m | 29 + test/CodeGenObjC/metadata-symbols-32.m | 42 +- test/CodeGenObjC/metadata-symbols-64.m | 20 +- test/CodeGenObjC/metadata_symbols.m | 8 +- test/CodeGenObjC/non-lazy-classes.m | 7 +- test/CodeGenObjC/objc-align.m | 35 +- test/CodeGenObjC/objc-container-subscripting-1.m | 8 +- test/CodeGenObjC/objc-fixed-enum.m | 24 +- test/CodeGenObjC/optimize-ivar-offset-load.m | 4 +- test/CodeGenObjC/optimized-setter-ios-device.m | 8 +- .../private-extern-selector-reference.m | 18 + test/CodeGenObjC/property-array-type.m | 2 +- test/CodeGenObjC/property-type-mismatch.m | 2 +- test/CodeGenObjC/property.m | 12 +- test/CodeGenObjC/reorder-synthesized-ivars.m | 36 +- test/CodeGenObjC/selector-ref-invariance.m | 2 +- test/CodeGenObjC/super-message-fragileabi.m | 2 +- test/CodeGenObjC/tentative-cfconstantstring.m | 4 +- test/CodeGenObjC/undefined-protocol2.m | 17 + test/CodeGenObjCXX/arc-cxx11-init-list.mm | 55 + test/CodeGenObjCXX/arc-cxx11-member-init.mm | 17 +- test/CodeGenObjCXX/arc-references.mm | 2 +- test/CodeGenObjCXX/arc.mm | 2 +- test/CodeGenObjCXX/block-id.mm | 22 + test/CodeGenObjCXX/debug-info-line.mm | 30 + test/CodeGenObjCXX/destroy.mm | 50 + .../externally-initialized-selectors.mm | 2 +- test/CodeGenObjCXX/lambda-expressions.mm | 4 +- test/CodeGenObjCXX/lvalue-reference-getter.mm | 2 +- test/CodeGenObjCXX/mangle-blocks.mm | 13 +- test/CodeGenObjCXX/property-lvalue-capture.mm | 6 +- test/CodeGenObjCXX/property-object-reference.mm | 4 +- test/CodeGenObjCXX/property-objects.mm | 7 +- test/CodeGenObjCXX/subst-sel.mm | 4 + test/CodeGenOpenCL/addr-space-struct-arg.cl | 46 +- .../address-space-constant-initializers.cl | 2 +- test/CodeGenOpenCL/address-spaces-conversions.cl | 22 + test/CodeGenOpenCL/amdgpu-num-gpr-attr.cl | 48 + test/CodeGenOpenCL/builtins-r600.cl | 37 +- test/CodeGenOpenCL/const-str-array-decay.cl | 11 + test/CodeGenOpenCL/constant-addr-space-globals.cl | 8 + test/CodeGenOpenCL/denorms-are-zero.cl | 5 + test/CodeGenOpenCL/fpmath.cl | 2 +- test/CodeGenOpenCL/kernel-arg-info.cl | 59 +- test/CodeGenOpenCL/kernel-attributes.cl | 12 +- test/CodeGenOpenCL/kernel-metadata.cl | 7 +- test/CodeGenOpenCL/local-initializer-undef.cl | 24 + test/CodeGenOpenCL/local.cl | 6 +- test/CodeGenOpenCL/opencl_types.cl | 5 +- test/CodeGenOpenCL/ptx-calls.cl | 2 +- test/CodeGenOpenCL/ptx-kernels.cl | 2 +- test/CodeGenOpenCL/relaxed-fpmath.cl | 36 + test/CodeGenOpenCL/str_literals.cl | 4 +- test/Coverage/html-diagnostics.c | 5 +- test/CoverageMapping/Inputs/code.h | 11 + test/CoverageMapping/Inputs/header1.h | 31 + test/CoverageMapping/break.c | 31 + test/CoverageMapping/builtinmacro.c | 14 + test/CoverageMapping/casts.c | 11 + test/CoverageMapping/classtemplate.cpp | 54 + test/CoverageMapping/continue.c | 24 + test/CoverageMapping/header.cpp | 27 + test/CoverageMapping/if.c | 24 + test/CoverageMapping/includehell.cpp | 12 + test/CoverageMapping/ir.c | 12 + test/CoverageMapping/label.cpp | 63 + test/CoverageMapping/logical.cpp | 13 + test/CoverageMapping/loopmacro.c | 40 + test/CoverageMapping/loops.cpp | 37 + test/CoverageMapping/macroception.c | 40 + test/CoverageMapping/macroparams.c | 12 + test/CoverageMapping/macroparams2.c | 20 + test/CoverageMapping/macros.c | 26 + test/CoverageMapping/nestedclass.cpp | 28 + test/CoverageMapping/objc.m | 29 + test/CoverageMapping/preprocessor.c | 37 + test/CoverageMapping/return.c | 35 + test/CoverageMapping/switch.c | 48 + test/CoverageMapping/templates.cpp | 21 + test/CoverageMapping/test.c | 31 + test/CoverageMapping/trycatch.cpp | 34 + test/Driver/B-opt.c | 8 +- .../ARM/8.1/usr/bin/armv7-windows-itanium-ld | 0 .../Inputs/basic_netbsd_tree/usr/lib/eabihf/crti.o | 0 .../basic_netbsd_tree/usr/lib/powerpc/crti.o | 0 test/Driver/Inputs/cc1-response.txt | 4 + test/Driver/Inputs/gen-response.c | 8 + .../4.6.3/include-fixed/uclibc/el/.keep | 0 .../4.6.3/include-fixed/uclibc/nan2008/el/.keep | 0 .../4.6.3/include-fixed/uclibc/soft-float/el/.keep | 0 .../lib/gcc/mips-linux-gnu/4.6.3/uclibc/crtbegin.o | 0 .../lib/gcc/mips-linux-gnu/4.6.3/uclibc/crtend.o | 0 .../gcc/mips-linux-gnu/4.6.3/uclibc/el/crtbegin.o | 0 .../gcc/mips-linux-gnu/4.6.3/uclibc/el/crtend.o | 0 .../mips-linux-gnu/4.6.3/uclibc/nan2008/crtbegin.o | 0 .../mips-linux-gnu/4.6.3/uclibc/nan2008/crtend.o | 0 .../4.6.3/uclibc/nan2008/el/crtbegin.o | 0 .../4.6.3/uclibc/nan2008/el/crtend.o | 0 .../4.6.3/uclibc/soft-float/crtbegin.o | 0 .../4.6.3/uclibc/soft-float/crtend.o | 0 .../4.6.3/uclibc/soft-float/el/crtbegin.o | 0 .../4.6.3/uclibc/soft-float/el/crtend.o | 0 .../mips-linux-gnu/lib/uclibc/el/.keep | 0 .../mips-linux-gnu/lib/uclibc/nan2008/el/.keep | 0 .../mips-linux-gnu/lib/uclibc/soft-float/el/.keep | 0 .../mips-linux-gnu/libc/uclibc/el/lib/.keep | 0 .../libc/uclibc/el/usr/include/.keep | 0 .../mips-linux-gnu/libc/uclibc/el/usr/lib/crt1.o | 0 .../mips-linux-gnu/libc/uclibc/el/usr/lib/crti.o | 0 .../mips-linux-gnu/libc/uclibc/el/usr/lib/crtn.o | 0 .../mips-linux-gnu/libc/uclibc/lib/.keep | 0 .../libc/uclibc/nan2008/el/lib/.keep | 0 .../libc/uclibc/nan2008/el/usr/include/.keep | 0 .../libc/uclibc/nan2008/el/usr/lib/crt1.o | 0 .../libc/uclibc/nan2008/el/usr/lib/crti.o | 0 .../libc/uclibc/nan2008/el/usr/lib/crtn.o | 0 .../mips-linux-gnu/libc/uclibc/nan2008/lib/.keep | 0 .../libc/uclibc/nan2008/usr/include/.keep | 0 .../libc/uclibc/nan2008/usr/lib/crt1.o | 0 .../libc/uclibc/nan2008/usr/lib/crti.o | 0 .../libc/uclibc/nan2008/usr/lib/crtn.o | 0 .../libc/uclibc/soft-float/el/lib/.keep | 0 .../libc/uclibc/soft-float/el/usr/include/.keep | 0 .../libc/uclibc/soft-float/el/usr/lib/crt1.o | 0 .../libc/uclibc/soft-float/el/usr/lib/crti.o | 0 .../libc/uclibc/soft-float/el/usr/lib/crtn.o | 0 .../libc/uclibc/soft-float/lib/.keep | 0 .../libc/uclibc/soft-float/usr/include/.keep | 0 .../libc/uclibc/soft-float/usr/lib/crt1.o | 0 .../libc/uclibc/soft-float/usr/lib/crti.o | 0 .../libc/uclibc/soft-float/usr/lib/crtn.o | 0 .../mips-linux-gnu/libc/uclibc/usr/include/.keep | 0 .../mips-linux-gnu/libc/uclibc/usr/lib/crt1.o | 0 .../mips-linux-gnu/libc/uclibc/usr/lib/crti.o | 0 .../mips-linux-gnu/libc/uclibc/usr/lib/crtn.o | 0 .../gcc/mips-mti-linux-gnu/4.9.0/uclibc/crtbegin.o | 0 .../gcc/mips-mti-linux-gnu/4.9.0/uclibc/crtend.o | 0 .../mips-mti-linux-gnu/4.9.0/uclibc/el/crtbegin.o | 0 .../mips-mti-linux-gnu/4.9.0/uclibc/el/crtend.o | 0 .../4.9.0/uclibc/el/nan2008/crtbegin.o | 0 .../4.9.0/uclibc/el/nan2008/crtend.o | 0 .../4.9.0/uclibc/el/sof/crtbegin.o | 0 .../4.9.0/uclibc/el/sof/crtend.o | 0 .../4.9.0/uclibc/nan2008/crtbegin.o | 0 .../4.9.0/uclibc/nan2008/crtend.o | 0 .../mips-mti-linux-gnu/4.9.0/uclibc/sof/crtbegin.o | 0 .../mips-mti-linux-gnu/4.9.0/uclibc/sof/crtend.o | 0 .../uclibc/el/nan2008/bits/.keep | 0 .../mips-mti-linux-gnu/uclibc/el/sof/bits/.keep | 0 .../mips-mti-linux-gnu/uclibc/nan2008/bits/.keep | 0 .../4.9.0/mips-mti-linux-gnu/uclibc/sof/bits/.keep | 0 .../mips-mti-linux-gnu/lib/uclibc/el/nan2008/.keep | 0 .../mips-mti-linux-gnu/lib/uclibc/el/sof/.keep | 0 .../mips-mti-linux-gnu/lib/uclibc/nan2008/.keep | 0 .../mips-mti-linux-gnu/lib/uclibc/sof/.keep | 0 .../uclibc/el/nan2008/usr/include/bits/.keep | 0 .../sysroot/uclibc/el/nan2008/usr/lib/crt1.o | 0 .../sysroot/uclibc/el/nan2008/usr/lib/crti.o | 0 .../sysroot/uclibc/el/nan2008/usr/lib/crtn.o | 0 .../sysroot/uclibc/el/sof/usr/include/bits/.keep | 0 .../sysroot/uclibc/el/sof/usr/lib/crt1.o | 0 .../sysroot/uclibc/el/sof/usr/lib/crti.o | 0 .../sysroot/uclibc/el/sof/usr/lib/crtn.o | 0 .../sysroot/uclibc/el/usr/include/bits/.keep | 0 .../mips_fsf_tree/sysroot/uclibc/el/usr/lib/crt1.o | 0 .../mips_fsf_tree/sysroot/uclibc/el/usr/lib/crti.o | 0 .../mips_fsf_tree/sysroot/uclibc/el/usr/lib/crtn.o | 0 .../sysroot/uclibc/nan2008/usr/include/bits/.keep | 0 .../sysroot/uclibc/nan2008/usr/lib/crt1.o | 0 .../sysroot/uclibc/nan2008/usr/lib/crti.o | 0 .../sysroot/uclibc/nan2008/usr/lib/crtn.o | 0 .../sysroot/uclibc/sof/usr/include/bits/.keep | 0 .../sysroot/uclibc/sof/usr/lib/crt1.o | 0 .../sysroot/uclibc/sof/usr/lib/crti.o | 0 .../sysroot/uclibc/sof/usr/lib/crtn.o | 0 .../sysroot/uclibc/usr/include/bits/.keep | 0 .../mips_fsf_tree/sysroot/uclibc/usr/lib/crt1.o | 0 .../mips_fsf_tree/sysroot/uclibc/usr/lib/crti.o | 0 .../mips_fsf_tree/sysroot/uclibc/usr/lib/crtn.o | 0 test/Driver/aarch64-cpus.c | 27 +- test/Driver/aarch64-fix-cortex-a53-835769.c | 13 + test/Driver/arm-abi.c | 53 + test/Driver/arm-alignment.c | 12 + test/Driver/arm-cortex-cpus.c | 14 +- test/Driver/arm-fixed-r9.c | 2 +- test/Driver/arm-mfpu.c | 45 +- test/Driver/ast.c | 7 +- test/Driver/biarch.c | 41 + test/Driver/cc1-response-files.c | 2 + test/Driver/cl-inputs.c | 10 + test/Driver/cl-link-at-file.c | 22 + test/Driver/cl-link.c | 9 + test/Driver/cl-options.c | 26 +- test/Driver/cl-outputs.c | 168 +- test/Driver/cl-zc.cpp | 59 + test/Driver/clang-g-opts.c | 2 + test/Driver/clang-s-opts.s | 4 + test/Driver/clang_f_opts.c | 150 ++ test/Driver/constructors.c | 10 + test/Driver/coverage_no_integrated_as.c | 23 + test/Driver/crash report spaces.c | 18 + test/Driver/crash-report-modules.m | 10 +- test/Driver/crash-report-null.test | 7 + test/Driver/crash-report.c | 36 +- test/Driver/cross-linux.c | 28 +- test/Driver/darwin-arch-default.c | 40 +- test/Driver/darwin-debug-flags.c | 8 +- test/Driver/darwin-dsymutil.c | 15 +- test/Driver/darwin-ld-demangle.c | 8 + test/Driver/darwin-ld.c | 18 +- test/Driver/darwin-max-type-align.c | 15 + test/Driver/darwin-sanitizer-ld.c | 8 +- test/Driver/darwin-sdkroot.c | 7 + test/Driver/darwin-verify-debug.c | 5 +- test/Driver/debug-options.c | 4 + test/Driver/default-image-name.c | 7 + test/Driver/env.c | 28 + test/Driver/fatal-warnings.c | 8 + test/Driver/fortran.f95 | 9 + test/Driver/freebsd.c | 12 +- test/Driver/freebsd.cc | 6 - test/Driver/freebsd.cpp | 6 + test/Driver/fsanitize.c | 87 +- test/Driver/gcc-version-debug.c | 1 + test/Driver/gcc_forward.c | 4 - test/Driver/hexagon-toolchain-elf.c | 137 +- test/Driver/hexagon-toolchain.c | 137 +- test/Driver/ident_md.c | 2 +- test/Driver/instrprof-ld.c | 6 +- test/Driver/le32-unknown-nacl.cpp | 6 +- test/Driver/le64-unknown-unknown.cpp | 137 ++ test/Driver/linux-header-search.cpp | 18 + test/Driver/linux-ld.c | 190 +- test/Driver/lto.c | 13 +- test/Driver/mips-as.c | 20 +- test/Driver/mips-cs.cpp | 174 ++ test/Driver/mips-features.c | 10 + test/Driver/mips-fsf.cpp | 162 ++ test/Driver/mips-integrated-as.s | 10 + test/Driver/mips-reduced-toolchain.cpp | 2 + test/Driver/modules.m | 24 +- test/Driver/modules.mm | 6 +- test/Driver/msvc_forward.c | 4 +- test/Driver/netbsd.c | 141 +- test/Driver/netbsd.cpp | 96 +- test/Driver/no-canonical-prefixes.c | 10 + test/Driver/openbsd.c | 17 +- test/Driver/parse-progname.c | 58 + test/Driver/phases.c | 66 +- test/Driver/pic.c | 5 + test/Driver/ppc-abi.c | 19 + test/Driver/ppc-features.cpp | 16 +- test/Driver/prefixed-tools.c | 8 +- test/Driver/r600-mcpu.cl | 18 +- test/Driver/response-file.c | 23 + test/Driver/rewrite-legacy-objc.m | 6 +- test/Driver/rewrite-map-in-diagnostics.c | 12 + test/Driver/rewrite-objc.m | 2 +- test/Driver/sanitizer-ld.c | 63 +- test/Driver/save-temps.c | 11 + test/Driver/sparc-float.c | 4 + test/Driver/split-debug.c | 1 - test/Driver/split-debug.s | 1 - test/Driver/std.c | 16 +- test/Driver/symbol-rewriter.c | 21 + test/Driver/systemz-as.s | 14 + test/Driver/thread-model.c | 15 + test/Driver/unknown-gcc-arch.c | 20 +- test/Driver/warning-options.cpp | 5 - test/Driver/windows-cross.c | 40 + test/Driver/x86-march.c | 105 + test/FixIt/fixit-class-method-messaging.m | 30 + test/FixIt/fixit-cxx1y-compat.cpp | 2 +- test/FixIt/fixit-errors.c | 10 +- test/FixIt/fixit-unrecoverable.cpp | 4 +- test/FixIt/fixit.cpp | 49 +- test/FixIt/multiarg-selector-fixit.m | 15 + test/FixIt/property-access-fixit.m | 31 + .../Inputs/profile-sample-use-loc-tracking.prof | 2 + test/Frontend/exceptions.c | 7 +- test/Frontend/invalid-o-level.c | 7 +- test/Frontend/output-failures.c | 2 +- test/Frontend/print-header-includes.c | 3 + test/Frontend/profile-sample-use-loc-tracking.c | 19 + test/Frontend/source-col-map.c | 37 + test/Frontend/std.cl | 9 + test/Frontend/trigraphs.cpp | 17 + test/Frontend/verify-unknown-arg.c | 6 + test/Frontend/x86-target-cpu.c | 30 + test/Headers/altivec-header.c | 1 + test/Headers/altivec-intrin.c | 18 + test/Headers/c11.c | 2 +- test/Headers/cpuid.c | 18 + test/Headers/cxx11.cpp | 3 +- test/Headers/ms-intrin.cpp | 5 + test/Headers/x86intrin.c | 39 + test/Index/Inputs/complete-at-EOF.c | 3 + test/Index/Inputs/declare-objc-predef.h | 3 + test/Index/Inputs/module-undef.h | 2 + test/Index/Inputs/module.map | 2 + test/Index/annotate-deep-statements.cpp | 4 +- test/Index/attributes-cuda.cu | 7 +- test/Index/comment-c-decls.c | 2 +- test/Index/comment-lots-of-unknown-commands.c | 295 +++ test/Index/comment-to-html-xml-conversion.cpp | 52 +- test/Index/complete-at-EOF.c | 9 + test/Index/complete-module-undef.m | 8 + test/Index/cursor-dynamic-call.mm | 14 + test/Index/cxx11-lambdas.cpp | 2 +- test/Index/format-comment-cdecls.c | 2 +- test/Index/get-cursor.cpp | 131 ++ test/Index/index-many-call-ops.cpp | 3 + test/Index/index-many-logical-ops.c | 3 + test/Index/index-module.m | 4 +- test/Index/index-templates.cpp | 32 +- test/Index/overriding-ftemplate-comments.cpp | 20 +- test/Index/overriding-method-comments.mm | 4 +- test/Index/preamble_macro_template.cpp | 2 +- test/Index/print-mangled-name.cpp | 30 + test/Index/reparse-predef-objc-protocol.m | 9 + .../Index/skip-parsed-bodies/compile_commands.json | 2 +- test/Index/usrs-cxx0x.cpp | 10 + test/Index/usrs.cpp | 82 +- test/Layout/itanium-union-bitfield.cpp | 29 + test/Layout/ms-x86-basic-layout.cpp | 32 + test/Layout/ms-x86-empty-layout.c | 88 + test/Layout/ms-x86-pack-and-align.cpp | 154 ++ test/Layout/ms-x86-vtordisp.cpp | 26 + test/Lexer/bcpl-escaped-newline.c | 2 +- test/Lexer/block_cmt_end.c | 10 +- test/Lexer/constants.c | 6 +- test/Lexer/cxx-features.cpp | 36 + test/Lexer/cxx1z-trigraphs.cpp | 2 +- test/Lexer/escape_newline.c | 8 +- test/Lexer/has_extension.c | 12 +- test/Lexer/has_feature_c1x.c | 22 +- test/Lexer/has_feature_cxx0x.cpp | 10 + test/Lexer/ms-compatibility.c | 11 + test/Lexer/string-literal-errors.cpp | 2 + test/Lexer/utf8-char-literal.cpp | 9 + test/Lexer/wchar-signedness.c | 1 + test/Misc/ast-dump-arm-attr.c | 10 +- test/Misc/ast-dump-attr.cpp | 17 +- test/Misc/ast-dump-color.cpp | 24 +- test/Misc/ast-dump-decl.cpp | 5 + test/Misc/ast-dump-invalid.cpp | 20 + test/Misc/ast-dump-lookups.cpp | 38 + test/Misc/ast-dump-msp430-attr.c | 10 +- test/Misc/ast-dump-templates.cpp | 12 + test/Misc/ast-print-objectivec.m | 41 + test/Misc/ast-print-pragmas.cpp | 15 + test/Misc/attr-source-range.cpp | 16 + test/Misc/diag-special-chars.c | 11 + test/Misc/serialized-diags-driver.c | 20 + test/Misc/serialized-diags.m | 2 +- test/Misc/warning-flags.c | 9 +- .../Headers/AddRemovePrivate.h | 1 + .../Modules/module.modulemap | 1 + .../Modules/module.private.modulemap | 1 + test/Modules/Inputs/PR20399/FirstHeader.h | 14 + test/Modules/Inputs/PR20399/SecondHeader.h | 13 + test/Modules/Inputs/PR20399/module.modulemap | 18 + test/Modules/Inputs/PR20399/stl_map.h | 13 + test/Modules/Inputs/PR20399/vector | 17 + test/Modules/Inputs/PR20786/TBranchProxy.h | 2 + test/Modules/Inputs/PR20786/TFormula.h | 1 + test/Modules/Inputs/PR20786/TMath.h | 1 + test/Modules/Inputs/PR20786/module.modulemap | 3 + test/Modules/Inputs/PR20786/random.h | 12 + test/Modules/Inputs/StdDef/include_again.h | 2 + test/Modules/Inputs/StdDef/module.map | 10 + test/Modules/Inputs/StdDef/ptrdiff_t.h | 2 + .../Inputs/attr-unavailable/module.modulemap | 4 + test/Modules/Inputs/attr-unavailable/oneA.h | 4 + test/Modules/Inputs/attr-unavailable/oneB.h | 5 + test/Modules/Inputs/attr-unavailable/oneC.h | 3 + test/Modules/Inputs/attr-unavailable/two.h | 6 + test/Modules/Inputs/cxx-decls-imported.h | 24 + test/Modules/Inputs/cxx-decls-merged.h | 26 + test/Modules/Inputs/cxx-decls-premerged.h | 3 + test/Modules/Inputs/cxx-irgen-left.h | 15 + test/Modules/Inputs/cxx-irgen-right.h | 10 + test/Modules/Inputs/cxx-irgen-top.h | 35 + test/Modules/Inputs/cxx-lookup/a.h | 2 + test/Modules/Inputs/cxx-lookup/b.h | 3 + test/Modules/Inputs/cxx-lookup/c1.h | 3 + test/Modules/Inputs/cxx-lookup/c2.h | 2 + test/Modules/Inputs/cxx-lookup/module.modulemap | 8 + test/Modules/Inputs/cxx-lookup/x.h | 2 + test/Modules/Inputs/cxx-lookup/y.h | 5 + test/Modules/Inputs/cxx-templates-a.h | 31 + test/Modules/Inputs/cxx-templates-b.h | 21 + test/Modules/Inputs/cxx-templates-c.h | 15 + test/Modules/Inputs/cxx-templates-common.h | 18 + test/Modules/Inputs/cxx-templates-d.h | 9 + test/Modules/Inputs/cxx-templates-textual.h | 2 + test/Modules/Inputs/declare-use/k.h | 8 + test/Modules/Inputs/declare-use/l.h | 8 + test/Modules/Inputs/declare-use/m.h | 8 + test/Modules/Inputs/declare-use/m2.h | 1 + test/Modules/Inputs/declare-use/module.map | 14 + test/Modules/Inputs/dependency-gen-base.modulemap | 6 + test/Modules/Inputs/dependency-gen-base2.modulemap | 4 + test/Modules/Inputs/dependency-gen-included.h | 9 + test/Modules/Inputs/dependency-gen-included2.h | 7 + test/Modules/Inputs/dependency-gen.h | 11 + test/Modules/Inputs/diamond_left.h | 2 + test/Modules/Inputs/diamond_top.h | 1 + test/Modules/Inputs/explicit-build/a.h | 5 + test/Modules/Inputs/explicit-build/b.h | 7 + test/Modules/Inputs/explicit-build/c.h | 7 + .../Modules/Inputs/explicit-build/module.modulemap | 3 + test/Modules/Inputs/filename/a.h | 1 + test/Modules/Inputs/filename/module.map | 3 + test/Modules/Inputs/include_next/x/a.h | 2 + .../Modules/Inputs/include_next/x/module.modulemap | 2 + test/Modules/Inputs/include_next/x/subdir/b.h | 2 + test/Modules/Inputs/include_next/y/a.h | 1 + test/Modules/Inputs/include_next/y/b.h | 1 + .../Modules/Inputs/include_next/y/module.modulemap | 2 + .../Headers/InferredExternC.h | 1 + test/Modules/Inputs/inferred-attr/module.modulemap | 1 + test/Modules/Inputs/macros_bottom.h | 3 + test/Modules/Inputs/macros_right_undef.h | 1 + test/Modules/Inputs/macros_top.h | 1 + test/Modules/Inputs/malformed/c.h | 1 + test/Modules/Inputs/malformed/module.map | 1 + test/Modules/Inputs/merge-typedefs/a1.h | 11 + test/Modules/Inputs/merge-typedefs/a2.h | 3 + test/Modules/Inputs/merge-typedefs/b1.h | 11 + test/Modules/Inputs/merge-typedefs/b2.h | 3 + .../Modules/Inputs/merge-typedefs/module.modulemap | 9 + test/Modules/Inputs/merge-using-decls/a.h | 43 + test/Modules/Inputs/merge-using-decls/b.h | 50 + .../Inputs/merge-using-decls/module.modulemap | 2 + test/Modules/Inputs/modular_maps-moduleb-cwd.map | 4 + test/Modules/Inputs/modular_maps/c.h | 4 + test/Modules/Inputs/modular_maps/common.h | 2 +- test/Modules/Inputs/modular_maps/modulea-cwd.map | 7 + test/Modules/Inputs/modular_maps/modulec-cwd.map | 3 + test/Modules/Inputs/modular_maps/modulec.map | 3 + test/Modules/Inputs/module.map | 16 + test/Modules/Inputs/odr/a.h | 6 + test/Modules/Inputs/odr/b.h | 8 +- test/Modules/Inputs/pch-used.h | 1 + test/Modules/Inputs/pr19692/AIX.h | 2 + test/Modules/Inputs/pr19692/Blah.h | 2 + test/Modules/Inputs/pr19692/TBlah.h | 3 + test/Modules/Inputs/pr19692/TFoo.h | 1 + test/Modules/Inputs/pr19692/module.map | 3 + test/Modules/Inputs/pr19692/stdint.h | 2 + test/Modules/Inputs/preprocess-prefix.h | 2 + test/Modules/Inputs/relative-dep-gen-1.h | 1 + test/Modules/Inputs/relative-dep-gen-2.h | 1 + test/Modules/Inputs/relative-dep-gen-cwd.modulemap | 4 + test/Modules/Inputs/relative-dep-gen.modulemap | 4 + test/Modules/Inputs/templates-left.h | 10 + test/Modules/Inputs/templates-right.h | 4 + test/Modules/Inputs/templates-top.h | 17 + test/Modules/Inputs/va_list/module.modulemap | 2 + test/Modules/Inputs/va_list/va_list_a.h | 1 + test/Modules/Inputs/va_list/va_list_b.h | 2 + test/Modules/Inputs/warn-unused-local-typedef.h | 1 + test/Modules/Rmodule-build.m | 23 +- test/Modules/Werror-Wsystem-headers.m | 7 +- test/Modules/Werror.m | 1 - test/Modules/add-remove-private.m | 28 + test/Modules/attr-unavailable.m | 25 + test/Modules/autolink.m | 16 +- test/Modules/cstd.m | 2 +- test/Modules/cxx-decls.cpp | 20 + test/Modules/cxx-irgen.cpp | 56 +- test/Modules/cxx-lookup.cpp | 6 + test/Modules/cxx-templates.cpp | 46 +- test/Modules/dependency-gen.m | 4 +- test/Modules/dependency-gen.modulemap.cpp | 18 + test/Modules/explicit-build-flags.cpp | 49 + test/Modules/explicit-build-relpath.cpp | 49 + test/Modules/explicit-build.cpp | 175 ++ test/Modules/filename.cpp | 9 + .../fmodules-validate-once-per-build-session.c | 28 +- test/Modules/implementation-of-module.m | 29 + test/Modules/include_next.c | 11 + test/Modules/incomplete-module.m | 6 +- test/Modules/inferred-attributes.mm | 6 + test/Modules/load-after-failure.m | 1 - test/Modules/macro-reexport/c1.h | 2 + test/Modules/macro-reexport/d1.h | 3 + test/Modules/macro-reexport/e1.h | 2 + test/Modules/macro-reexport/e2.h | 2 + test/Modules/macro-reexport/f1.h | 3 + test/Modules/macro-reexport/macro-reexport.cpp | 25 +- test/Modules/macro-reexport/module.modulemap | 8 + test/Modules/macros.c | 6 + test/Modules/malformed.cpp | 34 +- test/Modules/merge-typedefs.cpp | 10 + test/Modules/merge-using-decls.cpp | 69 + test/Modules/modular_maps.cpp | 20 +- test/Modules/module_file_info.m | 6 +- test/Modules/modules-with-same-name.m | 1 - test/Modules/no-implicit-maps.cpp | 3 + test/Modules/no-stale-modtime.m | 1 - test/Modules/odr.cpp | 3 + test/Modules/pch-used.m | 1 + test/Modules/pr19692.cpp | 7 + test/Modules/pr20399.cpp | 2 + test/Modules/pr20786.cpp | 2 + test/Modules/pr21217.cpp | 3 + test/Modules/preprocess.m | 21 + test/Modules/rebuild.m | 45 + test/Modules/relative-dep-gen.cpp | 26 + test/Modules/require-modular-includes.m | 1 - test/Modules/resolution-change.m | 8 +- test/Modules/stddef.c | 13 + test/Modules/system_headers.m | 7 +- test/Modules/system_version.m | 1 - test/Modules/templates-2.mm | 36 + test/Modules/templates.mm | 23 +- test/Modules/textual-headers.cpp | 18 + test/Modules/va_list.m | 27 + test/Modules/validate-system-headers.m | 14 +- test/Modules/warn-unused-local-typedef.cpp | 9 + test/OpenMP/atomic_ast_print.cpp | 176 ++ test/OpenMP/atomic_messages.c | 102 + test/OpenMP/atomic_messages.cpp | 297 +++ test/OpenMP/barrier_codegen.cpp | 41 + test/OpenMP/critical_codegen.cpp | 38 + test/OpenMP/flush_codegen.cpp | 34 + test/OpenMP/for_codegen.cpp | 91 + test/OpenMP/for_firstprivate_messages.cpp | 33 +- test/OpenMP/for_loop_messages.cpp | 39 + test/OpenMP/for_misc_messages.c | 18 +- test/OpenMP/for_private_messages.cpp | 14 +- test/OpenMP/for_simd_aligned_messages.cpp | 202 ++ test/OpenMP/for_simd_ast_print.cpp | 128 ++ test/OpenMP/for_simd_collapse_messages.cpp | 83 + test/OpenMP/for_simd_firstprivate_messages.cpp | 293 +++ test/OpenMP/for_simd_lastprivate_messages.cpp | 266 +++ test/OpenMP/for_simd_linear_messages.cpp | 206 ++ test/OpenMP/for_simd_loop_messages.cpp | 734 ++++++ test/OpenMP/for_simd_misc_messages.c | 659 ++++++ test/OpenMP/for_simd_private_messages.cpp | 173 ++ test/OpenMP/for_simd_reduction_messages.cpp | 350 +++ test/OpenMP/for_simd_safelen_messages.cpp | 79 + test/OpenMP/for_simd_schedule_messages.cpp | 91 + test/OpenMP/master_codegen.cpp | 46 + test/OpenMP/nesting_of_regions.cpp | 2339 +++++++++++++++++++- test/OpenMP/ordered_ast_print.cpp | 59 + test/OpenMP/ordered_messages.cpp | 54 + test/OpenMP/parallel_codegen.cpp | 16 +- test/OpenMP/parallel_firstprivate_codegen.cpp | 255 +++ test/OpenMP/parallel_firstprivate_messages.cpp | 18 +- test/OpenMP/parallel_for_firstprivate_messages.cpp | 28 +- test/OpenMP/parallel_for_loop_messages.cpp | 36 + test/OpenMP/parallel_for_misc_messages.c | 11 + test/OpenMP/parallel_for_private_messages.cpp | 14 +- test/OpenMP/parallel_for_simd_aligned_messages.cpp | 202 ++ test/OpenMP/parallel_for_simd_ast_print.cpp | 128 ++ .../OpenMP/parallel_for_simd_collapse_messages.cpp | 83 + test/OpenMP/parallel_for_simd_copyin_messages.cpp | 93 + test/OpenMP/parallel_for_simd_default_messages.cpp | 36 + .../parallel_for_simd_firstprivate_messages.cpp | 250 +++ test/OpenMP/parallel_for_simd_if_messages.cpp | 69 + .../parallel_for_simd_lastprivate_messages.cpp | 226 ++ test/OpenMP/parallel_for_simd_linear_messages.cpp | 206 ++ test/OpenMP/parallel_for_simd_loop_messages.cpp | 644 ++++++ test/OpenMP/parallel_for_simd_messages.cpp | 87 + test/OpenMP/parallel_for_simd_misc_messages.c | 657 ++++++ .../parallel_for_simd_num_threads_messages.cpp | 65 + test/OpenMP/parallel_for_simd_private_messages.cpp | 173 ++ .../parallel_for_simd_proc_bind_messages.cpp | 35 + .../parallel_for_simd_reduction_messages.cpp | 295 +++ test/OpenMP/parallel_for_simd_safelen_messages.cpp | 79 + .../OpenMP/parallel_for_simd_schedule_messages.cpp | 91 + test/OpenMP/parallel_if_codegen.cpp | 124 ++ test/OpenMP/parallel_num_threads_codegen.cpp | 84 + test/OpenMP/parallel_private_codegen.cpp | 181 ++ test/OpenMP/parallel_private_messages.cpp | 14 +- .../parallel_sections_firstprivate_messages.cpp | 28 +- test/OpenMP/parallel_sections_private_messages.cpp | 14 +- test/OpenMP/sections_firstprivate_messages.cpp | 28 +- test/OpenMP/sections_private_messages.cpp | 14 +- test/OpenMP/simd_aligned_messages.cpp | 3 +- test/OpenMP/simd_codegen.cpp | 407 ++++ test/OpenMP/simd_loop_messages.cpp | 34 +- test/OpenMP/simd_metadata.c | 29 +- test/OpenMP/simd_misc_messages.c | 1039 +++++---- test/OpenMP/simd_private_messages.cpp | 14 +- test/OpenMP/single_copyprivate_messages.cpp | 20 + test/OpenMP/single_firstprivate_messages.cpp | 28 +- test/OpenMP/single_private_messages.cpp | 14 +- test/OpenMP/target_ast_print.cpp | 57 + test/OpenMP/target_if_messages.cpp | 46 + test/OpenMP/target_messages.cpp | 64 + test/OpenMP/task_firstprivate_messages.cpp | 18 +- test/OpenMP/task_messages.cpp | 48 +- test/OpenMP/task_private_messages.cpp | 14 +- test/OpenMP/teams_ast_print.cpp | 112 + test/OpenMP/teams_default_messages.cpp | 34 + test/OpenMP/teams_firstprivate_messages.cpp | 124 ++ test/OpenMP/teams_messages.cpp | 82 + test/OpenMP/teams_private_messages.cpp | 119 + test/OpenMP/teams_reduction_messages.cpp | 307 +++ test/OpenMP/teams_shared_messages.cpp | 125 ++ test/OpenMP/threadprivate_codegen.cpp | 707 ++++++ test/OpenMP/threadprivate_messages.cpp | 3 + test/PCH/chain-openmp-threadprivate.cpp | 26 + test/PCH/cxx-namespaces.cpp | 4 +- test/PCH/cxx-traits.cpp | 65 +- test/PCH/cxx-traits.h | 53 + test/PCH/cxx1y-lambdas.mm | 2 +- test/PCH/pragma-loop.cpp | 28 +- test/PCH/pragma-optimize.c | 6 + test/PCH/stmt-attrs.cpp | 48 +- test/PCH/verify_pch.m | 14 +- test/Parser/MicrosoftExtensions.c | 8 + test/Parser/MicrosoftExtensions.cpp | 20 +- test/Parser/PR21872.cpp | 4 + test/Parser/access-spec-attrs.cpp | 1 + test/Parser/altivec.c | 31 +- test/Parser/asm.cpp | 1 + test/Parser/atomic.c | 3 + test/Parser/attributes.c | 10 + test/Parser/c11-noreturn.c | 4 +- test/Parser/c1x-alignas.c | 2 +- test/Parser/colon-colon-parentheses.cpp | 10 +- test/Parser/cxx-altivec.cpp | 17 +- test/Parser/cxx-ambig-init-templ.cpp | 6 + test/Parser/cxx-attributes.cpp | 2 + test/Parser/cxx-class.cpp | 48 + test/Parser/cxx-default-args.cpp | 10 + test/Parser/cxx-member-initializers.cpp | 30 +- test/Parser/cxx-template-argument.cpp | 5 + test/Parser/cxx-template-decl.cpp | 28 + test/Parser/cxx-variadic-func.cpp | 7 +- test/Parser/cxx0x-attributes.cpp | 16 +- test/Parser/cxx0x-decl.cpp | 10 + test/Parser/cxx0x-in-cxx98.cpp | 4 + test/Parser/cxx0x-lambda-expressions.cpp | 17 + test/Parser/cxx11-templates.cpp | 46 + test/Parser/cxx1z-attributes.cpp | 14 + test/Parser/cxx1z-fold-expressions.cpp | 29 + test/Parser/cxx1z-nested-namespace-definition.cpp | 38 + test/Parser/debugger-import-module.m | 6 + test/Parser/declarators.c | 4 + test/Parser/eof2.cpp | 15 + test/Parser/ms-if-exists.c | 87 + test/Parser/ms-inline-asm.c | 5 +- test/Parser/namespaces.cpp | 6 +- test/Parser/nested-namespaces-recovery.cpp | 24 - test/Parser/opencl-cl20.cl | 26 + test/Parser/pragma-loop.cpp | 147 +- test/Parser/pragma-unroll.cpp | 72 +- test/Parser/switch-recovery.cpp | 9 + test/Parser/vsx.c | 10 + test/Preprocessor/_Pragma.c | 2 + test/Preprocessor/aarch64-target-features.c | 6 + test/Preprocessor/arm-acle-6.4.c | 6 + test/Preprocessor/arm-acle-6.5.c | 22 + test/Preprocessor/arm-target-features.c | 64 +- test/Preprocessor/cxx_oper_keyword_ms_compat.cpp | 2 + test/Preprocessor/feature_tests.c | 9 +- test/Preprocessor/has_attribute.c | 5 + test/Preprocessor/has_attribute.cpp | 68 + test/Preprocessor/headermap-rel2.c | 4 +- test/Preprocessor/init.c | 227 +- test/Preprocessor/iwithprefix.c | 2 +- test/Preprocessor/line-directive.c | 2 +- test/Preprocessor/macro-reserved-cxx11.cpp | 7 + test/Preprocessor/macro-reserved-ms.c | 7 + test/Preprocessor/macro-reserved.c | 64 + test/Preprocessor/macro-reserved.cpp | 63 + test/Preprocessor/macro_arg_directive.c | 5 + test/Preprocessor/macro_paste_bad.c | 8 + test/Preprocessor/predefined-arch-macros.c | 153 ++ test/Preprocessor/predefined-exceptions.m | 2 +- test/Preprocessor/predefined-macros.c | 102 +- test/Preprocessor/stdint.c | 107 + test/Preprocessor/x86_target_features.c | 53 + test/Profile/Inputs/c-general.profdata.v1 | Bin 0 -> 2000 bytes test/Profile/c-captured.c | 14 +- test/Profile/c-counter-overflows.c | 6 +- test/Profile/c-general.c | 147 +- test/Profile/c-linkage-available_externally.c | 3 +- test/Profile/c-linkage.c | 17 +- test/Profile/c-unreachable-after-switch.c | 15 + test/Profile/cxx-class.cpp | 8 +- test/Profile/cxx-lambda.cpp | 12 +- test/Profile/cxx-linkage.cpp | 13 +- test/Profile/cxx-templates.cpp | 4 +- test/Profile/cxx-throws.cpp | 12 +- test/Profile/objc-general.m | 10 +- test/Rewriter/rewrite-block-literal.mm | 2 +- test/Rewriter/rewrite-modern-block.mm | 3 + .../rewrite-modern-captured-nested-bvar.mm | 2 +- test/Sema/128bitfloat.cc | 24 - test/Sema/128bitfloat.cpp | 24 + test/Sema/128bitint.c | 4 +- test/Sema/MicrosoftExtensions.c | 25 + test/Sema/align_value.c | 32 + test/Sema/anonymous-struct-union-c11.c | 4 +- test/Sema/anonymous-struct-union.c | 12 +- test/Sema/arm-darwin-aapcs.cpp | 1 + test/Sema/arm64-inline-asm.c | 2 +- test/Sema/arm64-neon-args.c | 2 +- test/Sema/arm_acle.c | 16 + test/Sema/array-init.c | 4 +- test/Sema/asm.c | 41 + test/Sema/ast-print.c | 6 + test/Sema/atomic-ops.c | 73 +- test/Sema/attr-bounded.c | 30 +- test/Sema/attr-deprecated.c | 4 +- test/Sema/attr-flag-enum.c | 73 + test/Sema/attr-msp430.c | 12 +- test/Sema/attr-naked.c | 40 +- test/Sema/attr-nonnull.c | 7 + test/Sema/attr-ownership.c | 5 + test/Sema/big-endian-neon-initializers.c | 2 +- test/Sema/bitfield.c | 22 +- test/Sema/block-misc.c | 2 +- test/Sema/builtin-assume-aligned.c | 60 + test/Sema/builtin-assume.c | 9 +- test/Sema/builtin-object-size.c | 28 +- test/Sema/builtins-arm.c | 10 +- test/Sema/builtins-arm64.c | 7 + test/Sema/builtins-x86.c | 20 + test/Sema/builtins.c | 56 +- test/Sema/call-with-static-chain.c | 11 + test/Sema/callingconv.c | 2 +- test/Sema/constructor-attribute.c | 1 + test/Sema/decl-microsoft-call-conv.c | 35 + test/Sema/dllexport.c | 3 + test/Sema/dllimport.c | 34 +- test/Sema/expr-comma-c99.c | 3 +- test/Sema/expr-comma.c | 3 +- test/Sema/exprs.c | 6 +- test/Sema/format-strings-gnu.c | 8 +- test/Sema/format-strings-ms.c | 89 +- test/Sema/format-strings.c | 2 +- test/Sema/gnu-attributes.c | 18 + test/Sema/inline-asm-validate-aarch64.c | 38 + test/Sema/inline-asm-validate-x86.c | 105 + test/Sema/inline-asm-validate.c | 3 +- test/Sema/ms-inline-asm.c | 85 +- test/Sema/ms_bitfield_layout.c | 530 ++--- test/Sema/nonnull.c | 107 +- test/Sema/parentheses.cpp | 106 +- test/Sema/scope-check.c | 36 +- test/Sema/sentinel-attribute.c | 13 +- test/Sema/sizeof-struct-non-zero-as-member.cl | 18 + test/Sema/statements.c | 2 +- test/Sema/static-array.c | 4 +- test/Sema/stdcall-fastcall.c | 2 +- test/Sema/string-plus-char.c | 15 + test/Sema/struct-packed-align.c | 10 +- test/Sema/switch-1.c | 5 + test/Sema/switch.c | 12 +- test/Sema/types.c | 18 +- test/Sema/typo-correction.c | 25 + test/Sema/var-redecl.c | 12 +- test/Sema/warn-cast-qual.c | 29 + test/Sema/warn-string-conversion.c | 17 + test/Sema/warn-tautological-compare.c | 86 + test/Sema/warn-thread-safety-analysis.c | 6 +- test/Sema/warn-unsequenced.c | 12 +- test/Sema/warn-unused-value.c | 25 +- test/Sema/wchar.c | 4 +- test/SemaCUDA/amdgpu-num-gpr-attr.cu | 14 + test/SemaCUDA/function-target.cu | 35 +- test/SemaCUDA/implicit-copy.cu | 51 + test/SemaCUDA/implicit-intrinsic.cu | 10 + .../implicit-member-target-collision-cxx11.cu | 111 + test/SemaCUDA/implicit-member-target-collision.cu | 57 + test/SemaCUDA/implicit-member-target.cu | 186 ++ test/SemaCUDA/launch_bounds.cu | 5 +- test/SemaCUDA/method-target.cu | 71 + .../Inputs/header-with-pragma-optimize-off.h | 5 + test/SemaCXX/Inputs/override-system-header.h | 6 + test/SemaCXX/MicrosoftCompatibility.cpp | 10 +- test/SemaCXX/MicrosoftExtensions.cpp | 8 +- test/SemaCXX/MicrosoftSuper.cpp | 149 ++ test/SemaCXX/PR10177.cpp | 31 +- test/SemaCXX/PR20705.cpp | 21 + test/SemaCXX/align_value.cpp | 26 + test/SemaCXX/anonymous-union.cpp | 6 +- test/SemaCXX/arrow-operator.cpp | 5 +- test/SemaCXX/ast-print.cpp | 5 + test/SemaCXX/atomic-type.cpp | 4 + test/SemaCXX/attr-cxx0x-fixit.cpp | 5 + test/SemaCXX/attr-flag-enum-reject.cpp | 4 + test/SemaCXX/attr-gnu.cpp | 29 + test/SemaCXX/attr-nodebug.cpp | 4 +- test/SemaCXX/attr-nonnull.cpp | 4 +- test/SemaCXX/attr-optnone.cpp | 38 +- test/SemaCXX/attr-print.cpp | 9 + test/SemaCXX/attributed-auto-deduction.cpp | 20 + test/SemaCXX/bitfield.cpp | 32 + test/SemaCXX/blocks.cpp | 45 + test/SemaCXX/builtin-assume-aligned-tmpl.cpp | 87 + test/SemaCXX/builtin-assume-aligned.cpp | 49 + test/SemaCXX/call-with-static-chain.cpp | 15 + test/SemaCXX/complex-folding.cpp | 90 + test/SemaCXX/const-cast.cpp | 3 + test/SemaCXX/constant-expression-cxx11.cpp | 126 +- test/SemaCXX/constant-expression-cxx1y.cpp | 31 +- test/SemaCXX/constexpr-value-init.cpp | 6 +- test/SemaCXX/conversion-function.cpp | 12 +- test/SemaCXX/conversion.cpp | 20 + test/SemaCXX/crashes.cpp | 6 + test/SemaCXX/cxx-deprecated.cpp | 26 + test/SemaCXX/cxx0x-compat.cpp | 8 +- test/SemaCXX/cxx0x-cursory-default-delete.cpp | 2 +- test/SemaCXX/cxx0x-initializer-references.cpp | 6 + ...nitializer-stdinitializerlist-system-header.cpp | 23 - test/SemaCXX/cxx11-ast-print.cpp | 2 +- test/SemaCXX/cxx11-thread-unsupported.cpp | 5 + test/SemaCXX/cxx1y-constexpr-not-const.cpp | 2 +- test/SemaCXX/cxx1y-deduced-return-type.cpp | 13 + test/SemaCXX/cxx1y-generic-lambdas.cpp | 32 +- test/SemaCXX/cxx1y-variable-templates_in_class.cpp | 10 +- test/SemaCXX/cxx98-compat-flags.cpp | 4 +- test/SemaCXX/cxx98-compat-pedantic.cpp | 31 +- test/SemaCXX/cxx98-compat.cpp | 65 +- test/SemaCXX/decl-init-ref.cpp | 2 +- test/SemaCXX/decl-microsoft-call-conv.cpp | 13 +- test/SemaCXX/default1.cpp | 6 + test/SemaCXX/default2.cpp | 6 + test/SemaCXX/dependent-noexcept-unevaluated.cpp | 3 +- test/SemaCXX/deprecated.cpp | 8 +- test/SemaCXX/devirtualize-vtable-marking.cpp | 47 + test/SemaCXX/dllexport.cpp | 58 +- test/SemaCXX/dllimport.cpp | 344 ++- test/SemaCXX/enable_if.cpp | 41 + test/SemaCXX/enum-scoped.cpp | 8 + test/SemaCXX/exceptions.cpp | 24 +- test/SemaCXX/explicit.cpp | 2 +- test/SemaCXX/flexible-array-test.cpp | 6 + test/SemaCXX/for-range-examples.cpp | 20 +- test/SemaCXX/friend.cpp | 55 +- test/SemaCXX/goto.cpp | 4 +- test/SemaCXX/implicit-exception-spec.cpp | 35 +- test/SemaCXX/issue547.cpp | 12 +- test/SemaCXX/lambda-expressions.cpp | 80 +- test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp | 23 + test/SemaCXX/libstdcxx_is_pod_hack.cpp | 15 +- test/SemaCXX/libstdcxx_pair_swap_hack.cpp | 74 + test/SemaCXX/member-init.cpp | 84 +- test/SemaCXX/member-pointer-ms.cpp | 19 + test/SemaCXX/namespace-alias.cpp | 6 +- test/SemaCXX/nonnull.cpp | 5 + test/SemaCXX/nullptr.cpp | 2 +- test/SemaCXX/overloaded-operator.cpp | 12 + test/SemaCXX/override-in-system-header.cpp | 19 + test/SemaCXX/pragma-optimize.cpp | 53 +- test/SemaCXX/predefined-expr.cpp | 16 +- test/SemaCXX/return-noreturn.cpp | 100 +- test/SemaCXX/return.cpp | 8 + test/SemaCXX/runtimediag-ppe.cpp | 2 +- test/SemaCXX/scope-check.cpp | 38 +- test/SemaCXX/statements.cpp | 19 +- test/SemaCXX/string-plus-int.cpp | 5 + test/SemaCXX/struct-class-redecl.cpp | 6 + test/SemaCXX/trailing-return-0x.cpp | 10 +- test/SemaCXX/type-traits.cpp | 8 + test/SemaCXX/typeid.cpp | 6 + test/SemaCXX/typo-correction-delayed.cpp | 159 ++ test/SemaCXX/typo-correction-pt2.cpp | 302 --- test/SemaCXX/typo-correction.cpp | 385 +++- test/SemaCXX/undefined-internal.cpp | 4 +- test/SemaCXX/uninitialized.cpp | 713 +++++- test/SemaCXX/unknown-type-name.cpp | 6 +- test/SemaCXX/using-decl-1.cpp | 8 + test/SemaCXX/vararg-non-pod.cpp | 5 +- test/SemaCXX/vtable-instantiation.cc | 68 - test/SemaCXX/vtable-instantiation.cpp | 68 + test/SemaCXX/warn-bool-conversion.cpp | 27 + test/SemaCXX/warn-consumed-parsing.cpp | 1 + test/SemaCXX/warn-global-constructors.cpp | 6 + test/SemaCXX/warn-overloaded-virtual.cpp | 22 +- test/SemaCXX/warn-self-move.cpp | 55 + test/SemaCXX/warn-tautological-compare.cpp | 40 + .../warn-tautological-undefined-compare.cpp | 28 + test/SemaCXX/warn-thread-safety-analysis.cpp | 484 +++- test/SemaCXX/warn-thread-safety-negative.cpp | 104 + test/SemaCXX/warn-thread-safety-verbose.cpp | 86 + test/SemaCXX/warn-undefined-bool-conversion.cpp | 24 + test/SemaCXX/warn-unused-comparison.cpp | 2 + test/SemaCXX/warn-unused-filescoped.cpp | 4 +- .../warn-unused-local-typedef-serialize.cpp | 11 + test/SemaCXX/warn-unused-local-typedef-x86asm.cpp | 16 + test/SemaCXX/warn-unused-local-typedef.cpp | 242 ++ .../warn-unused-private-field-delayed-template.cpp | 11 + test/SemaCXX/warn-unused-result.cpp | 47 + test/SemaCXX/warn-unused-value-cxx11.cpp | 44 + test/SemaCXX/warn-unused-value.cpp | 34 +- test/SemaObjC/access-property-getter.m | 17 + test/SemaObjC/arc-jump-block.m | 8 +- test/SemaObjC/arc-repeated-weak.mm | 14 + test/SemaObjC/arc.m | 2 +- test/SemaObjC/attr-availability-1.m | 116 + test/SemaObjC/attr-availability.m | 27 + test/SemaObjC/attr-deprecated-pch.m | 23 + test/SemaObjC/attr-deprecated.m | 71 +- test/SemaObjC/autoreleasepool.m | 2 +- test/SemaObjC/compare-qualified-class.m | 35 + test/SemaObjC/conditional-expr.m | 10 +- test/SemaObjC/debugger-support.m | 2 +- test/SemaObjC/default-synthesize-1.m | 17 + test/SemaObjC/default-synthesize-3.m | 20 +- test/SemaObjC/default-synthesize.m | 40 +- test/SemaObjC/encode-typeof-test.m | 19 + test/SemaObjC/format-cstrings-warning.m | 79 + test/SemaObjC/format-strings-objc.m | 2 +- test/SemaObjC/iboutlet.m | 6 +- test/SemaObjC/ivar-lookup.m | 4 +- test/SemaObjC/method-lookup-3.m | 26 + test/SemaObjC/nonnull.m | 30 +- test/SemaObjC/objc-cf-audited-warning.m | 24 + test/SemaObjC/objc-dictionary-literal.m | 15 + test/SemaObjC/objcbridge-attribute-arc.m | 16 + test/SemaObjC/property-user-setter.m | 9 +- test/SemaObjC/protocol-expr-1.m | 2 +- test/SemaObjC/protocol-expr-neg-1.m | 19 +- test/SemaObjC/protocols-suppress-conformance.m | 10 +- test/SemaObjC/resolve-method-in-global-pool.m | 63 + test/SemaObjC/scope-check.m | 28 +- test/SemaObjC/super-property-notation.m | 6 +- test/SemaObjC/warn-category-method-deprecated.m | 17 + test/SemaObjC/warn-explicit-call-initialize.m | 25 + test/SemaObjC/warn-strict-selector-match.m | 6 +- test/SemaObjCXX/arc-ppe.mm | 2 +- test/SemaObjCXX/synchronized.mm | 20 + .../SemaOpenCL/address-spaces-conversions-cl2.0.cl | 227 ++ test/SemaOpenCL/address-spaces.cl | 5 +- test/SemaOpenCL/amdgpu-num-register-attrs.cl | 40 + test/SemaOpenCL/extern.cl | 4 +- test/SemaTemplate/canonical-expr-type.cpp | 8 + test/SemaTemplate/class-template-decl.cpp | 2 +- test/SemaTemplate/constructor-template.cpp | 50 +- test/SemaTemplate/crash.cpp | 11 + test/SemaTemplate/cxx1z-fold-expressions.cpp | 77 + test/SemaTemplate/deduction.cpp | 12 +- test/SemaTemplate/dependent-type-identity.cpp | 23 +- test/SemaTemplate/derived.cpp | 4 +- test/SemaTemplate/enum-bool.cpp | 11 + test/SemaTemplate/explicit-instantiation.cpp | 39 +- .../function-template-specialization-noreturn.cpp | 12 + .../instantiate-exception-spec-cxx11.cpp | 41 + test/SemaTemplate/instantiate-exception-spec.cpp | 21 +- test/SemaTemplate/instantiate-expr-1.cpp | 2 +- test/SemaTemplate/instantiate-init.cpp | 10 + test/SemaTemplate/instantiate-method.cpp | 25 + .../instantiate-non-dependent-types.cpp | 40 +- test/SemaTemplate/instantiate-scope.cpp | 30 + test/SemaTemplate/instantiate-typeof.cpp | 7 +- test/SemaTemplate/lookup-dependent-bases.cpp | 63 +- .../ms-lookup-template-base-classes.cpp | 34 +- test/SemaTemplate/pack-deduction.cpp | 28 + test/SemaTemplate/temp_arg_enum_printing.cpp | 24 + test/SemaTemplate/temp_arg_nontype_cxx1z.cpp | 150 ++ test/SemaTemplate/virtual-member-functions.cpp | 26 +- .../auto-detect-from-source-parent-of-cwd.cpp | 3 - test/Tooling/auto-detect-from-source-parent.cpp | 6 +- test/Tooling/auto-detect-from-source.cpp | 6 +- test/Tooling/clang-check-autodetect-dir.cpp | 6 +- test/Tooling/clang-check-pwd.cpp | 3 - test/Tooling/pch.cpp | 1 - test/VFS/external-names.c | 4 +- test/VFS/umbrella-mismatch.m | 3 +- test/lit.cfg | 27 +- tools/arcmt-test/arcmt-test.cpp | 7 +- tools/c-arcmt-test/CMakeLists.txt | 12 +- tools/c-arcmt-test/Makefile | 1 + tools/c-index-test/CMakeLists.txt | 10 +- tools/c-index-test/Makefile | 1 + tools/c-index-test/c-index-test.c | 48 +- tools/clang-check/ClangCheck.cpp | 74 +- tools/clang-format-vs/CMakeLists.txt | 7 +- .../clang-format-vs/ClangFormat/ClangFormat.csproj | 5 +- tools/clang-format-vs/README.txt | 11 +- .../source.extension.vsixmanifest.in | 5 + tools/clang-format/CMakeLists.txt | 3 +- tools/clang-format/ClangFormat.cpp | 12 +- tools/clang-format/Makefile | 4 +- tools/clang-format/clang-format-diff.py | 8 +- tools/clang-format/clang-format.el | 209 +- tools/clang-format/clang-format.py | 7 +- tools/clang-format/git-clang-format | 2 +- tools/diagtool/DiagTool.cpp | 2 +- tools/diagtool/DiagTool.h | 4 +- tools/diagtool/DiagnosticNames.h | 4 + tools/diagtool/ListWarnings.cpp | 9 +- tools/diagtool/ShowEnabledWarnings.cpp | 2 +- tools/driver/cc1_main.cpp | 10 +- tools/driver/cc1as_main.cpp | 42 +- tools/driver/driver.cpp | 394 ++-- tools/libclang/ARCMigrate.cpp | 4 +- tools/libclang/CIndex.cpp | 203 +- tools/libclang/CIndexCodeCompletion.cpp | 4 +- tools/libclang/CIndexDiagnostic.cpp | 29 +- tools/libclang/CIndexDiagnostic.h | 27 +- tools/libclang/CIndexUSRs.cpp | 2 +- tools/libclang/CIndexer.h | 4 +- tools/libclang/CLog.h | 4 +- tools/libclang/CMakeLists.txt | 2 +- tools/libclang/CXComment.cpp | 2 +- tools/libclang/CXComment.h | 6 +- tools/libclang/CXCompilationDatabase.cpp | 6 +- tools/libclang/CXCursor.cpp | 167 +- tools/libclang/CXCursor.h | 4 +- tools/libclang/CXLoadedDiagnostic.cpp | 591 ++--- tools/libclang/CXLoadedDiagnostic.h | 4 +- tools/libclang/CXSourceLocation.h | 4 +- tools/libclang/CXString.h | 4 +- tools/libclang/CXTranslationUnit.h | 4 +- tools/libclang/CXType.cpp | 1 + tools/libclang/CXType.h | 4 +- tools/libclang/CursorVisitor.h | 4 +- tools/libclang/IndexBody.cpp | 2 +- tools/libclang/IndexTypeSourceInfo.cpp | 1 + tools/libclang/Index_Internal.h | 4 +- tools/libclang/Indexing.cpp | 21 +- tools/libclang/IndexingContext.h | 5 + tools/libclang/Makefile | 4 +- tools/libclang/libclang.exports | 8 + tools/scan-build/c++-analyzer.bat | 1 + tools/scan-build/ccc-analyzer | 24 + tools/scan-build/ccc-analyzer.bat | 1 + tools/scan-build/scan-build | 171 +- unittests/AST/ASTTypeTraitsTest.cpp | 39 + unittests/AST/ASTVectorTest.cpp | 74 +- unittests/AST/CommentLexer.cpp | 4 +- unittests/AST/CommentParser.cpp | 4 +- unittests/AST/DeclPrinterTest.cpp | 35 +- unittests/AST/EvaluateAsRValueTest.cpp | 15 +- unittests/AST/ExternalASTSourceTest.cpp | 8 +- unittests/AST/MatchVerifier.h | 18 +- unittests/AST/NamedDeclPrinterTest.cpp | 4 +- unittests/AST/SourceLocationTest.cpp | 12 + unittests/ASTMatchers/ASTMatchersTest.cpp | 273 ++- unittests/ASTMatchers/ASTMatchersTest.h | 87 +- unittests/ASTMatchers/Dynamic/ParserTest.cpp | 75 +- unittests/ASTMatchers/Dynamic/RegistryTest.cpp | 60 +- unittests/Basic/CMakeLists.txt | 1 + unittests/Basic/DiagnosticTest.cpp | 49 + unittests/Basic/FileManagerTest.cpp | 37 +- unittests/Basic/SourceManagerTest.cpp | 30 +- unittests/Basic/VirtualFileSystemTest.cpp | 17 +- unittests/CMakeLists.txt | 1 + unittests/CodeGen/BufferSourceTest.cpp | 78 + unittests/CodeGen/CMakeLists.txt | 15 + unittests/CodeGen/Makefile | 20 + unittests/Format/CMakeLists.txt | 3 +- unittests/Format/FormatTest.cpp | 1116 ++++++++-- unittests/Format/FormatTestJS.cpp | 202 +- unittests/Format/FormatTestJava.cpp | 492 ++++ unittests/Format/FormatTestProto.cpp | 53 +- unittests/Format/FormatTestUtils.h | 6 +- unittests/Format/Makefile | 4 +- unittests/Frontend/CMakeLists.txt | 2 + unittests/Frontend/FrontendActionTest.cpp | 106 +- unittests/Lex/CMakeLists.txt | 1 - unittests/Lex/LexerTest.cpp | 4 +- unittests/Lex/PPCallbacksTest.cpp | 18 +- unittests/Lex/PPConditionalDirectiveRecordTest.cpp | 6 +- unittests/Makefile | 5 +- unittests/Sema/ExternalSemaSourceTest.cpp | 6 +- unittests/Tooling/CMakeLists.txt | 5 + unittests/Tooling/Makefile | 3 +- unittests/Tooling/RecursiveASTVisitorTest.cpp | 525 +---- .../Tooling/RecursiveASTVisitorTestCallVisitor.cpp | 121 + .../Tooling/RecursiveASTVisitorTestDeclVisitor.cpp | 141 ++ .../Tooling/RecursiveASTVisitorTestExprVisitor.cpp | 224 ++ .../RecursiveASTVisitorTestTypeLocVisitor.cpp | 93 + unittests/Tooling/RefactoringTest.cpp | 23 +- unittests/Tooling/RewriterTestContext.h | 17 +- unittests/Tooling/TestVisitor.h | 12 +- unittests/Tooling/ToolingTest.cpp | 85 +- unittests/libclang/LibclangTest.cpp | 2 +- unittests/libclang/Makefile | 1 + utils/ABITest/ABITestGen.py | 2 +- utils/ABITest/TypeGen.py | 6 +- utils/TableGen/ClangAttrEmitter.cpp | 248 ++- utils/TableGen/NeonEmitter.cpp | 8 +- utils/TableGen/TableGenBackends.h | 5 + utils/analyzer/SATestBuild.py | 2 +- www/analyzer/open_projects.html | 2 +- www/analyzer/potential_checkers.html | 44 +- www/analyzer/scan-build.html | 31 +- www/compatibility.html | 20 +- www/cxx_dr_status.html | 1962 ++++++++++------ www/cxx_status.html | 82 +- www/make_cxx_dr_status | 4 +- 2304 files changed, 104566 insertions(+), 34078 deletions(-) create mode 100644 .clang-tidy create mode 100644 cmake/modules/ClangConfig.cmake create mode 100644 include/clang/Analysis/CodeInjector.h create mode 100644 include/clang/Basic/BuiltinsLe64.def create mode 100644 include/clang/Basic/SanitizerBlacklist.h create mode 100644 include/clang/Basic/Sanitizers.h create mode 100644 include/clang/Frontend/SerializedDiagnosticReader.h create mode 100644 include/clang/Frontend/SerializedDiagnostics.h create mode 100644 include/clang/StaticAnalyzer/Frontend/ModelConsumer.h create mode 100644 include/clang/Tooling/Core/Replacement.h delete mode 100644 lib/AST/MangleNumberingContext.cpp create mode 100644 lib/Analysis/CodeInjector.cpp create mode 100644 lib/Basic/SanitizerBlacklist.cpp create mode 100644 lib/Basic/Sanitizers.cpp create mode 100644 lib/CodeGen/CoverageMappingGen.cpp create mode 100644 lib/CodeGen/CoverageMappingGen.h delete mode 100644 lib/CodeGen/SanitizerBlacklist.cpp delete mode 100644 lib/CodeGen/SanitizerBlacklist.h create mode 100644 lib/CodeGen/SanitizerMetadata.cpp create mode 100644 lib/CodeGen/SanitizerMetadata.h create mode 100644 lib/Driver/CrossWindowsToolChain.cpp create mode 100644 lib/Driver/MSVCToolChain.cpp delete mode 100644 lib/Driver/WindowsToolChain.cpp create mode 100644 lib/Format/UnwrappedLineFormatter.cpp create mode 100644 lib/Format/UnwrappedLineFormatter.h create mode 100644 lib/Frontend/CodeGenOptions.cpp create mode 100644 lib/Frontend/SerializedDiagnosticReader.cpp create mode 100644 lib/Headers/__stddef_max_align_t.h create mode 100644 lib/Headers/adxintrin.h create mode 100644 lib/Headers/avx512bwintrin.h create mode 100644 lib/Headers/avx512erintrin.h create mode 100644 lib/Headers/avx512fintrin.h create mode 100644 lib/Headers/avx512vlbwintrin.h create mode 100644 lib/Headers/avx512vlintrin.h create mode 100644 lib/Headers/stdatomic.h create mode 100644 lib/Headers/vadefs.h create mode 100644 lib/Sema/SemaCUDA.cpp create mode 100644 lib/StaticAnalyzer/Frontend/ModelConsumer.cpp create mode 100644 lib/StaticAnalyzer/Frontend/ModelInjector.cpp create mode 100644 lib/StaticAnalyzer/Frontend/ModelInjector.h create mode 100644 lib/Tooling/Core/CMakeLists.txt create mode 100644 lib/Tooling/Core/Makefile create mode 100644 lib/Tooling/Core/Replacement.cpp create mode 100644 test/ARCMT/objcmt-property-dot-syntax.m create mode 100644 test/ARCMT/objcmt-property-dot-syntax.m.result create mode 100644 test/ARCMT/objcmt-undefined-ns-macros.m create mode 100644 test/ARCMT/objcmt-undefined-ns-macros.m.result create mode 100644 test/Analysis/Inputs/Models/modeledFunction.model create mode 100644 test/Analysis/Inputs/Models/notzero.model create mode 100644 test/Analysis/Inputs/system-header-simulator-for-pthread-lock.h create mode 100644 test/Analysis/NewDeleteLeaks-PR19102.cpp create mode 100644 test/Analysis/disable-all-checks.c create mode 100644 test/Analysis/malloc-protoype.c create mode 100644 test/Analysis/malloc-sizeof.cpp create mode 100644 test/Analysis/model-file.cpp create mode 100644 test/Analysis/unix-api.c create mode 100644 test/Analysis/vla.c create mode 100644 test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.general/p8.cpp create mode 100644 test/CXX/drs/dr16xx.cpp create mode 100644 test/CXX/drs/dr18xx.cpp create mode 100644 test/CXX/drs/dr6xx.cpp create mode 100644 test/CXX/except/except.spec/p5-delayed.cpp create mode 100644 test/CodeGen/24-bit.c create mode 100644 test/CodeGen/aarch64-fix-cortex-a53-835769.c create mode 100644 test/CodeGen/adc-builtins.c create mode 100644 test/CodeGen/address-sanitizer-and-array-cookie.cpp create mode 100644 test/CodeGen/adx-builtins.c create mode 100644 test/CodeGen/align_value.cpp create mode 100644 test/CodeGen/arm-neon-directed-rounding.c create mode 100644 test/CodeGen/arm-neon-numeric-maxmin.c create mode 100644 test/CodeGen/avx512bw-builtins.c create mode 100644 test/CodeGen/avx512f-builtins.c create mode 100644 test/CodeGen/avx512vl-builtins.c create mode 100644 test/CodeGen/avx512vlbw-builtins.c create mode 100644 test/CodeGen/block-with-perdefinedexpr.c create mode 100644 test/CodeGen/builtin-assume-aligned.c delete mode 100644 test/CodeGen/builtin-recursive.cc create mode 100644 test/CodeGen/builtin-recursive.cpp create mode 100644 test/CodeGen/builtins-arm-msvc-compat-error.c create mode 100644 test/CodeGen/builtins-arm-msvc-compat-only.c create mode 100644 test/CodeGen/builtins-ppc-vsx.c create mode 100644 test/CodeGen/complex-math.c create mode 100644 test/CodeGen/debug-info-block-out-return.c create mode 100644 test/CodeGen/ext-vector-indexing.c create mode 100644 test/CodeGen/fp128_complex.c create mode 100644 test/CodeGen/fsgsbase-builtins.c create mode 100644 test/CodeGen/mangle-blocks.c create mode 100644 test/CodeGen/mips-transparent-union.c create mode 100644 test/CodeGen/ms-align-tentative.c create mode 100644 test/CodeGen/ms-inline-asm-functions.c create mode 100644 test/CodeGen/piclevels.c create mode 100644 test/CodeGen/ppc-signbit.c create mode 100644 test/CodeGen/ppc-varargs-struct.c create mode 100644 test/CodeGen/ppc64-elf-abi.c delete mode 100644 test/CodeGen/ppc64-varargs-struct.c create mode 100644 test/CodeGen/sanitize-address-field-padding.cpp delete mode 100644 test/CodeGen/sections.c create mode 100644 test/CodeGen/variadic-null-win64.c create mode 100644 test/CodeGen/vectorcall.c create mode 100644 test/CodeGen/vlt_to_pointer.c create mode 100644 test/CodeGen/windows-struct-abi.c create mode 100644 test/CodeGen/x86-atomic-long_double.c create mode 100644 test/CodeGen/x86_64-arguments-win32.c create mode 100644 test/CodeGenCXX/align-avx-complete-objects.cpp create mode 100644 test/CodeGenCXX/call-with-static-chain.cpp create mode 100644 test/CodeGenCXX/ctor-globalopt.cpp create mode 100644 test/CodeGenCXX/cxx1y-variable-template-linkage.cpp create mode 100644 test/CodeGenCXX/cxx1z-fold-expression.cpp create mode 100644 test/CodeGenCXX/debug-info-access.cpp create mode 100644 test/CodeGenCXX/debug-info-line.cpp create mode 100644 test/CodeGenCXX/debug-info-ptr-to-member-function.cpp create mode 100644 test/CodeGenCXX/debug-info-windows-dtor.cpp create mode 100644 test/CodeGenCXX/dllexport-alias.cpp create mode 100644 test/CodeGenCXX/homogeneous-aggregates.cpp create mode 100644 test/CodeGenCXX/mangle-literal-suffix.cpp create mode 100644 test/CodeGenCXX/mangle-local-anonymous-unions.cpp create mode 100644 test/CodeGenCXX/merge-functions.cpp create mode 100644 test/CodeGenCXX/microsoft-abi-byval-thunks.cpp create mode 100644 test/CodeGenCXX/microsoft-abi-structors-delayed-template.cpp create mode 100644 test/CodeGenCXX/microsoft-abi-vmemptr-conflicts.cpp create mode 100644 test/CodeGenCXX/microsoft-abi-vmemptr-fastcall.cpp create mode 100644 test/CodeGenCXX/microsoft-uuidof-mangling.cpp create mode 100644 test/CodeGenCXX/mingw-w64-seh-exceptions.cpp create mode 100644 test/CodeGenCXX/ms-inline-asm-return.cpp create mode 100644 test/CodeGenCXX/ms-thread_local.cpp delete mode 100644 test/CodeGenCXX/nrvo-noreturn.cc create mode 100644 test/CodeGenCXX/nrvo-noreturn.cpp create mode 100644 test/CodeGenCXX/optnone-def-decl.cpp create mode 100644 test/CodeGenCXX/pr18635.cpp create mode 100644 test/CodeGenCXX/pr20719.cpp create mode 100644 test/CodeGenCXX/pr20897.cpp create mode 100644 test/CodeGenCXX/pr21989.cpp create mode 100644 test/CodeGenCXX/predefined-expr-cxx14.cpp create mode 100644 test/CodeGenCXX/sections.cpp create mode 100644 test/CodeGenCXX/vararg-non-pod-ms-compat.cpp create mode 100644 test/CodeGenCXX/vla-lambda-capturing.cpp create mode 100644 test/CodeGenCXX/vlt_to_reference.cpp create mode 100644 test/CodeGenCXX/vtable-align.cpp create mode 100644 test/CodeGenCXX/vtable-holder-self-reference.cpp create mode 100644 test/CodeGenCXX/x86_64-arguments-nacl-x32.cpp create mode 100644 test/CodeGenObjC/block-over-align.m create mode 100644 test/CodeGenObjC/debug-info-block-type.m create mode 100644 test/CodeGenObjC/debug-info-nested-blocks.m create mode 100644 test/CodeGenObjC/debug-info-variadic-method.m create mode 100644 test/CodeGenObjC/mangle-blocks.m create mode 100644 test/CodeGenObjC/private-extern-selector-reference.m create mode 100644 test/CodeGenObjC/undefined-protocol2.m create mode 100644 test/CodeGenObjCXX/arc-cxx11-init-list.mm create mode 100644 test/CodeGenObjCXX/block-id.mm create mode 100644 test/CodeGenObjCXX/debug-info-line.mm create mode 100644 test/CodeGenObjCXX/destroy.mm create mode 100644 test/CodeGenObjCXX/subst-sel.mm create mode 100644 test/CodeGenOpenCL/address-spaces-conversions.cl create mode 100644 test/CodeGenOpenCL/amdgpu-num-gpr-attr.cl create mode 100644 test/CodeGenOpenCL/const-str-array-decay.cl create mode 100644 test/CodeGenOpenCL/constant-addr-space-globals.cl create mode 100644 test/CodeGenOpenCL/denorms-are-zero.cl create mode 100644 test/CodeGenOpenCL/local-initializer-undef.cl create mode 100644 test/CodeGenOpenCL/relaxed-fpmath.cl create mode 100644 test/CoverageMapping/Inputs/code.h create mode 100644 test/CoverageMapping/Inputs/header1.h create mode 100644 test/CoverageMapping/break.c create mode 100644 test/CoverageMapping/builtinmacro.c create mode 100644 test/CoverageMapping/casts.c create mode 100644 test/CoverageMapping/classtemplate.cpp create mode 100644 test/CoverageMapping/continue.c create mode 100644 test/CoverageMapping/header.cpp create mode 100644 test/CoverageMapping/if.c create mode 100644 test/CoverageMapping/includehell.cpp create mode 100644 test/CoverageMapping/ir.c create mode 100644 test/CoverageMapping/label.cpp create mode 100644 test/CoverageMapping/logical.cpp create mode 100644 test/CoverageMapping/loopmacro.c create mode 100644 test/CoverageMapping/loops.cpp create mode 100644 test/CoverageMapping/macroception.c create mode 100644 test/CoverageMapping/macroparams.c create mode 100644 test/CoverageMapping/macroparams2.c create mode 100644 test/CoverageMapping/macros.c create mode 100644 test/CoverageMapping/nestedclass.cpp create mode 100644 test/CoverageMapping/objc.m create mode 100644 test/CoverageMapping/preprocessor.c create mode 100644 test/CoverageMapping/return.c create mode 100644 test/CoverageMapping/switch.c create mode 100644 test/CoverageMapping/templates.cpp create mode 100644 test/CoverageMapping/test.c create mode 100644 test/CoverageMapping/trycatch.cpp create mode 100755 test/Driver/Inputs/Windows/ARM/8.1/usr/bin/armv7-windows-itanium-ld create mode 100644 test/Driver/Inputs/basic_netbsd_tree/usr/lib/eabihf/crti.o create mode 100644 test/Driver/Inputs/basic_netbsd_tree/usr/lib/powerpc/crti.o create mode 100644 test/Driver/Inputs/cc1-response.txt create mode 100644 test/Driver/Inputs/gen-response.c create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/include-fixed/uclibc/el/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/include-fixed/uclibc/nan2008/el/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/include-fixed/uclibc/soft-float/el/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/crtbegin.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/crtend.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/el/crtbegin.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/el/crtend.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/nan2008/crtbegin.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/nan2008/crtend.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/nan2008/el/crtbegin.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/nan2008/el/crtend.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/soft-float/crtbegin.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/soft-float/crtend.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/soft-float/el/crtbegin.o create mode 100644 test/Driver/Inputs/mips_cs_tree/lib/gcc/mips-linux-gnu/4.6.3/uclibc/soft-float/el/crtend.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/lib/uclibc/el/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/lib/uclibc/nan2008/el/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/lib/uclibc/soft-float/el/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/el/lib/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/el/usr/include/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/el/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/el/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/el/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/lib/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/el/lib/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/el/usr/include/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/el/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/el/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/el/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/lib/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/usr/include/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/nan2008/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/el/lib/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/el/usr/include/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/el/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/el/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/el/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/lib/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/usr/include/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/soft-float/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/usr/include/.keep create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_cs_tree/mips-linux-gnu/libc/uclibc/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/crtbegin.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/crtend.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/el/crtbegin.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/el/crtend.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/el/nan2008/crtbegin.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/el/nan2008/crtend.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/el/sof/crtbegin.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/el/sof/crtend.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/nan2008/crtbegin.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/nan2008/crtend.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/sof/crtbegin.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/lib/gcc/mips-mti-linux-gnu/4.9.0/uclibc/sof/crtend.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/include/c++/4.9.0/mips-mti-linux-gnu/uclibc/el/nan2008/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/include/c++/4.9.0/mips-mti-linux-gnu/uclibc/el/sof/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/include/c++/4.9.0/mips-mti-linux-gnu/uclibc/nan2008/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/include/c++/4.9.0/mips-mti-linux-gnu/uclibc/sof/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/lib/uclibc/el/nan2008/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/lib/uclibc/el/sof/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/lib/uclibc/nan2008/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/mips-mti-linux-gnu/lib/uclibc/sof/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/nan2008/usr/include/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/nan2008/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/nan2008/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/nan2008/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/sof/usr/include/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/sof/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/sof/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/sof/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/usr/include/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/el/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/nan2008/usr/include/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/nan2008/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/nan2008/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/nan2008/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/sof/usr/include/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/sof/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/sof/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/sof/usr/lib/crtn.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/usr/include/bits/.keep create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/usr/lib/crt1.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/usr/lib/crti.o create mode 100644 test/Driver/Inputs/mips_fsf_tree/sysroot/uclibc/usr/lib/crtn.o create mode 100644 test/Driver/aarch64-fix-cortex-a53-835769.c create mode 100644 test/Driver/arm-abi.c create mode 100644 test/Driver/biarch.c create mode 100644 test/Driver/cc1-response-files.c create mode 100644 test/Driver/cl-link-at-file.c create mode 100644 test/Driver/cl-zc.cpp create mode 100644 test/Driver/clang-s-opts.s create mode 100644 test/Driver/coverage_no_integrated_as.c create mode 100644 test/Driver/crash report spaces.c create mode 100644 test/Driver/crash-report-null.test create mode 100644 test/Driver/darwin-ld-demangle.c create mode 100644 test/Driver/darwin-max-type-align.c create mode 100644 test/Driver/default-image-name.c create mode 100644 test/Driver/env.c create mode 100644 test/Driver/fatal-warnings.c create mode 100644 test/Driver/fortran.f95 delete mode 100644 test/Driver/freebsd.cc create mode 100644 test/Driver/freebsd.cpp create mode 100644 test/Driver/le64-unknown-unknown.cpp create mode 100644 test/Driver/no-canonical-prefixes.c create mode 100644 test/Driver/parse-progname.c create mode 100644 test/Driver/ppc-abi.c create mode 100644 test/Driver/response-file.c create mode 100644 test/Driver/rewrite-map-in-diagnostics.c create mode 100644 test/Driver/symbol-rewriter.c create mode 100644 test/Driver/systemz-as.s create mode 100644 test/Driver/thread-model.c create mode 100644 test/Driver/windows-cross.c create mode 100644 test/Driver/x86-march.c create mode 100644 test/FixIt/fixit-class-method-messaging.m create mode 100644 test/FixIt/multiarg-selector-fixit.m create mode 100644 test/FixIt/property-access-fixit.m create mode 100644 test/Frontend/Inputs/profile-sample-use-loc-tracking.prof create mode 100644 test/Frontend/profile-sample-use-loc-tracking.c create mode 100644 test/Frontend/source-col-map.c create mode 100644 test/Frontend/std.cl create mode 100644 test/Frontend/trigraphs.cpp create mode 100644 test/Frontend/verify-unknown-arg.c create mode 100644 test/Frontend/x86-target-cpu.c create mode 100644 test/Headers/altivec-intrin.c create mode 100644 test/Headers/cpuid.c create mode 100644 test/Index/Inputs/complete-at-EOF.c create mode 100644 test/Index/Inputs/declare-objc-predef.h create mode 100644 test/Index/Inputs/module-undef.h create mode 100644 test/Index/comment-lots-of-unknown-commands.c create mode 100644 test/Index/complete-at-EOF.c create mode 100644 test/Index/complete-module-undef.m create mode 100644 test/Index/print-mangled-name.cpp create mode 100644 test/Index/reparse-predef-objc-protocol.m create mode 100644 test/Layout/itanium-union-bitfield.cpp create mode 100644 test/Layout/ms-x86-empty-layout.c create mode 100644 test/Lexer/ms-compatibility.c create mode 100644 test/Misc/ast-dump-invalid.cpp create mode 100644 test/Misc/ast-dump-lookups.cpp create mode 100644 test/Misc/ast-print-objectivec.m create mode 100644 test/Misc/attr-source-range.cpp create mode 100644 test/Misc/diag-special-chars.c create mode 100644 test/Misc/serialized-diags-driver.c create mode 100644 test/Modules/Inputs/AddRemovePrivate.framework/Headers/AddRemovePrivate.h create mode 100644 test/Modules/Inputs/AddRemovePrivate.framework/Modules/module.modulemap create mode 100644 test/Modules/Inputs/AddRemovePrivate.framework/Modules/module.private.modulemap create mode 100644 test/Modules/Inputs/PR20399/FirstHeader.h create mode 100644 test/Modules/Inputs/PR20399/SecondHeader.h create mode 100644 test/Modules/Inputs/PR20399/module.modulemap create mode 100644 test/Modules/Inputs/PR20399/stl_map.h create mode 100644 test/Modules/Inputs/PR20399/vector create mode 100644 test/Modules/Inputs/PR20786/TBranchProxy.h create mode 100644 test/Modules/Inputs/PR20786/TFormula.h create mode 100644 test/Modules/Inputs/PR20786/TMath.h create mode 100644 test/Modules/Inputs/PR20786/module.modulemap create mode 100644 test/Modules/Inputs/PR20786/random.h create mode 100644 test/Modules/Inputs/StdDef/include_again.h create mode 100644 test/Modules/Inputs/StdDef/ptrdiff_t.h create mode 100644 test/Modules/Inputs/attr-unavailable/module.modulemap create mode 100644 test/Modules/Inputs/attr-unavailable/oneA.h create mode 100644 test/Modules/Inputs/attr-unavailable/oneB.h create mode 100644 test/Modules/Inputs/attr-unavailable/oneC.h create mode 100644 test/Modules/Inputs/attr-unavailable/two.h create mode 100644 test/Modules/Inputs/cxx-decls-premerged.h create mode 100644 test/Modules/Inputs/cxx-lookup/a.h create mode 100644 test/Modules/Inputs/cxx-lookup/b.h create mode 100644 test/Modules/Inputs/cxx-lookup/c1.h create mode 100644 test/Modules/Inputs/cxx-lookup/c2.h create mode 100644 test/Modules/Inputs/cxx-lookup/module.modulemap create mode 100644 test/Modules/Inputs/cxx-lookup/x.h create mode 100644 test/Modules/Inputs/cxx-lookup/y.h create mode 100644 test/Modules/Inputs/cxx-templates-d.h create mode 100644 test/Modules/Inputs/cxx-templates-textual.h create mode 100644 test/Modules/Inputs/declare-use/k.h create mode 100644 test/Modules/Inputs/declare-use/l.h create mode 100644 test/Modules/Inputs/declare-use/m.h create mode 100644 test/Modules/Inputs/declare-use/m2.h create mode 100644 test/Modules/Inputs/dependency-gen-base.modulemap create mode 100644 test/Modules/Inputs/dependency-gen-base2.modulemap create mode 100644 test/Modules/Inputs/dependency-gen-included.h create mode 100644 test/Modules/Inputs/dependency-gen-included2.h create mode 100644 test/Modules/Inputs/dependency-gen.h create mode 100644 test/Modules/Inputs/explicit-build/a.h create mode 100644 test/Modules/Inputs/explicit-build/b.h create mode 100644 test/Modules/Inputs/explicit-build/c.h create mode 100644 test/Modules/Inputs/explicit-build/module.modulemap create mode 100644 test/Modules/Inputs/filename/a.h create mode 100644 test/Modules/Inputs/filename/module.map create mode 100644 test/Modules/Inputs/include_next/x/a.h create mode 100644 test/Modules/Inputs/include_next/x/module.modulemap create mode 100644 test/Modules/Inputs/include_next/x/subdir/b.h create mode 100644 test/Modules/Inputs/include_next/y/a.h create mode 100644 test/Modules/Inputs/include_next/y/b.h create mode 100644 test/Modules/Inputs/include_next/y/module.modulemap create mode 100644 test/Modules/Inputs/inferred-attr/InferredExternC.framework/Headers/InferredExternC.h create mode 100644 test/Modules/Inputs/inferred-attr/module.modulemap create mode 100644 test/Modules/Inputs/macros_bottom.h create mode 100644 test/Modules/Inputs/malformed/c.h create mode 100644 test/Modules/Inputs/merge-typedefs/a1.h create mode 100644 test/Modules/Inputs/merge-typedefs/a2.h create mode 100644 test/Modules/Inputs/merge-typedefs/b1.h create mode 100644 test/Modules/Inputs/merge-typedefs/b2.h create mode 100644 test/Modules/Inputs/merge-typedefs/module.modulemap create mode 100644 test/Modules/Inputs/merge-using-decls/a.h create mode 100644 test/Modules/Inputs/merge-using-decls/b.h create mode 100644 test/Modules/Inputs/merge-using-decls/module.modulemap create mode 100644 test/Modules/Inputs/modular_maps-moduleb-cwd.map create mode 100644 test/Modules/Inputs/modular_maps/c.h create mode 100644 test/Modules/Inputs/modular_maps/modulea-cwd.map create mode 100644 test/Modules/Inputs/modular_maps/modulec-cwd.map create mode 100644 test/Modules/Inputs/modular_maps/modulec.map create mode 100644 test/Modules/Inputs/pr19692/AIX.h create mode 100644 test/Modules/Inputs/pr19692/Blah.h create mode 100644 test/Modules/Inputs/pr19692/TBlah.h create mode 100644 test/Modules/Inputs/pr19692/TFoo.h create mode 100644 test/Modules/Inputs/pr19692/module.map create mode 100644 test/Modules/Inputs/pr19692/stdint.h create mode 100644 test/Modules/Inputs/preprocess-prefix.h create mode 100644 test/Modules/Inputs/relative-dep-gen-1.h create mode 100644 test/Modules/Inputs/relative-dep-gen-2.h create mode 100644 test/Modules/Inputs/relative-dep-gen-cwd.modulemap create mode 100644 test/Modules/Inputs/relative-dep-gen.modulemap create mode 100644 test/Modules/Inputs/va_list/module.modulemap create mode 100644 test/Modules/Inputs/va_list/va_list_a.h create mode 100644 test/Modules/Inputs/va_list/va_list_b.h create mode 100644 test/Modules/Inputs/warn-unused-local-typedef.h create mode 100644 test/Modules/add-remove-private.m create mode 100644 test/Modules/attr-unavailable.m create mode 100644 test/Modules/cxx-lookup.cpp create mode 100644 test/Modules/dependency-gen.modulemap.cpp create mode 100644 test/Modules/explicit-build-flags.cpp create mode 100644 test/Modules/explicit-build-relpath.cpp create mode 100644 test/Modules/explicit-build.cpp create mode 100644 test/Modules/filename.cpp create mode 100644 test/Modules/implementation-of-module.m create mode 100644 test/Modules/include_next.c create mode 100644 test/Modules/inferred-attributes.mm create mode 100644 test/Modules/macro-reexport/e1.h create mode 100644 test/Modules/macro-reexport/e2.h create mode 100644 test/Modules/macro-reexport/f1.h create mode 100644 test/Modules/merge-typedefs.cpp create mode 100644 test/Modules/merge-using-decls.cpp create mode 100644 test/Modules/no-implicit-maps.cpp create mode 100644 test/Modules/pr19692.cpp create mode 100644 test/Modules/pr20399.cpp create mode 100644 test/Modules/pr20786.cpp create mode 100644 test/Modules/pr21217.cpp create mode 100644 test/Modules/preprocess.m create mode 100644 test/Modules/rebuild.m create mode 100644 test/Modules/relative-dep-gen.cpp create mode 100644 test/Modules/stddef.c create mode 100644 test/Modules/templates-2.mm create mode 100644 test/Modules/textual-headers.cpp create mode 100644 test/Modules/va_list.m create mode 100644 test/Modules/warn-unused-local-typedef.cpp create mode 100644 test/OpenMP/atomic_ast_print.cpp create mode 100644 test/OpenMP/atomic_messages.c create mode 100644 test/OpenMP/atomic_messages.cpp create mode 100644 test/OpenMP/barrier_codegen.cpp create mode 100644 test/OpenMP/critical_codegen.cpp create mode 100644 test/OpenMP/flush_codegen.cpp create mode 100644 test/OpenMP/for_codegen.cpp create mode 100644 test/OpenMP/for_simd_aligned_messages.cpp create mode 100644 test/OpenMP/for_simd_ast_print.cpp create mode 100644 test/OpenMP/for_simd_collapse_messages.cpp create mode 100644 test/OpenMP/for_simd_firstprivate_messages.cpp create mode 100644 test/OpenMP/for_simd_lastprivate_messages.cpp create mode 100644 test/OpenMP/for_simd_linear_messages.cpp create mode 100644 test/OpenMP/for_simd_loop_messages.cpp create mode 100644 test/OpenMP/for_simd_misc_messages.c create mode 100644 test/OpenMP/for_simd_private_messages.cpp create mode 100644 test/OpenMP/for_simd_reduction_messages.cpp create mode 100644 test/OpenMP/for_simd_safelen_messages.cpp create mode 100644 test/OpenMP/for_simd_schedule_messages.cpp create mode 100644 test/OpenMP/master_codegen.cpp create mode 100644 test/OpenMP/ordered_ast_print.cpp create mode 100644 test/OpenMP/ordered_messages.cpp create mode 100644 test/OpenMP/parallel_firstprivate_codegen.cpp create mode 100644 test/OpenMP/parallel_for_simd_aligned_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_ast_print.cpp create mode 100644 test/OpenMP/parallel_for_simd_collapse_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_copyin_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_default_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_firstprivate_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_if_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_lastprivate_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_linear_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_loop_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_misc_messages.c create mode 100644 test/OpenMP/parallel_for_simd_num_threads_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_private_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_proc_bind_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_reduction_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_safelen_messages.cpp create mode 100644 test/OpenMP/parallel_for_simd_schedule_messages.cpp create mode 100644 test/OpenMP/parallel_if_codegen.cpp create mode 100644 test/OpenMP/parallel_num_threads_codegen.cpp create mode 100644 test/OpenMP/parallel_private_codegen.cpp create mode 100644 test/OpenMP/simd_codegen.cpp create mode 100644 test/OpenMP/target_ast_print.cpp create mode 100644 test/OpenMP/target_if_messages.cpp create mode 100644 test/OpenMP/target_messages.cpp create mode 100644 test/OpenMP/teams_ast_print.cpp create mode 100644 test/OpenMP/teams_default_messages.cpp create mode 100644 test/OpenMP/teams_firstprivate_messages.cpp create mode 100644 test/OpenMP/teams_messages.cpp create mode 100644 test/OpenMP/teams_private_messages.cpp create mode 100644 test/OpenMP/teams_reduction_messages.cpp create mode 100644 test/OpenMP/teams_shared_messages.cpp create mode 100644 test/OpenMP/threadprivate_codegen.cpp create mode 100644 test/PCH/chain-openmp-threadprivate.cpp create mode 100644 test/Parser/PR21872.cpp create mode 100644 test/Parser/cxx11-templates.cpp create mode 100644 test/Parser/cxx1z-attributes.cpp create mode 100644 test/Parser/cxx1z-fold-expressions.cpp create mode 100644 test/Parser/cxx1z-nested-namespace-definition.cpp create mode 100644 test/Parser/debugger-import-module.m create mode 100644 test/Parser/eof2.cpp create mode 100644 test/Parser/ms-if-exists.c delete mode 100644 test/Parser/nested-namespaces-recovery.cpp create mode 100644 test/Parser/opencl-cl20.cl create mode 100644 test/Parser/vsx.c create mode 100644 test/Preprocessor/arm-acle-6.5.c create mode 100644 test/Preprocessor/has_attribute.cpp create mode 100644 test/Preprocessor/macro-reserved-cxx11.cpp create mode 100644 test/Preprocessor/macro-reserved-ms.c create mode 100644 test/Preprocessor/macro-reserved.c create mode 100644 test/Preprocessor/macro-reserved.cpp create mode 100644 test/Profile/Inputs/c-general.profdata.v1 create mode 100644 test/Profile/c-unreachable-after-switch.c delete mode 100644 test/Sema/128bitfloat.cc create mode 100644 test/Sema/128bitfloat.cpp create mode 100644 test/Sema/align_value.c create mode 100644 test/Sema/attr-flag-enum.c create mode 100644 test/Sema/attr-nonnull.c create mode 100644 test/Sema/builtin-assume-aligned.c create mode 100644 test/Sema/builtins-x86.c create mode 100644 test/Sema/call-with-static-chain.c create mode 100644 test/Sema/decl-microsoft-call-conv.c create mode 100644 test/Sema/gnu-attributes.c create mode 100644 test/Sema/inline-asm-validate-aarch64.c create mode 100644 test/Sema/inline-asm-validate-x86.c create mode 100644 test/Sema/sizeof-struct-non-zero-as-member.cl create mode 100644 test/Sema/typo-correction.c create mode 100644 test/Sema/warn-cast-qual.c create mode 100644 test/Sema/warn-string-conversion.c create mode 100644 test/Sema/warn-tautological-compare.c create mode 100644 test/SemaCUDA/amdgpu-num-gpr-attr.cu create mode 100644 test/SemaCUDA/implicit-copy.cu create mode 100644 test/SemaCUDA/implicit-intrinsic.cu create mode 100644 test/SemaCUDA/implicit-member-target-collision-cxx11.cu create mode 100644 test/SemaCUDA/implicit-member-target-collision.cu create mode 100644 test/SemaCUDA/implicit-member-target.cu create mode 100644 test/SemaCUDA/method-target.cu create mode 100644 test/SemaCXX/Inputs/header-with-pragma-optimize-off.h create mode 100644 test/SemaCXX/Inputs/override-system-header.h create mode 100644 test/SemaCXX/MicrosoftSuper.cpp create mode 100644 test/SemaCXX/PR20705.cpp create mode 100644 test/SemaCXX/align_value.cpp create mode 100644 test/SemaCXX/attr-cxx0x-fixit.cpp create mode 100644 test/SemaCXX/attr-flag-enum-reject.cpp create mode 100644 test/SemaCXX/attr-gnu.cpp create mode 100644 test/SemaCXX/attributed-auto-deduction.cpp create mode 100644 test/SemaCXX/bitfield.cpp create mode 100644 test/SemaCXX/builtin-assume-aligned-tmpl.cpp create mode 100644 test/SemaCXX/builtin-assume-aligned.cpp create mode 100644 test/SemaCXX/call-with-static-chain.cpp create mode 100644 test/SemaCXX/complex-folding.cpp create mode 100644 test/SemaCXX/cxx-deprecated.cpp delete mode 100644 test/SemaCXX/cxx0x-initializer-stdinitializerlist-system-header.cpp create mode 100644 test/SemaCXX/cxx11-thread-unsupported.cpp create mode 100644 test/SemaCXX/devirtualize-vtable-marking.cpp create mode 100644 test/SemaCXX/libstdcxx_explicit_init_list_hack.cpp create mode 100644 test/SemaCXX/libstdcxx_pair_swap_hack.cpp create mode 100644 test/SemaCXX/override-in-system-header.cpp create mode 100644 test/SemaCXX/typo-correction-delayed.cpp delete mode 100644 test/SemaCXX/typo-correction-pt2.cpp delete mode 100644 test/SemaCXX/vtable-instantiation.cc create mode 100644 test/SemaCXX/vtable-instantiation.cpp create mode 100644 test/SemaCXX/warn-self-move.cpp create mode 100644 test/SemaCXX/warn-thread-safety-negative.cpp create mode 100644 test/SemaCXX/warn-thread-safety-verbose.cpp create mode 100644 test/SemaCXX/warn-unused-local-typedef-serialize.cpp create mode 100644 test/SemaCXX/warn-unused-local-typedef-x86asm.cpp create mode 100644 test/SemaCXX/warn-unused-local-typedef.cpp create mode 100644 test/SemaCXX/warn-unused-private-field-delayed-template.cpp create mode 100644 test/SemaCXX/warn-unused-value-cxx11.cpp create mode 100644 test/SemaObjC/attr-availability-1.m create mode 100644 test/SemaObjC/attr-deprecated-pch.m create mode 100644 test/SemaObjC/format-cstrings-warning.m create mode 100644 test/SemaObjC/objc-cf-audited-warning.m create mode 100644 test/SemaObjC/resolve-method-in-global-pool.m create mode 100644 test/SemaObjC/warn-category-method-deprecated.m create mode 100644 test/SemaObjC/warn-explicit-call-initialize.m create mode 100644 test/SemaObjCXX/synchronized.mm create mode 100644 test/SemaOpenCL/address-spaces-conversions-cl2.0.cl create mode 100644 test/SemaOpenCL/amdgpu-num-register-attrs.cl create mode 100644 test/SemaTemplate/crash.cpp create mode 100644 test/SemaTemplate/cxx1z-fold-expressions.cpp create mode 100644 test/SemaTemplate/enum-bool.cpp create mode 100644 test/SemaTemplate/instantiate-scope.cpp create mode 100644 test/SemaTemplate/temp_arg_enum_printing.cpp create mode 100644 test/SemaTemplate/temp_arg_nontype_cxx1z.cpp create mode 100644 tools/scan-build/c++-analyzer.bat create mode 100644 tools/scan-build/ccc-analyzer.bat create mode 100644 unittests/Basic/DiagnosticTest.cpp create mode 100644 unittests/CodeGen/BufferSourceTest.cpp create mode 100644 unittests/CodeGen/CMakeLists.txt create mode 100644 unittests/CodeGen/Makefile create mode 100644 unittests/Format/FormatTestJava.cpp create mode 100644 unittests/Tooling/RecursiveASTVisitorTestCallVisitor.cpp create mode 100644 unittests/Tooling/RecursiveASTVisitorTestDeclVisitor.cpp create mode 100644 unittests/Tooling/RecursiveASTVisitorTestExprVisitor.cpp create mode 100644 unittests/Tooling/RecursiveASTVisitorTestTypeLocVisitor.cpp diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..3186da4 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1 @@ +Checks: '-*,clang-diagnostic-*,llvm-*,misc-*' diff --git a/CMakeLists.txt b/CMakeLists.txt index 02374e2..75b8075 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,13 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) # They are used as destination of target generators. set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) - set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib) + set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) + if(WIN32 OR CYGWIN) + # DLL platform -- put DLLs into bin. + set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) + else() + set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) + endif() option(LLVM_INSTALL_TOOLCHAIN_ONLY "Only include toolchain files in the 'install' target." OFF) @@ -105,8 +111,8 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) link_directories("${LLVM_LIBRARY_DIR}") set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin ) - set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) - set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib ) + set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX} ) + set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX} ) if(LLVM_INCLUDE_TESTS) # Check prebuilt llvm/utils. @@ -193,6 +199,9 @@ endif() set(CLANG_VENDOR_UTI "org.llvm.clang" CACHE STRING "Vendor-specific uti.") +# The libdir suffix must exactly match whatever LLVM's configuration used. +set(CLANG_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}") + set(CLANG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) set(CLANG_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) @@ -240,7 +249,7 @@ configure_file( # Add appropriate flags for GCC if (LLVM_COMPILER_IS_GCC_COMPATIBLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-common -Woverloaded-virtual -fno-strict-aliasing") # Enable -pedantic for Clang even if it's not enabled for LLVM. if (NOT LLVM_ENABLE_PEDANTIC) @@ -253,6 +262,26 @@ if (LLVM_COMPILER_IS_GCC_COMPATIBLE) endif() endif () +# Determine HOST_LINK_VERSION on Darwin. +set(HOST_LINK_VERSION) +if (APPLE) + set(LD_V_OUTPUT) + execute_process( + COMMAND sh -c "${CMAKE_LINKER} -v 2>&1 | head -1" + RESULT_VARIABLE HAD_ERROR + OUTPUT_VARIABLE LD_V_OUTPUT + ) + if (NOT HAD_ERROR) + if ("${LD_V_OUTPUT}" MATCHES ".*ld64-([0-9.]+).*") + string(REGEX REPLACE ".*ld64-([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) + elseif ("${LD_V_OUTPUT}" MATCHES "[^0-9]*([0-9.]+).*") + string(REGEX REPLACE "[^0-9]*([0-9.]+).*" "\\1" HOST_LINK_VERSION ${LD_V_OUTPUT}) + endif() + else() + message(FATAL_ERROR "${CMAKE_LINKER} failed with status ${HAD_ERROR}") + endif() +endif() + configure_file( ${CLANG_SOURCE_DIR}/include/clang/Config/config.h.cmake ${CLANG_BINARY_DIR}/include/clang/Config/config.h) @@ -337,6 +366,7 @@ macro(add_clang_library name) ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX} RUNTIME DESTINATION bin) endif() + set_property(GLOBAL APPEND PROPERTY CLANG_EXPORTS ${name}) else() # Add empty "phony" target add_custom_target(${name}) @@ -478,3 +508,27 @@ endif() set(CLANG_ORDER_FILE "" CACHE FILEPATH "Order file to use when compiling clang in order to improve startup time.") + +if (CLANG_BUILT_STANDALONE) + # Generate a list of CMake library targets so that other CMake projects can + # link against them. LLVM calls its version of this file LLVMExports.cmake, but + # the usual CMake convention seems to be ${Project}Targets.cmake. + set(CLANG_INSTALL_PACKAGE_DIR share/clang/cmake) + set(clang_cmake_builddir "${CMAKE_BINARY_DIR}/${CLANG_INSTALL_PACKAGE_DIR}") + get_property(CLANG_EXPORTS GLOBAL PROPERTY CLANG_EXPORTS) + export(TARGETS ${CLANG_EXPORTS} FILE ${clang_cmake_builddir}/ClangTargets.cmake) + + # Install a /share/clang/cmake/ClangConfig.cmake file so that + # find_package(Clang) works. Install the target list with it. + install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/ClangConfig.cmake + ${CLANG_BINARY_DIR}/share/clang/cmake/ClangTargets.cmake + DESTINATION share/clang/cmake) + + # Also copy ClangConfig.cmake to the build directory so that dependent projects + # can build against a build directory of Clang more easily. + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/ClangConfig.cmake + ${CLANG_BINARY_DIR}/share/clang/cmake/ClangConfig.cmake + COPYONLY) +endif () diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT index bbd3142..b58014f 100644 --- a/CODE_OWNERS.TXT +++ b/CODE_OWNERS.TXT @@ -22,6 +22,7 @@ E: echristo@gmail.com D: Debug Information, autotools/configure/make build, inline assembly N: Doug Gregor +E: dgregor@apple.com D: All parts of Clang not covered by someone else N: Anton Korobeynikov @@ -29,6 +30,7 @@ E: anton@korobeynikov.info D: Exception handling, Windows codegen, ARM EABI N: Ted Kremenek +E: kremenek@apple.com D: Clang Static Analyzer N: John McCall @@ -37,7 +39,7 @@ D: Clang LLVM IR generation N: Chad Rosier E: mcrosier@codeaurora.org -D: MS-inline asm, and the compiler driver +D: Compiler driver N: Richard Smith E: richard@metafoo.co.uk diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py index 517b3c1..5792eff 100644 --- a/bindings/python/clang/cindex.py +++ b/bindings/python/clang/cindex.py @@ -496,24 +496,28 @@ class TokenKind(object): setattr(TokenKind, name, kind) ### Cursor Kinds ### - -class CursorKind(object): - """ - A CursorKind describes the kind of entity that a cursor points to. +class BaseEnumeration(object): """ + Common base class for named enumerations held in sync with Index.h values. - # The unique kind objects, indexed by id. + Subclasses must define their own _kinds and _name_map members, as: _kinds = [] _name_map = None + These values hold the per-subclass instances and value-to-name mappings, + respectively. + + """ def __init__(self, value): - if value >= len(CursorKind._kinds): - CursorKind._kinds += [None] * (value - len(CursorKind._kinds) + 1) - if CursorKind._kinds[value] is not None: - raise ValueError,'CursorKind already loaded' + if value >= len(self.__class__._kinds): + self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1) + if self.__class__._kinds[value] is not None: + raise ValueError,'{0} value {1} already loaded'.format( + str(self.__class__), value) self.value = value - CursorKind._kinds[value] = self - CursorKind._name_map = None + self.__class__._kinds[value] = self + self.__class__._name_map = None + def from_param(self): return self.value @@ -523,16 +527,29 @@ class CursorKind(object): """Get the enumeration name of this cursor kind.""" if self._name_map is None: self._name_map = {} - for key,value in CursorKind.__dict__.items(): - if isinstance(value,CursorKind): + for key, value in self.__class__.__dict__.items(): + if isinstance(value, self.__class__): self._name_map[value] = key return self._name_map[self] - @staticmethod - def from_id(id): - if id >= len(CursorKind._kinds) or CursorKind._kinds[id] is None: - raise ValueError,'Unknown cursor kind %d' % id - return CursorKind._kinds[id] + @classmethod + def from_id(cls, id): + if id >= len(cls._kinds) or cls._kinds[id] is None: + raise ValueError,'Unknown template argument kind %d' % id + return cls._kinds[id] + + def __repr__(self): + return '%s.%s' % (self.__class__, self.name,) + + +class CursorKind(BaseEnumeration): + """ + A CursorKind describes the kind of entity that a cursor points to. + """ + + # The required BaseEnumeration declarations. + _kinds = [] + _name_map = None @staticmethod def get_all_kinds(): @@ -578,11 +595,6 @@ class CursorKind(object): def __repr__(self): return 'CursorKind.%s' % (self.name,) -# FIXME: Is there a nicer way to expose this enumeration? We could potentially -# represent the nested structure, or even build a class hierarchy. The main -# things we want for sure are (a) simple external access to kinds, (b) a place -# to hang a description and name, (c) easy to keep in sync with Index.h. - ### # Declaration Kinds @@ -1086,6 +1098,7 @@ CursorKind.CUDACONSTANT_ATTR = CursorKind(412) CursorKind.CUDADEVICE_ATTR = CursorKind(413) CursorKind.CUDAGLOBAL_ATTR = CursorKind(414) CursorKind.CUDAHOST_ATTR = CursorKind(415) +CursorKind.CUDASHARED_ATTR = CursorKind(416) ### # Preprocessing @@ -1100,6 +1113,24 @@ CursorKind.INCLUSION_DIRECTIVE = CursorKind(503) # A module import declaration. CursorKind.MODULE_IMPORT_DECL = CursorKind(600) + +### Template Argument Kinds ### +class TemplateArgumentKind(BaseEnumeration): + """ + A TemplateArgumentKind describes the kind of entity that a template argument + represents. + """ + + # The required BaseEnumeration declarations. + _kinds = [] + _name_map = None + +TemplateArgumentKind.NULL = TemplateArgumentKind(0) +TemplateArgumentKind.TYPE = TemplateArgumentKind(1) +TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2) +TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3) +TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4) + ### Cursors ### class Cursor(Structure): @@ -1176,9 +1207,9 @@ class Cursor(Structure): """ Return the display name for the entity referenced by this cursor. - The display name contains extra information that helps identify the cursor, - such as the parameters of a function or template or the arguments of a - class template specialization. + The display name contains extra information that helps identify the + cursor, such as the parameters of a function or template or the + arguments of a class template specialization. """ if not hasattr(self, '_displayname'): self._displayname = conf.lib.clang_getCursorDisplayName(self) @@ -1186,6 +1217,14 @@ class Cursor(Structure): return self._displayname @property + def mangled_name(self): + """Return the mangled name for the entity referenced by this cursor.""" + if not hasattr(self, '_mangled_name'): + self._mangled_name = conf.lib.clang_Cursor_getMangling(self) + + return self._mangled_name + + @property def location(self): """ Return the source location (the starting character) of the entity @@ -1208,6 +1247,17 @@ class Cursor(Structure): return self._extent @property + def storage_class(self): + """ + Retrieves the storage class (if any) of the entity pointed at by the + cursor. + """ + if not hasattr(self, '_storage_class'): + self._storage_class = conf.lib.clang_Cursor_getStorageClass(self) + + return StorageClass.from_id(self._storage_class) + + @property def access_specifier(self): """ Retrieves the access specifier (if any) of the entity pointed at by the @@ -1369,6 +1419,27 @@ class Cursor(Structure): for i in range(0, num_args): yield conf.lib.clang_Cursor_getArgument(self, i) + def get_num_template_arguments(self): + """Returns the number of template args associated with this cursor.""" + return conf.lib.clang_Cursor_getNumTemplateArguments(self) + + def get_template_argument_kind(self, num): + """Returns the TemplateArgumentKind for the indicated template + argument.""" + return conf.lib.clang_Cursor_getTemplateArgumentKind(self, num) + + def get_template_argument_type(self, num): + """Returns the CXType for the indicated template argument.""" + return conf.lib.clang_Cursor_getTemplateArgumentType(self, num) + + def get_template_argument_value(self, num): + """Returns the value of the indicated arg as a signed 64b integer.""" + return conf.lib.clang_Cursor_getTemplateArgumentValue(self, num) + + def get_template_argument_unsigned_value(self, num): + """Returns the value of the indicated arg as an unsigned 64b integer.""" + return conf.lib.clang_Cursor_getTemplateArgumentUnsignedValue(self, num) + def get_children(self): """Return an iterator for accessing the children of this cursor.""" @@ -1450,11 +1521,9 @@ class Cursor(Structure): res._tu = args[0]._tu return res -### C++ access specifiers ### - -class AccessSpecifier(object): +class StorageClass(object): """ - Describes the access of a C++ class member + Describes the storage class of a declaration """ # The unique kind objects, index by id. @@ -1462,32 +1531,59 @@ class AccessSpecifier(object): _name_map = None def __init__(self, value): - if value >= len(AccessSpecifier._kinds): - AccessSpecifier._kinds += [None] * (value - len(AccessSpecifier._kinds) + 1) - if AccessSpecifier._kinds[value] is not None: - raise ValueError,'AccessSpecifier already loaded' + if value >= len(StorageClass._kinds): + StorageClass._kinds += [None] * (value - len(StorageClass._kinds) + 1) + if StorageClass._kinds[value] is not None: + raise ValueError,'StorageClass already loaded' self.value = value - AccessSpecifier._kinds[value] = self - AccessSpecifier._name_map = None + StorageClass._kinds[value] = self + StorageClass._name_map = None def from_param(self): return self.value @property def name(self): - """Get the enumeration name of this access specifier.""" + """Get the enumeration name of this storage class.""" if self._name_map is None: self._name_map = {} - for key,value in AccessSpecifier.__dict__.items(): - if isinstance(value,AccessSpecifier): + for key,value in StorageClass.__dict__.items(): + if isinstance(value,StorageClass): self._name_map[value] = key return self._name_map[self] @staticmethod def from_id(id): - if id >= len(AccessSpecifier._kinds) or not AccessSpecifier._kinds[id]: - raise ValueError,'Unknown access specifier %d' % id - return AccessSpecifier._kinds[id] + if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]: + raise ValueError,'Unknown storage class %d' % id + return StorageClass._kinds[id] + + def __repr__(self): + return 'StorageClass.%s' % (self.name,) + +StorageClass.INVALID = StorageClass(0) +StorageClass.NONE = StorageClass(1) +StorageClass.EXTERN = StorageClass(2) +StorageClass.STATIC = StorageClass(3) +StorageClass.PRIVATEEXTERN = StorageClass(4) +StorageClass.OPENCLWORKGROUPLOCAL = StorageClass(5) +StorageClass.AUTO = StorageClass(6) +StorageClass.REGISTER = StorageClass(7) + + +### C++ access specifiers ### + +class AccessSpecifier(BaseEnumeration): + """ + Describes the access of a C++ class member + """ + + # The unique kind objects, index by id. + _kinds = [] + _name_map = None + + def from_param(self): + return self.value def __repr__(self): return 'AccessSpecifier.%s' % (self.name,) @@ -1500,7 +1596,7 @@ AccessSpecifier.NONE = AccessSpecifier(4) ### Type Kinds ### -class TypeKind(object): +class TypeKind(BaseEnumeration): """ Describes the kind of type. """ @@ -1509,39 +1605,11 @@ class TypeKind(object): _kinds = [] _name_map = None - def __init__(self, value): - if value >= len(TypeKind._kinds): - TypeKind._kinds += [None] * (value - len(TypeKind._kinds) + 1) - if TypeKind._kinds[value] is not None: - raise ValueError,'TypeKind already loaded' - self.value = value - TypeKind._kinds[value] = self - TypeKind._name_map = None - - def from_param(self): - return self.value - - @property - def name(self): - """Get the enumeration name of this cursor kind.""" - if self._name_map is None: - self._name_map = {} - for key,value in TypeKind.__dict__.items(): - if isinstance(value,TypeKind): - self._name_map[value] = key - return self._name_map[self] - @property def spelling(self): """Retrieve the spelling of this TypeKind.""" return conf.lib.clang_getTypeKindSpelling(self.value) - @staticmethod - def from_id(id): - if id >= len(TypeKind._kinds) or TypeKind._kinds[id] is None: - raise ValueError,'Unknown type kind %d' % id - return TypeKind._kinds[id] - def __repr__(self): return 'TypeKind.%s' % (self.name,) @@ -1594,43 +1662,16 @@ TypeKind.VARIABLEARRAY = TypeKind(115) TypeKind.DEPENDENTSIZEDARRAY = TypeKind(116) TypeKind.MEMBERPOINTER = TypeKind(117) -class RefQualifierKind(object): +class RefQualifierKind(BaseEnumeration): """Describes a specific ref-qualifier of a type.""" # The unique kind objects, indexed by id. _kinds = [] _name_map = None - def __init__(self, value): - if value >= len(RefQualifierKind._kinds): - num_kinds = value - len(RefQualifierKind._kinds) + 1 - RefQualifierKind._kinds += [None] * num_kinds - if RefQualifierKind._kinds[value] is not None: - raise ValueError, 'RefQualifierKind already loaded' - self.value = value - RefQualifierKind._kinds[value] = self - RefQualifierKind._name_map = None - def from_param(self): return self.value - @property - def name(self): - """Get the enumeration name of this kind.""" - if self._name_map is None: - self._name_map = {} - for key, value in RefQualifierKind.__dict__.items(): - if isinstance(value, RefQualifierKind): - self._name_map[value] = key - return self._name_map[self] - - @staticmethod - def from_id(id): - if (id >= len(RefQualifierKind._kinds) or - RefQualifierKind._kinds[id] is None): - raise ValueError, 'Unknown type kind %d' % id - return RefQualifierKind._kinds[id] - def __repr__(self): return 'RefQualifierKind.%s' % (self.name,) @@ -2973,6 +3014,11 @@ functionList = [ _CXString, _CXString.from_result), + ("clang_Cursor_getMangling", + [Cursor], + _CXString, + _CXString.from_result), + # ("clang_getCXTUResourceUsage", # [TranslationUnit], # CXTUResourceUsage), @@ -3300,6 +3346,27 @@ functionList = [ Cursor, Cursor.from_result), + ("clang_Cursor_getNumTemplateArguments", + [Cursor], + c_int), + + ("clang_Cursor_getTemplateArgumentKind", + [Cursor, c_uint], + TemplateArgumentKind.from_id), + + ("clang_Cursor_getTemplateArgumentType", + [Cursor, c_uint], + Type, + Type.from_result), + + ("clang_Cursor_getTemplateArgumentValue", + [Cursor, c_uint], + c_longlong), + + ("clang_Cursor_getTemplateArgumentUnsignedValue", + [Cursor, c_uint], + c_ulonglong), + ("clang_Cursor_isBitField", [Cursor], bool), diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py index 4315045..a5224aa 100644 --- a/bindings/python/tests/cindex/test_cursor.py +++ b/bindings/python/tests/cindex/test_cursor.py @@ -1,6 +1,8 @@ +import ctypes import gc from clang.cindex import CursorKind +from clang.cindex import TemplateArgumentKind from clang.cindex import TranslationUnit from clang.cindex import TypeKind from .util import get_cursor @@ -244,6 +246,48 @@ def test_get_arguments(): assert arguments[0].spelling == "i" assert arguments[1].spelling == "j" +kTemplateArgTest = """\ + template + void foo(); + + template<> + void foo<-7, float, true>(); + """ + +def test_get_num_template_arguments(): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + assert foos[1].get_num_template_arguments() == 3 + +def test_get_template_argument_kind(): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL + assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE + assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL + +def test_get_template_argument_type(): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT + +def test_get_template_argument_value(): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + assert foos[1].get_template_argument_value(0) == -7 + assert foos[1].get_template_argument_value(2) == True + +def test_get_template_argument_unsigned_value(): + tu = get_tu(kTemplateArgTest, lang='cpp') + foos = get_cursors(tu, 'foo') + + assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7 + assert foos[1].get_template_argument_unsigned_value(2) == True + def test_referenced(): tu = get_tu('void foo(); void bar() { foo(); }') foo = get_cursor(tu, 'foo') @@ -252,3 +296,17 @@ def test_referenced(): if c.kind == CursorKind.CALL_EXPR: assert c.referenced.spelling == foo.spelling break + +def test_mangled_name(): + kInputForMangling = """\ + int foo(int, int); + """ + tu = get_tu(kInputForMangling, lang='cpp') + foo = get_cursor(tu, 'foo') + + # Since libclang does not link in targets, we cannot pass a triple to it + # and force the target. To enable this test to pass on all platforms, accept + # all valid manglings. + # [c-index-test handles this by running the source through clang, emitting + # an AST file and running libclang on that AST file] + assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH') diff --git a/cmake/modules/ClangConfig.cmake b/cmake/modules/ClangConfig.cmake new file mode 100644 index 0000000..f052bb9 --- /dev/null +++ b/cmake/modules/ClangConfig.cmake @@ -0,0 +1,8 @@ +# This file allows users to call find_package(Clang) and pick up our targets. + +# Clang doesn't have any CMake configuration settings yet because it mostly +# uses LLVM's. When it does, we should move this file to ClangConfig.cmake.in +# and call configure_file() on it. + +# Provide all our library targets to users. +include("${CMAKE_CURRENT_LIST_DIR}/ClangTargets.cmake") diff --git a/docs/AddressSanitizer.rst b/docs/AddressSanitizer.rst index 93a6a0e..cbdd7c6 100644 --- a/docs/AddressSanitizer.rst +++ b/docs/AddressSanitizer.rst @@ -165,9 +165,9 @@ problems happening in certain source files or with certain global variables. # Disable out-of-bound checks for global: global:bad_array # Disable out-of-bound checks for global instances of a given class ... - type:class.Namespace::BadClassName + type:Namespace::BadClassName # ... or a given struct. Use wildcard to deal with anonymous namespace. - type:struct.Namespace2::*::BadStructName + type:Namespace2::*::BadStructName # Disable initialization-order checks for globals: global:bad_init_global=init type:*BadInitClassSubstring*=init @@ -187,6 +187,7 @@ AddressSanitizer is supported on * Linux i386/x86\_64 (tested on Ubuntu 12.04); * MacOS 10.6 - 10.9 (i386/x86\_64). * Android ARM +* FreeBSD i386/x86\_64 (tested on FreeBSD 11-current) Ports to various other platforms are in progress. diff --git a/docs/ClangFormat.rst b/docs/ClangFormat.rst index 86c5ec5..45ea327 100644 --- a/docs/ClangFormat.rst +++ b/docs/ClangFormat.rst @@ -96,8 +96,8 @@ This can be integrated by adding the following to your `.vimrc`: .. code-block:: vim - map :pyf /clang-format.py - imap :pyf /clang-format.pyi + map :pyf /clang-format.py + imap :pyf /clang-format.py The first line enables :program:`clang-format` for NORMAL and VISUAL mode, the second line adds support for INSERT mode. Change "C-K" to another binding if diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst index 07febaf..ce6fae1 100644 --- a/docs/ClangFormatStyleOptions.rst +++ b/docs/ClangFormatStyleOptions.rst @@ -33,6 +33,43 @@ The ``.clang-format`` file uses YAML format: # A comment. ... +The configuration file can consist of several sections each having different +``Language:`` parameter denoting the programming language this section of the +configuration is targeted at. See the description of the **Language** option +below for the list of supported languages. The first section may have no +language set, it will set the default style options for all lanugages. +Configuration sections for specific language will override options set in the +default section. + +When :program:`clang-format` formats a file, it auto-detects the language using +the file name. When formatting standard input or a file that doesn't have the +extension corresponding to its language, ``-assume-filename=`` option can be +used to override the file name :program:`clang-format` uses to detect the +language. + +An example of a configuration file for multiple languages: + +.. code-block:: yaml + + --- + # We'll use defaults from the LLVM style, but with 4 columns indentation. + BasedOnStyle: LLVM + IndentWidth: 4 + --- + Language: Cpp + # Force pointers to the type for C++. + DerivePointerAlignment: false + PointerAlignment: Left + --- + Language: JavaScript + # Use 100 columns for JS. + ColumnLimit: 100 + --- + Language: Proto + # Don't format .proto files. + DisableFormat: true + ... + An easy way to get a valid ``.clang-format`` file containing all configuration options of a certain predefined style is: @@ -48,6 +85,24 @@ is applied for all input files. The format of the configuration is: -style='{key1: value1, key2: value2, ...}' +Disabling Formatting on a Piece of Code +======================================= + +Clang-format understands also special comments that switch formatting in a +delimited range. The code between a comment ``// clang-format off`` or +``/* clang-format off */`` up to a comment ``// clang-format on`` or +``/* clang-format on */`` will not be formatted. The comments themselves +will be formatted (aligned) normally. + +.. code-block:: c++ + + int formatted_code; + // clang-format off + void unformatted_code ; + // clang-format on + void formatted_code_again; + + Configuring Style in Code ========================= @@ -95,10 +150,24 @@ the configuration (without a prefix: ``Auto``). **AccessModifierOffset** (``int``) The extra indent or outdent of access modifiers, e.g. ``public:``. +**AlignAfterOpenBracket** (``bool``) + If ``true``, horizontally aligns arguments after an open bracket. + + This applies to round brackets (parentheses), angle brackets and square + brackets. This will result in formattings like + \code + someLongFunction(argument1, + argument2); + \endcode + **AlignEscapedNewlinesLeft** (``bool``) If ``true``, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column. +**AlignOperands** (``bool``) + If ``true``, horizontally align operands of binary and ternary + expressions. + **AlignTrailingComments** (``bool``) If ``true``, aligns trailing comments. @@ -111,6 +180,9 @@ the configuration (without a prefix: ``Auto``). E.g., this allows ``if (a) { return; }`` to be put on a single line. +**AllowShortCaseLabelsOnASingleLine** (``bool``) + If ``true``, short case labels will be contracted to a single line. + **AllowShortFunctionsOnASingleLine** (``ShortFunctionStyle``) Dependent on the value, ``int f() { return 0; }`` can be put on a single line. @@ -121,6 +193,8 @@ the configuration (without a prefix: ``Auto``). Never merge functions into a single line. * ``SFS_Inline`` (in configuration: ``Inline``) Only merge functions defined inside a class. + * ``SFS_Empty`` (in configuration: ``Empty``) + Only merge empty functions. * ``SFS_All`` (in configuration: ``All``) Merge all functions fitting on a single line. @@ -133,6 +207,13 @@ the configuration (without a prefix: ``Auto``). If ``true``, ``while (true) continue;`` can be put on a single line. +**AlwaysBreakAfterDefinitionReturnType** (``bool``) + If ``true``, always break after function definition return types. + + More truthfully called 'break before the identifier following the type + in a function definition'. PenaltyReturnTypeOnItsOwnLine becomes + irrelevant. + **AlwaysBreakBeforeMultilineStrings** (``bool``) If ``true``, always break before multiline string literals. @@ -140,12 +221,26 @@ the configuration (without a prefix: ``Auto``). If ``true``, always break after the ``template<...>`` of a template declaration. +**BinPackArguments** (``bool``) + If ``false``, a function call's arguments will either be all on the + same line or will have one line each. + **BinPackParameters** (``bool``) - If ``false``, a function call's or function definition's parameters - will either all be on the same line or will have one line each. + If ``false``, a function declaration's or function definition's + parameters will either all be on the same line or will have one line each. + +**BreakBeforeBinaryOperators** (``BinaryOperatorStyle``) + The way to wrap binary operators. + + Possible values: + + * ``BOS_None`` (in configuration: ``None``) + Break after operators. + * ``BOS_NonAssignment`` (in configuration: ``NonAssignment``) + Break before operators that aren't assignments. + * ``BOS_All`` (in configuration: ``All``) + Break before operators. -**BreakBeforeBinaryOperators** (``bool``) - If ``true``, binary operators will be placed after line breaks. **BreakBeforeBraces** (``BraceBreakingStyle``) The brace breaking style to use. @@ -158,7 +253,7 @@ the configuration (without a prefix: ``Auto``). Like ``Attach``, but break before braces on function, namespace and class definitions. * ``BS_Stroustrup`` (in configuration: ``Stroustrup``) - Like ``Attach``, but break before function definitions. + Like ``Attach``, but break before function definitions, and 'else'. * ``BS_Allman`` (in configuration: ``Allman``) Always break before braces. * ``BS_GNU`` (in configuration: ``GNU``) @@ -267,6 +362,8 @@ the configuration (without a prefix: ``Auto``). Do not use. * ``LK_Cpp`` (in configuration: ``Cpp``) Should be used for C, C++, ObjectiveC, ObjectiveC++. + * ``LK_Java`` (in configuration: ``Java``) + Should be used for Java. * ``LK_JavaScript`` (in configuration: ``JavaScript``) Should be used for JavaScript. * ``LK_Proto`` (in configuration: ``Proto``) @@ -290,6 +387,9 @@ the configuration (without a prefix: ``Auto``). Indent in all namespaces. +**ObjCBlockIndentWidth** (``unsigned``) + The number of characters to use for indentation of ObjC blocks. + **ObjCSpaceAfterProperty** (``bool``) Add a space after ``@property`` in Objective-C, i.e. use ``\@property (readonly)`` instead of ``\@property(readonly)``. @@ -330,6 +430,9 @@ the configuration (without a prefix: ``Auto``). Align pointer in the middle. +**SpaceAfterCStyleCast** (``bool``) + If ``true``, a space may be inserted after C style casts. + **SpaceBeforeAssignmentOperators** (``bool``) If ``false``, spaces will be removed before assignment operators. @@ -374,6 +477,9 @@ the configuration (without a prefix: ``Auto``). **SpacesInParentheses** (``bool``) If ``true``, spaces will be inserted after '(' and before ')'. +**SpacesInSquareBrackets** (``bool``) + If ``true``, spaces will be inserted after '[' and before ']'. + **Standard** (``LanguageStandard``) Format compatible with this standard, e.g. use ``A >`` instead of ``A>`` for LS_Cpp03. diff --git a/docs/CrossCompilation.rst b/docs/CrossCompilation.rst index 89f8777..fd42856e 100644 --- a/docs/CrossCompilation.rst +++ b/docs/CrossCompilation.rst @@ -201,4 +201,3 @@ uses hard-float), Clang will pick the ``armv7l-linux-gnueabi-ld`` The same is true if you're compiling for different ABIs, like ``gnueabi`` and ``androideabi``, and might even link and run, but produce run-time errors, which are much harder to track down and fix. - diff --git a/docs/InternalsManual.rst b/docs/InternalsManual.rst index 8e047db..502cae4 100644 --- a/docs/InternalsManual.rst +++ b/docs/InternalsManual.rst @@ -784,9 +784,24 @@ buffer uses this idiom and is subsequently ``#include``'d, the preprocessor can simply check to see whether the guarding condition is defined or not. If so, the preprocessor can completely ignore the include of the header. +.. _Parser: + The Parser Library ================== +This library contains a recursive-descent parser that polls tokens from the +preprocessor and notifies a client of the parsing progress. + +Historically, the parser used to talk to an abstract ``Action`` interface that +had virtual methods for parse events, for example ``ActOnBinOp()``. When Clang +grew C++ support, the parser stopped supporting general ``Action`` clients -- +it now always talks to the :ref:`Sema libray `. However, the Parser +still accesses AST objects only through opaque types like ``ExprResult`` and +``StmtResult``. Only :ref:`Sema ` looks at the AST node contents of these +wrappers. + +.. _AST: + The AST Library =============== @@ -1396,10 +1411,7 @@ body by single call to a static class method: .. code-block:: c++ Stmt *FooBody = ... - CFG *FooCFG = CFG::buildCFG(FooBody); - -It is the responsibility of the caller of ``CFG::buildCFG`` to ``delete`` the -returned ``CFG*`` when the CFG is no longer needed. + std::unique_ptr FooCFG = CFG::buildCFG(FooBody); Along with providing an interface to iterate over its ``CFGBlocks``, the ``CFG`` class also provides methods that are useful for debugging and @@ -1585,6 +1597,23 @@ interacts with constant evaluation: * ``__builtin_strlen`` and ``strlen``: These are constant folded as integer constant expressions if the argument is a string literal. +.. _Sema: + +The Sema Library +================ + +This library is called by the :ref:`Parser library ` during parsing to +do semantic analysis of the input. For valid programs, Sema builds an AST for +parsed constructs. + +.. _CodeGen: + +The CodeGen Library +=================== + +CodeGen takes an :ref:`AST ` as input and produces `LLVM IR code +`_ from it. + How to change Clang =================== diff --git a/docs/LanguageExtensions.rst b/docs/LanguageExtensions.rst index 35f759f..035b50d 100644 --- a/docs/LanguageExtensions.rst +++ b/docs/LanguageExtensions.rst @@ -109,12 +109,42 @@ following ``__`` (double underscore) to avoid interference from a macro with the same name. For instance, ``__cxx_rvalue_references__`` can be used instead of ``cxx_rvalue_references``. +``__has_cpp_attribute`` +----------------------- + +This function-like macro takes a single argument that is the name of a +C++11-style attribute. The argument can either be a single identifier, or a +scoped identifier. If the attribute is supported, a nonzero value is returned. +If the attribute is a standards-based attribute, this macro returns a nonzero +value based on the year and month in which the attribute was voted into the +working draft. If the attribute is not supported by the current compliation +target, this macro evaluates to 0. It can be used like this: + +.. code-block:: c++ + + #ifndef __has_cpp_attribute // Optional of course. + #define __has_cpp_attribute(x) 0 // Compatibility with non-clang compilers. + #endif + + ... + #if __has_cpp_attribute(clang::fallthrough) + #define FALLTHROUGH [[clang::fallthrough]] + #else + #define FALLTHROUGH + #endif + ... + +The attribute identifier (but not scope) can also be specified with a preceding +and following ``__`` (double underscore) to avoid interference from a macro with +the same name. For instance, ``gnu::__const__`` can be used instead of +``gnu::const``. + ``__has_attribute`` ------------------- This function-like macro takes a single identifier argument that is the name of -an attribute. It evaluates to 1 if the attribute is supported by the current -compilation target, or 0 if not. It can be used like this: +a GNU-style attribute. It evaluates to 1 if the attribute is supported by the +current compilation target, or 0 if not. It can be used like this: .. code-block:: c++ @@ -134,6 +164,33 @@ The attribute name can also be specified with a preceding and following ``__`` (double underscore) to avoid interference from a macro with the same name. For instance, ``__always_inline__`` can be used instead of ``always_inline``. + +``__has_declspec_attribute`` +---------------------------- + +This function-like macro takes a single identifier argument that is the name of +an attribute implemented as a Microsoft-style ``__declspec`` attribute. It +evaluates to 1 if the attribute is supported by the current compilation target, +or 0 if not. It can be used like this: + +.. code-block:: c++ + + #ifndef __has_declspec_attribute // Optional of course. + #define __has_declspec_attribute(x) 0 // Compatibility with non-clang compilers. + #endif + + ... + #if __has_declspec_attribute(dllexport) + #define DLLEXPORT __declspec(dllexport) + #else + #define DLLEXPORT + #endif + ... + +The attribute name can also be specified with a preceding and following ``__`` +(double underscore) to avoid interference from a macro with the same name. For +instance, ``__dllexport__`` can be used instead of ``dllexport``. + ``__is_identifier`` ------------------- @@ -357,23 +414,27 @@ The table below shows the support for each operation by vector extension. A dash indicates that an operation is not accepted according to a corresponding specification. -============================== ====== ======= === ==== - Opeator OpenCL AltiVec GCC NEON -============================== ====== ======= === ==== -[] yes yes yes -- -unary operators +, -- yes yes yes -- -++, -- -- yes yes yes -- -+,--,*,/,% yes yes yes -- -bitwise operators &,|,^,~ yes yes yes -- ->>,<< yes yes yes -- -!, &&, || no -- -- -- -==, !=, >, <, >=, <= yes yes -- -- -= yes yes yes yes -:? yes -- -- -- -sizeof yes yes yes yes -============================== ====== ======= === ==== - -See also :ref:`langext-__builtin_shufflevector`. +============================== ======= ======= ======= ======= + Opeator OpenCL AltiVec GCC NEON +============================== ======= ======= ======= ======= +[] yes yes yes -- +unary operators +, -- yes yes yes -- +++, -- -- yes yes yes -- ++,--,*,/,% yes yes yes -- +bitwise operators &,|,^,~ yes yes yes -- +>>,<< yes yes yes -- +!, &&, || yes -- -- -- +==, !=, >, <, >=, <= yes yes -- -- += yes yes yes yes +:? yes -- -- -- +sizeof yes yes yes yes +C-style cast yes yes yes no +reinterpret_cast yes no yes no +static_cast yes no yes no +const_cast no no no no +============================== ======= ======= ======= ======= + +See also :ref:`langext-__builtin_shufflevector`, :ref:`langext-__builtin_convertvector`. Messages on ``deprecated`` and ``unavailable`` Attributes ========================================================= @@ -454,6 +515,13 @@ features are enabled. The ``__has_extension`` macro can be used to query if language features are available as an extension when compiling for a standard which does not provide them. The features which can be tested are listed here. +Since Clang 3.4, the C++ SD-6 feature test macros are also supported. +These are macros with names of the form ``__cpp_``, and are +intended to be a portable way to query the supported features of the compiler. +See `the C++ status page `_ for +information on the version of SD-6 supported by each Clang release, and the +macros provided by that revision of the recommendations. + C++98 ----- @@ -502,6 +570,9 @@ C++11 alignment specifiers Use ``__has_feature(cxx_alignas)`` or ``__has_extension(cxx_alignas)`` to determine if support for alignment specifiers using ``alignas`` is enabled. +Use ``__has_feature(cxx_alignof)`` or ``__has_extension(cxx_alignof)`` to +determine if support for the ``alignof`` keyword is enabled. + C++11 attributes ^^^^^^^^^^^^^^^^ @@ -747,6 +818,13 @@ Use ``__has_feature(cxx_aggregate_nsdmi)`` or ``__has_extension(cxx_aggregate_nsdmi)`` to determine if support for default initializers in aggregate members is enabled. +C++1y digit separators +^^^^^^^^^^^^^^^^^^^^^^ + +Use ``__cpp_digit_separators`` to determine if support for digit separators +using single quotes (for instance, ``10'000``) is enabled. At this time, there +is no corresponding ``__has_feature`` name + C++1y generalized lambda capture ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -809,13 +887,25 @@ C11 alignment specifiers Use ``__has_feature(c_alignas)`` or ``__has_extension(c_alignas)`` to determine if support for alignment specifiers using ``_Alignas`` is enabled. +Use ``__has_feature(c_alignof)`` or ``__has_extension(c_alignof)`` to determine +if support for the ``_Alignof`` keyword is enabled. + C11 atomic operations ^^^^^^^^^^^^^^^^^^^^^ Use ``__has_feature(c_atomic)`` or ``__has_extension(c_atomic)`` to determine if support for atomic types using ``_Atomic`` is enabled. Clang also provides :ref:`a set of builtins ` which can be used to implement -the ```` operations on ``_Atomic`` types. +the ```` operations on ``_Atomic`` types. Use +``__has_include()`` to determine if C11's ```` header +is available. + +Clang will use the system's ```` header when one is available, and +will otherwise use its own. When using its own, implementations of the atomic +operations are provided as macros. In the cases where C11 also requires a real +function, this header provides only the declaration of that function (along +with a shadowing macro implementation), and you must link to a library which +provides a definition of the function if you use it instead of the macro. C11 generic selections ^^^^^^^^^^^^^^^^^^^^^^ @@ -1224,8 +1314,9 @@ Builtin Functions Clang supports a number of builtin library functions with the same syntax as GCC, including things like ``__builtin_nan``, ``__builtin_constant_p``, ``__builtin_choose_expr``, ``__builtin_types_compatible_p``, -``__sync_fetch_and_add``, etc. In addition to the GCC builtins, Clang supports -a number of builtins that GCC does not, which are listed here. +``__builtin_assume_aligned``, ``__sync_fetch_and_add``, etc. In addition to +the GCC builtins, Clang supports a number of builtins that GCC does not, which +are listed here. Please note that Clang does not and will not support all of the GCC builtins for vector operations. Instead of using builtins, you should use the functions @@ -1235,6 +1326,42 @@ implemented directly in terms of :ref:`extended vector support ` instead of builtins, in order to reduce the number of builtins that we need to implement. +``__builtin_assume`` +------------------------------ + +``__builtin_assume`` is used to provide the optimizer with a boolean +invariant that is defined to be true. + +**Syntax**: + +.. code-block:: c++ + + __builtin_assume(bool) + +**Example of Use**: + +.. code-block:: c++ + + int foo(int x) { + __builtin_assume(x != 0); + + // The optimizer may short-circuit this check using the invariant. + if (x == 0) + return do_something(); + + return do_something_else(); + } + +**Description**: + +The boolean argument to this function is defined to be true. The optimizer may +analyze the form of the expression provided as the argument and deduce from +that information used to optimize the program. If the condition is violated +during execution, the behavior is undefined. The argument itself is never +evaluated, so any side effects of the expression will be discarded. + +Query for this feature with ``__has_builtin(__builtin_assume)``. + ``__builtin_readcyclecounter`` ------------------------------ @@ -1324,6 +1451,8 @@ indices specified. Query for this feature with ``__has_builtin(__builtin_shufflevector)``. +.. _langext-__builtin_convertvector: + ``__builtin_convertvector`` --------------------------- @@ -1354,7 +1483,7 @@ type must have the same number of elements. // convert from a vector of 4 shorts to a vector of 4 floats. __builtin_convertvector(vs, vector4float) // equivalent to: - (vector4float) { (float) vf[0], (float) vf[1], (float) vf[2], (float) vf[3] } + (vector4float) { (float) vs[0], (float) vs[1], (float) vs[2], (float) vs[3] } **Description**: @@ -1554,12 +1683,14 @@ __c11_atomic builtins Clang provides a set of builtins which are intended to be used to implement C11's ```` header. These builtins provide the semantics of the ``_explicit`` form of the corresponding C11 operation, and are named with a -``__c11_`` prefix. The supported operations are: +``__c11_`` prefix. The supported operations, and the differences from +the corresponding C11 operations, are: * ``__c11_atomic_init`` * ``__c11_atomic_thread_fence`` * ``__c11_atomic_signal_fence`` -* ``__c11_atomic_is_lock_free`` +* ``__c11_atomic_is_lock_free`` (The argument is the size of the + ``_Atomic(...)`` object, instead of its address) * ``__c11_atomic_store`` * ``__c11_atomic_load`` * ``__c11_atomic_exchange`` @@ -1571,6 +1702,11 @@ C11's ```` header. These builtins provide the semantics of the * ``__c11_atomic_fetch_or`` * ``__c11_atomic_fetch_xor`` +The macros ``__ATOMIC_RELAXED``, ``__ATOMIC_CONSUME``, ``__ATOMIC_ACQUIRE``, +``__ATOMIC_RELEASE``, ``__ATOMIC_ACQ_REL``, and ``__ATOMIC_SEQ_CST`` are +provided, with values corresponding to the enumerators of C11's +``memory_order`` enumeration. + Low-level ARM exclusive memory builtins --------------------------------------- @@ -1780,15 +1916,17 @@ it causes the instantiation of ``twice`` and ``thrice`` with an ``int`` type; of these two instantiations, ``twice`` will be optimized (because its definition was outside the region) and ``thrice`` will not be optimized. -.. _langext-pragma-loop: - Extensions for loop hint optimizations ====================================== The ``#pragma clang loop`` directive is used to specify hints for optimizing the subsequent for, while, do-while, or c++11 range-based for loop. The directive -provides options for vectorization and interleaving. Loop hints can be specified -before any loop and will be ignored if the optimization is not safe to apply. +provides options for vectorization, interleaving, and unrolling. Loop hints can +be specified before any loop and will be ignored if the optimization is not safe +to apply. + +Vectorization and Interleaving +------------------------------ A vectorized loop performs multiple iterations of the original loop in parallel using vector instructions. The instruction set of the target @@ -1831,6 +1969,46 @@ width/count of the set of target architectures supported by your application. Specifying a width/count of 1 disables the optimization, and is equivalent to ``vectorize(disable)`` or ``interleave(disable)``. +Loop Unrolling +-------------- + +Unrolling a loop reduces the loop control overhead and exposes more +opportunities for ILP. Loops can be fully or partially unrolled. Full unrolling +eliminates the loop and replaces it with an enumerated sequence of loop +iterations. Full unrolling is only possible if the loop trip count is known at +compile time. Partial unrolling replicates the loop body within the loop and +reduces the trip count. + +If ``unroll(full)`` is specified the unroller will attempt to fully unroll the +loop if the trip count is known at compile time. If the loop count is not known +or the fully unrolled code size is greater than the limit specified by the +`-pragma-unroll-threshold` command line option the loop will be partially +unrolled subject to the same limit. + +.. code-block:: c++ + + #pragma clang loop unroll(full) + for(...) { + ... + } + +The unroll count can be specified explicitly with ``unroll_count(_value_)`` where +_value_ is a positive integer. If this value is greater than the trip count the +loop will be fully unrolled. Otherwise the loop is partially unrolled subject +to the `-pragma-unroll-threshold` limit. + +.. code-block:: c++ + + #pragma clang loop unroll_count(8) + for(...) { + ... + } + +Unrolling of a loop can be prevented by specifying ``unroll(disable)``. + +Additional Information +---------------------- + For convenience multiple loop hints can be specified on a single line. .. code-block:: c++ diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 4988053..e70d1ec 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -246,6 +246,16 @@ Example matches f +Matcher<Decl>linkageSpecDeclMatcher<LinkageSpecDecl>... +

Matches a declaration of a linkage specification.
+
+Given
+  extern "C" {}
+linkageSpecDecl()
+  matches "extern "C" {}"
+
+ + Matcher<Decl>methodDeclMatcher<CXXMethodDecl>...
Matches method declarations.
 
@@ -297,6 +307,16 @@ Example matches X, Z
 
+Matcher<Decl>typedefDeclMatcher<TypedefDecl>... +
Matches typedef declarations.
+
+Given
+  typedef int X;
+typedefDecl()
+  matches "typedef int X"
+
+ + Matcher<Decl>unresolvedUsingValueDeclMatcher<UnresolvedUsingValueDecl>...
Matches unresolved using value declarations.
 
@@ -319,6 +339,25 @@ usingDecl()
   matches using X::x 
+Matcher<Decl>usingDirectiveDeclMatcher<UsingDirectiveDecl>... +
Matches using namespace declarations.
+
+Given
+  namespace X { int x; }
+  using namespace X;
+usingDirectiveDecl()
+  matches using namespace X 
+ + +Matcher<Decl>valueDeclMatcher<ValueDecl>... +
Matches any value declaration.
+
+Example matches A, B, C and F
+  enum X { A, B, C };
+  void F();
+
+ + Matcher<Decl>varDeclMatcher<VarDecl>...
Matches variable declarations.
 
@@ -355,6 +394,14 @@ nestedNameSpecifier()
 
+Matcher<Stmt>CUDAKernelCallExprMatcher<CUDAKernelCallExpr>... +
Matches CUDA kernel call expression.
+
+Example matches,
+  kernel<<<i,j>>>();
+
+ + Matcher<Stmt>arraySubscriptExprMatcher<ArraySubscriptExpr>...
Matches array subscript expressions.
 
@@ -711,7 +758,7 @@ Given
   int a[] = { 1, 2 };
   struct B { int x, y; };
   B b = { 5, 6 };
-initList()
+initListExpr()
   matches "{ 1, 2 }" and "{ 5, 6 }"
 
@@ -876,6 +923,18 @@ Example matches "abcd", L"abcd" +Matcher<Stmt>substNonTypeTemplateParmExprMatcher<SubstNonTypeTemplateParmExpr>... +
Matches substitutions of non-type template parameters.
+
+Given
+  template <int N>
+  struct A { static const int n = N; };
+  struct B : public A<42> {};
+substNonTypeTemplateParmExpr()
+  matches "N" in the right-hand side of "static const int n = N;"
+
+ + Matcher<Stmt>switchCaseMatcher<SwitchCase>...
Matches case and default statements inside switch statements.
 
@@ -980,6 +1039,17 @@ whileStmt()
 
+Matcher<TemplateArgument>templateArgumentMatcher<TemplateArgument>... +
Matches template arguments.
+
+Given
+  template <typename T> struct C {};
+  C<int> c;
+templateArgument()
+  matches 'int' in C<int>.
+
+ + Matcher<TypeLoc>typeLocMatcher<TypeLoc>...
Matches TypeLocs in the clang AST.
 
@@ -1269,6 +1339,7 @@ Given int a[] = { 2, 3 } int b[42]; int c[a[0]]; + } variableArrayType() matches "int c[a[0]]" @@ -1381,26 +1452,6 @@ constructorDecl(hasAnyConstructorInitializer(isWritten())) -Matcher<CXXMethodDecl>hasOverloadedOperatorNameStringRef Name -
Matches overloaded operator names.
-
-Matches overloaded operator names specified in strings without the
-"operator" prefix: e.g. "<<".
-
-Given:
-  class A { int operator*(); };
-  const A &operator<<(const A &a, const A &b);
-  A a;
-  a << a;   <-- This matches
-
-operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified
-line and recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
-the declaration of A.
-
-Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
-
- - Matcher<CXXMethodDecl>isConst
Matches if the given method declaration is const.
 
@@ -1470,7 +1521,7 @@ operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified
 line and recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
 the declaration of A.
 
-Usable as: Matcher<CXXOperatorCallExpr>, Matcher<CXXMethodDecl>
+Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
 
@@ -1541,6 +1592,17 @@ Usable as: Matcher<ClassTemplateSpecializationDecl>templateArgumentCountIsunsigned N +
Matches if the number of template arguments equals N.
+
+Given
+  template<typename T> struct C {};
+  C<int> c;
+classTemplateSpecializationDecl(templateArgumentCountIs(1))
+  matches C<int>.
+
+ + Matcher<CompoundStmt>statementCountIsunsigned N
Checks that a compound statement contains a specific number of
 child statements.
@@ -1601,10 +1663,55 @@ and reference to that variable declaration within a compound statement.
 
-Matcher<Decl>equalsNodeDecl *Node -
Matches if a node equals another node.
+Matcher<Decl>hasAttrattr::Kind AttrKind
+
Matches declaration that has a given attribute.
 
-Decl has pointer identity in the AST.
+Given
+  __attribute__((device)) void f() { ... }
+decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+f.
+
+ + +Matcher<Decl>isExpansionInFileMatchingstd::string RegExp +
Matches AST nodes that were expanded within files whose name is
+partially matching a given regex.
+
+Example matches Y but not X
+    (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+  #include "ASTMatcher.h"
+  class X {};
+ASTMatcher.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ + +Matcher<Decl>isExpansionInMainFile +
Matches AST nodes that were expanded within the main-file.
+
+Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+  #include <Y.h>
+  class X {};
+Y.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ + +Matcher<Decl>isExpansionInSystemHeader +
Matches AST nodes that were expanded within system-header-files.
+
+Example matches Y but not X
+    (matcher = recordDecl(isExpansionInSystemHeader())
+  #include <SystemHeader.h>
+  class X {};
+SystemHeader.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
 
@@ -1614,6 +1721,19 @@ by the compiler (eg. implicit defaultcopy constructors).
+Matcher<Decl>isInstantiated +
Matches declarations that are template instantiations or are inside
+template instantiations.
+
+Given
+  template<typename T> void A(T t) { T i; }
+  A(0);
+  A(0U);
+functionDecl(isInstantiated())
+  matches 'A(int) {...};' and 'A(unsigned) {...}'.
+
+ + Matcher<Decl>isPrivate
Matches private C++ declarations.
 
@@ -1667,6 +1787,26 @@ Usable as: Matcher<FunctionDecl>hasOverloadedOperatorNameStringRef Name
+
Matches overloaded operator names.
+
+Matches overloaded operator names specified in strings without the
+"operator" prefix: e.g. "<<".
+
+Given:
+  class A { int operator*(); };
+  const A &operator<<(const A &a, const A &b);
+  A a;
+  a << a;   <-- This matches
+
+operatorCallExpr(hasOverloadedOperatorName("<<"))) matches the specified
+line and recordDecl(hasMethod(hasOverloadedOperatorName("*"))) matches
+the declaration of A.
+
+Usable as: Matcher<CXXOperatorCallExpr>, Matcher<FunctionDecl>
+
+ + Matcher<FunctionDecl>isDefinition
Matches if a declaration has a body attached.
 
@@ -1682,6 +1822,17 @@ Usable as: Matcher<FunctionDecl>isDeleted
+
Matches deleted function declarations.
+
+Given:
+  void Func();
+  void DeletedFunc() = delete;
+functionDecl(isDeleted())
+  matches the declaration of DeletedFunc, but not Func.
+
+ + Matcher<FunctionDecl>isExplicitTemplateSpecialization
Matches explicit template specializations of function, class, or
 static member variable template instantiations.
@@ -1768,7 +1919,7 @@ memberExpr(isArrow())
 
-Matcher<NamedDecl>hasNamestd::string Name +Matcher<NamedDecl>hasNamestd::string Name
Matches NamedDecl nodes that have the specified name.
 
 Supports specifying enclosing namespaces or classes by prefixing the name
@@ -1900,11 +2051,61 @@ and reference to that variable declaration within a compound statement.
 
-Matcher<Stmt>equalsNodeStmt *Node -
Matches if a node equals another node.
+Matcher<Stmt>isExpansionInFileMatchingstd::string RegExp
+
Matches AST nodes that were expanded within files whose name is
+partially matching a given regex.
 
-Stmt has pointer identity in the AST.
+Example matches Y but not X
+    (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+  #include "ASTMatcher.h"
+  class X {};
+ASTMatcher.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ + +Matcher<Stmt>isExpansionInMainFile +
Matches AST nodes that were expanded within the main-file.
+
+Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+  #include <Y.h>
+  class X {};
+Y.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ +Matcher<Stmt>isExpansionInSystemHeader +
Matches AST nodes that were expanded within system-header-files.
+
+Example matches Y but not X
+    (matcher = recordDecl(isExpansionInSystemHeader())
+  #include <SystemHeader.h>
+  class X {};
+SystemHeader.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ + +Matcher<Stmt>isInTemplateInstantiation +
Matches statements inside of a template instantiation.
+
+Given
+  int j;
+  template<typename T> void A(T t) { T i; j += 42;}
+  A(0);
+  A(0U);
+declStmt(isInTemplateInstantiation())
+  matches 'int i;' and 'unsigned i'.
+unless(stmt(isInTemplateInstantiation()))
+  will NOT match j += 42; as it's shared between the template definition and
+  instantiation.
 
@@ -1923,6 +2124,88 @@ Usable as: Matcher<TemplateArgument>equalsIntegralValuestd::string Value +
Matches a TemplateArgument of integral type with a given value.
+
+Note that 'Value' is a string as the template argument's value is
+an arbitrary precision integer. 'Value' must be euqal to the canonical
+representation of that integral value in base 10.
+
+Given
+  template<int T> struct A {};
+  C<42> c;
+classTemplateSpecializationDecl(
+  hasAnyTemplateArgument(equalsIntegralValue("42")))
+  matches the implicit instantiation of C in C<42>.
+
+ + +Matcher<TemplateArgument>isIntegral +
Matches a TemplateArgument that is an integral value.
+
+Given
+  template<int T> struct A {};
+  C<42> c;
+classTemplateSpecializationDecl(
+  hasAnyTemplateArgument(isIntegral()))
+  matches the implicit instantiation of C in C<42>
+  with isIntegral() matching 42.
+
+ + +Matcher<TemplateSpecializationType>templateArgumentCountIsunsigned N +
Matches if the number of template arguments equals N.
+
+Given
+  template<typename T> struct C {};
+  C<int> c;
+classTemplateSpecializationDecl(templateArgumentCountIs(1))
+  matches C<int>.
+
+ + +Matcher<TypeLoc>isExpansionInFileMatchingstd::string RegExp +
Matches AST nodes that were expanded within files whose name is
+partially matching a given regex.
+
+Example matches Y but not X
+    (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+  #include "ASTMatcher.h"
+  class X {};
+ASTMatcher.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ + +Matcher<TypeLoc>isExpansionInMainFile +
Matches AST nodes that were expanded within the main-file.
+
+Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+  #include <Y.h>
+  class X {};
+Y.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ + +Matcher<TypeLoc>isExpansionInSystemHeader +
Matches AST nodes that were expanded within system-header-files.
+
+Example matches Y but not X
+    (matcher = recordDecl(isExpansionInSystemHeader())
+  #include <SystemHeader.h>
+  class X {};
+SystemHeader.h:
+  class Y {};
+
+Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc>
+
+ + Matcher<Type>equalsBoundNodestd::string ID
Matches if a node equals a previously bound node.
 
@@ -2550,7 +2833,7 @@ given matcher.
 
 Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x")))))
   class Y { public: void x(); };
-  void z() { Y y; y.x();
+  void z() { Y y; y.x(); }
 
@@ -3448,6 +3731,7 @@ Example matches X &x and const X &y void a(X b) { X &x = b; const X &y = b; + } };
@@ -3582,6 +3866,18 @@ classTemplateSpecializationDecl(hasAnyTemplateArgument(
+Matcher<TemplateArgument>refersToIntegralTypeMatcher<QualType> InnerMatcher +
Matches a TemplateArgument that referes to an integral type.
+
+Given
+  template<int T> struct A {};
+  C<42> c;
+classTemplateSpecializationDecl(
+  hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
+  matches the implicit instantiation of C in C<42>.
+
+ + Matcher<TemplateArgument>refersToTypeMatcher<QualType> InnerMatcher
Matches a TemplateArgument that refers to a certain type.
 
diff --git a/docs/MSVCCompatibility.rst b/docs/MSVCCompatibility.rst
index 32efb76..73f01fc 100644
--- a/docs/MSVCCompatibility.rst
+++ b/docs/MSVCCompatibility.rst
@@ -72,17 +72,21 @@ The status of major ABI-impacting C++ features:
 .. _/vm: http://msdn.microsoft.com/en-us/library/yad46a6z.aspx
 .. _pointer to a member of a virtual base class: http://llvm.org/PR15713
 
-* Debug info: :partial:`Minimal`.  Clang emits CodeView line tables into the
-  object file, similar to what MSVC emits when given the ``/Z7`` flag.
-  Microsoft's link.exe will read this information and use it to create a PDB,
+* Debug info: :partial:`Minimal`.  Clang emits both CodeView line tables
+  (similar to what MSVC emits when given the ``/Z7`` flag) and DWARF debug
+  information into the object file.
+  Microsoft's link.exe will transform the CodeView line tables into a PDB,
   enabling stack traces in all modern Windows debuggers.  Clang does not emit
-  any type info or description of variable layout.
+  any CodeView-compatible type info or description of variable layout.
+  Binaries linked with either binutils' ld or LLVM's lld should be usable with
+  GDB however sophisticated C++ expressions are likely to fail.
 
 * RTTI: :good:`Complete`.  Generation of RTTI data structures has been
   finished, along with support for the ``/GR`` flag.
 
-* Exceptions and SEH: :none:`Unstarted`.  Clang can parse both constructs, but
-  does not know how to emit compatible handlers.
+* Exceptions and SEH: :partial:`Minimal`.  Clang can parse both constructs, but
+  does not know how to emit compatible handlers.  Clang cannot throw exceptions
+  but it can rethrow them.
 
 * Thread-safe initialization of local statics: :none:`Unstarted`.  We are ABI
   compatible with MSVC 2013, which does not support thread-safe local statics.
diff --git a/docs/Modules.rst b/docs/Modules.rst
index ce1e717..1575ce6 100644
--- a/docs/Modules.rst
+++ b/docs/Modules.rst
@@ -2,10 +2,6 @@
 Modules
 =======
 
-.. warning::
-   The functionality described on this page is supported for C and
-   Objective-C. C++ support is experimental.
-
 .. contents::
    :local:
 
@@ -104,7 +100,7 @@ Many programming languages have a module or package system, and because of the v
 
 Using Modules
 =============
-To enable modules, pass the command-line flag ``-fmodules`` [#]_. This will make any modules-enabled software libraries available as modules as well as introducing any modules-specific syntax. Additional `command-line parameters`_ are described in a separate section later.
+To enable modules, pass the command-line flag ``-fmodules``. This will make any modules-enabled software libraries available as modules as well as introducing any modules-specific syntax. Additional `command-line parameters`_ are described in a separate section later.
 
 Objective-C Import declaration
 ------------------------------
@@ -114,7 +110,7 @@ Objective-C provides syntax for importing a module via an *@import declaration*,
 
   @import std;
 
-The @import declaration above imports the entire contents of the ``std`` module (which would contain, e.g., the entire C or C++ standard library) and make its API available within the current translation unit. To import only part of a module, one may use dot syntax to specific a particular submodule, e.g.,
+The ``@import`` declaration above imports the entire contents of the ``std`` module (which would contain, e.g., the entire C or C++ standard library) and make its API available within the current translation unit. To import only part of a module, one may use dot syntax to specific a particular submodule, e.g.,
 
 .. parsed-literal::
 
@@ -140,6 +136,19 @@ will be automatically mapped to an import of the module ``std.io``. Even with sp
 
   The automatic mapping of ``#include`` to ``import`` also solves an implementation problem: importing a module with a definition of some entity (say, a ``struct Point``) and then parsing a header containing another definition of ``struct Point`` would cause a redefinition error, even if it is the same ``struct Point``. By mapping ``#include`` to ``import``, the compiler can guarantee that it always sees just the already-parsed definition from the module.
 
+While building a module, ``#include_next`` is also supported, with one caveat.
+The usual behavior of ``#include_next`` is to search for the specified filename
+in the list of include paths, starting from the path *after* the one
+in which the current file was found.
+Because files listed in module maps are not found through include paths, a
+different strategy is used for ``#include_next`` directives in such files: the
+list of include paths is searched for the specified header name, to find the
+first include path that would refer to the current file. ``#include_next`` is
+interpreted as if the current file had been found in that path.
+If this search finds a file named by a module map, the ``#include_next``
+directive is translated into an import, just like for a ``#include``
+directive.``
+
 Module maps
 -----------
 The crucial link between modules and headers is described by a *module map*, which describes how a collection of existing headers maps on to the (logical) structure of a module. For example, one could imagine a module ``std`` covering the C standard library. Each of the C standard library headers (````, ````, ````, etc.) would contribute to the ``std`` module, by placing their respective APIs into the corresponding submodule (``std.io``, ``std.lib``, ``std.math``, etc.). Having a list of the headers that are part of the ``std`` module allows the compiler to build the ``std`` module as a standalone entity, and having the mapping from header names to (sub)modules allows the automatic translation of ``#include`` directives to module imports.
@@ -163,13 +172,10 @@ Modules maintain references to each of the headers that were part of the module
 Command-line parameters
 -----------------------
 ``-fmodules``
-  Enable the modules feature (EXPERIMENTAL).
-
-``-fcxx-modules``
-  Enable the modules feature for C++ (EXPERIMENTAL and VERY BROKEN).
+  Enable the modules feature.
 
 ``-fmodule-maps``
-  Enable interpretation of module maps (EXPERIMENTAL). This option is implied by ``-fmodules``.
+  Enable interpretation of module maps. This option is implied by ``-fmodules``.
 
 ``-fmodules-cache-path=``
   Specify the path to the modules cache. If not provided, Clang will select a system-appropriate default.
@@ -201,6 +207,9 @@ Command-line parameters
 ``-fmodules-search-all``
   If a symbol is not found, search modules referenced in the current module maps but not imported for symbols, so the error message can reference the module by name.  Note that if the global module index has not been built before, this might take some time as it needs to build all the modules.  Note that this option doesn't apply in module builds, to avoid the recursion.
 
+``-fno-modules-implicit-maps``
+  Suppresses the implicit search for files called ``module.modulemap`` and similar. Instead, module files need to be explicitly specified via ``-fmodule-map-file`` or transitively used.
+
 Module Semantics
 ================
 
@@ -208,7 +217,7 @@ Modules are modeled as if each submodule were a separate translation unit, and a
 
 .. note::
 
-  This behavior is currently only approximated when building a module. Entities within a submodule that has already been built are visible when building later submodules in that module. This can lead to fragile modules that depend on the build order used for the submodules of the module, and should not be relied upon.
+  This behavior is currently only approximated when building a module with submodules. Entities within a submodule that has already been built are visible when building later submodules in that module. This can lead to fragile modules that depend on the build order used for the submodules of the module, and should not be relied upon. This behavior is subject to change.
 
 As an example, in C, this implies that if two structs are defined in different submodules with the same name, those two types are distinct types (but may be *compatible* types if their definitions match. In C++, two structs defined with the same name in different submodules are the *same* type, and must be equivalent under C++'s One Definition Rule.
 
@@ -216,6 +225,8 @@ As an example, in C, this implies that if two structs are defined in different s
 
   Clang currently only performs minimal checking for violations of the One Definition Rule.
 
+If any submodule of a module is imported into any part of a program, the entire top-level module is considered to be part of the program. As a consequence of this, Clang may diagnose conflicts between an entity declared in an unimported submodule and an entity declared in the current translation unit, and Clang may inline or devirtualize based on knowledge from unimported submodules.
+
 Macros
 ------
 
@@ -238,6 +249,10 @@ The ``#undef`` overrides the ``#define``, and a source file that imports both mo
 Module Map Language
 ===================
 
+.. warning::
+
+  The module map language is not currently guaranteed to be stable between major revisions of Clang.
+
 The module map language describes the mapping from header files to the
 logical structure of modules. To enable support for using a library as
 a module, one must write a ``module.modulemap`` file for that library. The
@@ -255,6 +270,12 @@ As an example, the module map file for the C standard library might look a bit l
 .. parsed-literal::
 
   module std [system] [extern_c] {
+    module assert {
+      textual header "assert.h"
+      header "bits/assert-decls.h"
+      export *
+    }
+
     module complex {
       header "complex.h"
       export *
@@ -287,11 +308,11 @@ Module map files use a simplified form of the C99 lexer, with the same rules for
 
 .. parsed-literal::
 
-  ``config_macros`` ``export``     ``module``
+  ``config_macros`` ``export``     ``private``
   ``conflict``      ``framework``  ``requires``
-  ``exclude``       ``header``     ``private``
+  ``exclude``       ``header``     ``textual``
   ``explicit``      ``link``       ``umbrella``
-  ``extern``        ``use``
+  ``extern``        ``module``     ``use``
 
 Module map file
 ---------------
@@ -319,7 +340,7 @@ A module declaration describes a module, including the headers that contribute t
     ``explicit``:sub:`opt` ``framework``:sub:`opt` ``module`` *module-id* *attributes*:sub:`opt` '{' *module-member** '}'
     ``extern`` ``module`` *module-id* *string-literal*
 
-The *module-id* should consist of only a single *identifier*, which provides the name of the module being defined. Each module shall have a single definition. 
+The *module-id* should consist of only a single *identifier*, which provides the name of the module being defined. Each module shall have a single definition.
 
 The ``explicit`` qualifier can only be applied to a submodule, i.e., a module that is nested within another module. The contents of explicit submodules are only made available when the submodule itself was explicitly named in an import declaration or was re-exported from an imported module.
 
@@ -427,11 +448,11 @@ A header declaration specifies that a particular header is associated with the e
 .. parsed-literal::
 
   *header-declaration*:
-    ``umbrella``:sub:`opt` ``header`` *string-literal*
-    ``private`` ``header`` *string-literal*
+    ``private``:sub:`opt` ``textual``:sub:`opt` ``header`` *string-literal*
+    ``umbrella`` ``header`` *string-literal*
     ``exclude`` ``header`` *string-literal*
 
-A header declaration that does not contain ``exclude`` specifies a header that contributes to the enclosing module. Specifically, when the module is built, the named header will be parsed and its declarations will be (logically) placed into the enclosing submodule.
+A header declaration that does not contain ``exclude`` nor ``textual`` specifies a header that contributes to the enclosing module. Specifically, when the module is built, the named header will be parsed and its declarations will be (logically) placed into the enclosing submodule.
 
 A header with the ``umbrella`` specifier is called an umbrella header. An umbrella header includes all of the headers within its directory (and any subdirectories), and is typically used (in the ``#include`` world) to easily access the full API provided by a particular library. With modules, an umbrella header is a convenient shortcut that eliminates the need to write out ``header`` declarations for every library header. A given directory can only contain a single umbrella header.
 
@@ -443,14 +464,16 @@ A header with the ``umbrella`` specifier is called an umbrella header. An umbrel
 
 A header with the ``private`` specifier may not be included from outside the module itself.
 
-A header with the ``exclude`` specifier is excluded from the module. It will not be included when the module is built, nor will it be considered to be part of the module.
+A header with the ``textual`` specifier will not be included when the module is built, and will be textually included if it is named by a ``#include`` directive. However, it is considered to be part of the module for the purpose of checking *use-declaration*\s.
 
-**Example**: The C header ``assert.h`` is an excellent candidate for an excluded header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings).
+A header with the ``exclude`` specifier is excluded from the module. It will not be included when the module is built, nor will it be considered to be part of the module, even if an ``umbrella`` header or directory would otherwise make it part of the module.
+
+**Example**: The C header ``assert.h`` is an excellent candidate for a textual header, because it is meant to be included multiple times (possibly with different ``NDEBUG`` settings). However, declarations within it should typically be split into a separate modular header.
 
 .. parsed-literal::
 
   module std [system] {
-    exclude header "assert.h"
+    textual header "assert.h"
   }
 
 A given header shall not be referenced by more than one *header-declaration*.
@@ -824,20 +847,17 @@ To detect and help address some of these problems, the ``clang-tools-extra`` rep
 
 Future Directions
 =================
-Modules is an experimental feature, and there is much work left to do to make it both real and useful. Here are a few ideas:
+Modules support is under active development, and there are many opportunities remaining to improve it. Here are a few ideas:
 
 **Detect unused module imports**
   Unlike with ``#include`` directives, it should be fairly simple to track whether a directly-imported module has ever been used. By doing so, Clang can emit ``unused import`` or ``unused #include`` diagnostics, including Fix-Its to remove the useless imports/includes.
 
 **Fix-Its for missing imports**
-  It's fairly common for one to make use of some API while writing code, only to get a compiler error about "unknown type" or "no function named" because the corresponding header has not been included. Clang should detect such cases and auto-import the required module (with a Fix-It!).
+  It's fairly common for one to make use of some API while writing code, only to get a compiler error about "unknown type" or "no function named" because the corresponding header has not been included. Clang can detect such cases and auto-import the required module, but should provide a Fix-It to add the import.
 
 **Improve modularize**
   The modularize tool is both extremely important (for deployment) and extremely crude. It needs better UI, better detection of problems (especially for C++), and perhaps an assistant mode to help write module maps for you.
 
-**C++ Support**
-  Modules clearly has to work for C++, or we'll never get to use it for the Clang code base.
-
 Where To Learn More About Modules
 =================================
 The Clang source code provides additional information about modules:
@@ -859,8 +879,6 @@ PCHInternals_
 
 .. [#] Automatic linking against the libraries of modules requires specific linker support, which is not widely available.
 
-.. [#] Modules are only available in C and Objective-C; a separate flag ``-fcxx-modules`` enables modules support for C++, which is even more experimental and broken.
-
 .. [#] There are certain anti-patterns that occur in headers, particularly system headers, that cause problems for modules. The section `Modularizing a Platform`_ describes some of them.
 
 .. [#] The second instance is actually a new thread within the current process, not a separate process. However, the original compiler instance is blocked on the execution of this thread.
diff --git a/docs/RAVFrontendAction.rst b/docs/RAVFrontendAction.rst
index 2f60ce9..ec5d5d5 100644
--- a/docs/RAVFrontendAction.rst
+++ b/docs/RAVFrontendAction.rst
@@ -25,9 +25,10 @@ unit.
 
       class FindNamedClassAction : public clang::ASTFrontendAction {
       public:
-        virtual clang::ASTConsumer *CreateASTConsumer(
+        virtual std::unique_ptr CreateASTConsumer(
           clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
-          return new FindNamedClassConsumer;
+          return std::unique_ptr(
+              new FindNamedClassConsumer);
         }
       };
 
@@ -111,9 +112,10 @@ freshly created FindNamedClassConsumer:
 
 ::
 
-      virtual clang::ASTConsumer *CreateASTConsumer(
+      virtual std::unique_ptr CreateASTConsumer(
         clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
-        return new FindNamedClassConsumer(&Compiler.getASTContext());
+        return std::unique_ptr(
+            new FindNamedClassConsumer(&Compiler.getASTContext()));
       }
 
 Now that the ASTContext is available in the RecursiveASTVisitor, we can
@@ -185,9 +187,10 @@ Now we can combine all of the above into a small example program:
 
       class FindNamedClassAction : public clang::ASTFrontendAction {
       public:
-        virtual clang::ASTConsumer *CreateASTConsumer(
+        virtual std::unique_ptr CreateASTConsumer(
           clang::CompilerInstance &Compiler, llvm::StringRef InFile) {
-          return new FindNamedClassConsumer(&Compiler.getASTContext());
+          return std::unique_ptr(
+              new FindNamedClassConsumer(&Compiler.getASTContext()));
         }
       };
 
diff --git a/docs/ReleaseNotes.rst b/docs/ReleaseNotes.rst
index 5ff136e..8c47d69 100644
--- a/docs/ReleaseNotes.rst
+++ b/docs/ReleaseNotes.rst
@@ -1,6 +1,6 @@
-=======================
-Clang 3.5 Release Notes
-=======================
+=====================================
+Clang 3.6 (In-Progress) Release Notes
+=====================================
 
 .. contents::
    :local:
@@ -8,11 +8,17 @@ Clang 3.5 Release Notes
 
 Written by the `LLVM Team `_
 
+.. warning::
+
+   These are in-progress notes for the upcoming Clang 3.6 release. You may
+   prefer the `Clang 3.5 Release Notes
+   `_.
+
 Introduction
 ============
 
 This document contains the release notes for the Clang C/C++/Objective-C
-frontend, part of the LLVM Compiler Infrastructure, release 3.5. Here we
+frontend, part of the LLVM Compiler Infrastructure, release 3.6. Here we
 describe the status of Clang in some detail, including major
 improvements from the previous release and new feature work. For the
 general LLVM release notes, see `the LLVM
@@ -30,7 +36,7 @@ main Clang web page, this document applies to the *next* release, not
 the current one. To see the release notes for a specific release, please
 see the `releases page `_.
 
-What's New in Clang 3.5?
+What's New in Clang 3.6?
 ========================
 
 Some of the major new features and improvements to Clang are listed
@@ -41,213 +47,104 @@ sections with improvements to Clang's support for those languages.
 Major New Features
 ------------------
 
-- Clang uses the new MingW ABI
-  GCC 4.7 changed the mingw ABI. Clang 3.4 and older use the GCC 4.6
-  ABI. Clang 3.5 and newer use the GCC 4.7 abi.
-
-- The __has_attribute feature test is now target-aware. Older versions of Clang
-  would return true when the attribute spelling was known, regardless of whether
-  the attribute was available to the specific target. Clang now returns true
-  only when the attribute pertains to the current compilation target.
-  
-- Clang 3.5 now has parsing and semantic-analysis support for all OpenMP 3.1
-  pragmas (except atomics and ordered). LLVM's OpenMP runtime library,
-  originally developed by Intel, has been modified to work on ARM, PowerPC,
-  as well as X86. Code generation support is minimal at this point and will
-  continue to be developed for 3.6, along with the rest of OpenMP 3.1.
-  Support for OpenMP 4.0 features, such as SIMD and target accelerator
-  directives, is also in progress. Contributors to this work include AMD,
-  Argonne National Lab., IBM, Intel, Texas Instruments, University of Houston
-  and many others.
+- The __has_attribute built-in macro no longer queries for attributes across
+  multiple attribute syntaxes (GNU, C++11, __declspec, etc). Instead, it only
+  queries GNU-style attributes. With the addition of __has_cpp_attribute and
+  __has_declspec_attribute, this allows for more precise coverage of attribute
+  syntax querying.
+
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Clang's diagnostics are constantly being improved to catch more issues,
 explain them more clearly, and provide more accurate source information
-about them. The improvements since the 3.4 release include:
-
-- GCC compatibility: Clang displays a warning on unsupported gcc
-  optimization flags instead of an error.
-
-- Remarks system: Clang supports `-R` flags for enabling remarks. These are
-  diagnostic messages that provide information about the compilation process,
-  but don't suggest that a problem has been detected. As such, they cannot
-  be upgraded to errors with `-Werror` or `-Rerror`. A `-Reverything` flag
-  is provided (paralleling `-Weverything`) to turn on all remarks.
-
-- New remark `-Rpass`: Clang provides information about decisions made by
-  optimization passes during compilation. See :ref:`opt_rpass`.
-
-- New warning `-Wabsolute-value`: Clang warns about incorrect or useless usage
-  of the absolute functions (`abs`, `fabsf`, etc).
-
-  .. code-block:: c
-
-    #include 
-    void foo() {
-     unsigned int i=0;
-     abs(i);
-    }
-
-  returns
-  `warning: taking the absolute value of unsigned type 'unsigned int' has no effect [-Wabsolute-value]`
-
-  or
-
-  .. code-block:: c
-
-    #include 
-    void plop() {
-      long long i=0;
-      abs(i);
-    }
-
-  returns
-  `warning: absolute value function 'abs' given an argument of type 'long long' but has parameter of type 'int' which may cause truncation of value [-Wabsolute-value] use function 'llabs' instead`
-
-- New warning `-Wtautological-pointer-compare`:
-
-  .. code-block:: c++
-
-    #include 
-    void foo() {
-     int arr[5];
-     int x;
-     // warn on these conditionals
-     if (foo);
-     if (arr);
-     if (&x);
-     if (foo == NULL);
-     if (arr == NULL);
-     if (&x == NULL);
-    }
-
-  returns
-  `warning: comparison of address of 'x' equal to a null pointer is always false [-Wtautological-pointer-compare]`
-
-- New warning `-Wtautological-undefined-compare`: 
-
-  .. code-block:: c++
-
-    #include 
-    void f(int &x) {
-       if (&x == nullptr) { }
-    }
-
-  returns
-  `warning: reference cannot be bound to dereferenced null pointer in well-defined C++ code; comparison may be assumed to always evaluate to false [-Wtautological-undefined-compare]`
+about them. The improvements since the 3.5 release include:
 
 -  ...
 
 New Compiler Flags
 ------------------
 
-The integrated assembler is now turned on by default on ARM (and Thumb),
-so the use of the option `-fintegrated-as` is now redundant on those
-architectures. This is an important move to both *eat our own dog food*
-and to ease cross-compilation tremendously.
+The option ....
 
-We are aware of the problems that this may cause for code bases that
-rely on specific GNU syntax or extensions, and we're working towards
-getting them all fixed. Please, report bugs or feature requests if
-you find anything. In the meantime, use `-fno-integrated-as` to revert
-back the call to GNU assembler.
 
-In order to provide better diagnostics, the integrated assembler validates
-inline assembly when the integrated assembler is enabled.  Because this is
-considered a feature of the compiler, it is controlled via the `fintegrated-as`
-and `fno-integrated-as` flags which enable and disable the integrated assembler
-respectively.  `-integrated-as` and `-no-integrated-as` are now considered
-legacy flags (but are available as an alias to prevent breaking existing users),
-and users are encouraged to switch to the equivalent new feature flag.
+New Pragmas in Clang
+-----------------------
 
-Deprecated flags `-faddress-sanitizer`, `-fthread-sanitizer`,
-`-fcatch-undefined-behavior` and `-fbounds-checking` were removed in favor of
-`-fsanitize=` family of flags.
+Clang now supports the ...
 
-It is now possible to get optimization reports from the major transformation
-passes via three new flags: `-Rpass`, `-Rpass-missed` and `-Rpass-analysis`.
-These flags take a POSIX regular expression which indicates the name
-of the pass (or passes) that should emit optimization remarks.
+Windows Support
+---------------
 
-Options `-u` and `-z` are forwarded to the linker on gnutools toolchains.
+Clang's support for building native Windows programs ...
 
 
-New Pragmas in Clang
------------------------
+C Language Changes in Clang
+---------------------------
+
+...
 
-Loop optimization hints can be specified using the new `#pragma clang loop`
-directive just prior to the desired loop. The directive allows vectorization and
-interleaving to be enabled or disabled. Vector width as well as interleave count
-can be manually specified.  See :ref:`langext-pragma-loop` for details.
+C11 Feature Support
+^^^^^^^^^^^^^^^^^^^
+
+...
 
 C++ Language Changes in Clang
 -----------------------------
 
-- Reference parameters and return values from functions are more aggressively
-  assumed to refer to valid objects when optimizing. Clang will attempt to
-  issue a warning by default if it sees null checks being performed on
-  references, and `-fsanitize=null` can be used to detect null references
-  being formed at runtime.
+- ...
 
-C++17 Feature Support
+C++11 Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
-Clang has experimental support for some proposed C++1z (tentatively, C++17)
-features. This support can be enabled using the `-std=c++1z` flag. The
-supported features are:
-
-- `static_assert(expr)` with no message
-
-- `for (identifier : range)` as a synonym for `for (auto &&identifier : range)`
+...
 
-- `template typename>` as a synonym for `template class>`
+Objective-C Language Changes in Clang
+-------------------------------------
 
-Additionally, trigraphs are not recognized by default in this mode.
-`-ftrigraphs` can be used if you need to parse legacy code that uses trigraphs.
-Note that these features may be changed or removed in future Clang releases
-without notice.
+...
 
-OpenMP C/C++ Language Changes in Clang
---------------------------------------
-
-- `Status of supported OpenMP constructs 
-  `_.
+OpenCL C Language Changes in Clang
+----------------------------------
 
+...
 
 Internal API Changes
 --------------------
 
-These are major API changes that have happened since the 3.4 release of
+These are major API changes that have happened since the 3.5 release of
 Clang. If upgrading an external codebase that uses Clang as a library,
 this section should help get you past the largest hurdles of upgrading.
 
-- Clang uses `std::unique_ptr` in many places where it used to use
-  raw `T *` pointers.
+...
+
+libclang
+--------
+
+...
 
 Static Analyzer
 ---------------
 
-Check for code testing a variable for 0 after using it as a denominator.
-This new checker, alpha.core.TestAfterDivZero, catches issues like this:
+...
+
+Core Analysis Improvements
+==========================
 
-.. code-block:: c
+- ...
 
-  int sum = ...
-  int avg = sum / count; // potential division by zero...
-  if (count == 0) { ... } // ...caught here
+New Issues Found
+================
 
+- ...
 
-The `-analyzer-config` options are now passed from scan-build through to
-ccc-analyzer and then to Clang.
+Python Binding Changes
+----------------------
 
-With the option `-analyzer-config stable-report-filename=true`,
-instead of `report-XXXXXX.html`, scan-build/clang analyzer generate
-`report----.html`.
-(id = i++ for several issues found in the same function/method).
+The following methods have been added:
 
-List the function/method name in the index page of scan-build.
+-  ...
 
 Significant Known Problems
 ==========================
diff --git a/docs/ThreadSafetyAnalysis.rst b/docs/ThreadSafetyAnalysis.rst
index dfef80b..0a1b804 100644
--- a/docs/ThreadSafetyAnalysis.rst
+++ b/docs/ThreadSafetyAnalysis.rst
@@ -10,8 +10,8 @@ Clang Thread Safety Analysis is a C++ language extension which warns about
 potential race conditions in code.  The analysis is completely static (i.e.
 compile-time); there is no run-time overhead.  The analysis is still
 under active development, but it is mature enough to be deployed in an
-industrial setting.  It being developed by Google, and is used extensively
-on their internal code base.
+industrial setting.  It is being developed by Google, in collaboration with
+CERT/SEI, and is used extensively in Google's internal code base.
 
 Thread safety analysis works very much like a type system for multi-threaded
 programs.  In addition to declaring the *type* of data (e.g. ``int``, ``float``,
@@ -21,7 +21,7 @@ controlled in a multi-threaded environment.  For example, if ``foo`` is
 a piece of code reads or writes to ``foo`` without first locking ``mu``.
 Similarly, if there are particular routines that should only be called by
 the GUI thread, then the analysis will warn if other threads call those
-routines. 
+routines.
 
 Getting Started
 ----------------
@@ -34,21 +34,21 @@ Getting Started
   private:
     Mutex mu;
     int   balance GUARDED_BY(mu);
-  
+
     void depositImpl(int amount) {
       balance += amount;       // WARNING! Cannot write balance without locking mu.
     }
-  
-    void withdrawImpl(int amount) EXCLUSIVE_LOCKS_REQUIRED(mu) {
+
+    void withdrawImpl(int amount) REQUIRES(mu) {
       balance -= amount;       // OK. Caller must have locked mu.
     }
-  
+
   public:
     void withdraw(int amount) {
       mu.Lock();
       withdrawImpl(amount);    // OK.  We've locked mu.
     }                          // WARNING!  Failed to unlock mu.
-  
+
     void transferFrom(BankAccount& b, int amount) {
       mu.Lock();
       b.withdrawImpl(amount);  // WARNING!  Calling withdrawImpl() requires locking b.mu.
@@ -60,23 +60,23 @@ Getting Started
 This example demonstrates the basic concepts behind the analysis.  The
 ``GUARDED_BY`` attribute declares that a thread must lock ``mu`` before it can
 read or write to ``balance``, thus ensuring that the increment and decrement
-operations are atomic.  Similarly, ``EXCLUSIVE_LOCKS_REQUIRED`` declares that
+operations are atomic.  Similarly, ``REQUIRES`` declares that
 the calling thread must lock ``mu`` before calling ``withdrawImpl``.
 Because the caller is assumed to have locked ``mu``, it is safe to modify
 ``balance`` within the body of the method.
 
-The ``depositImpl()`` method does not have ``EXCLUSIVE_LOCKS_REQUIRED``, so the
+The ``depositImpl()`` method does not have ``REQUIRES``, so the
 analysis issues a warning.  Thread safety analysis is not inter-procedural, so
 caller requirements must be explicitly declared.
 There is also a warning in ``transferFrom()``, because although the method
 locks ``this->mu``, it does not lock ``b.mu``.  The analysis understands
-that these are two separate mutexes, in two different objects.  
+that these are two separate mutexes, in two different objects.
 
 Finally, there is a warning in the ``withdraw()`` method, because it fails to
 unlock ``mu``.  Every lock must have a corresponding unlock, and the analysis
 will detect both double locks, and double unlocks.  A function is allowed to
 acquire a lock without releasing it, (or vice versa), but it must be annotated
-as such (using ``LOCK``/``UNLOCK_FUNCTION``).
+as such (using ``ACQUIRE``/``RELEASE``).
 
 
 Running The Analysis
@@ -90,7 +90,7 @@ To run the analysis, simply compile with the ``-Wthread-safety`` flag, e.g.
 
 Note that this example assumes the presence of a suitably annotated
 :ref:`mutexheader` that declares which methods perform locking,
-unlocking, and so on. 
+unlocking, and so on.
 
 
 Basic Concepts: Capabilities
@@ -106,14 +106,14 @@ Capabilities are associated with named C++ objects which declare specific
 methods to acquire and release the capability.  The name of the object serves
 to identify the capability.  The most common example is a mutex.  For example,
 if ``mu`` is a mutex, then calling ``mu.Lock()`` causes the calling thread
-to acquire the capability to access data that is protected by ``mu``. Similarly, 
+to acquire the capability to access data that is protected by ``mu``. Similarly,
 calling ``mu.Unlock()`` releases that capability.
 
 A thread may hold a capability either *exclusively* or *shared*.  An exclusive
 capability can be held by only one thread at a time, while a shared capability
 can be held by many threads at the same time.  This mechanism enforces a
 multiple-reader, single-writer pattern.  Write operations to protected data
-require exclusive access, while read operations require only shared access.  
+require exclusive access, while read operations require only shared access.
 
 At any given moment during program execution, a thread holds a specific set of
 capabilities (e.g. the set of mutexes that it has locked.)  These act like keys
@@ -121,7 +121,7 @@ or tokens that allow the thread to access a given resource.  Just like physical
 security keys, a thread cannot make copy of a capability, nor can it destroy
 one.  A thread can only release a capability to another thread, or acquire one
 from another thread.  The annotations are deliberately agnostic about the
-exact mechanism used to acquire and release capabilities; it assumes that the 
+exact mechanism used to acquire and release capabilities; it assumes that the
 underlying implementation (e.g. the Mutex implementation) does the handoff in
 an appropriate manner.
 
@@ -144,6 +144,11 @@ and data members. Users are *strongly advised* to define macros for the various
 attributes; example definitions can be found in :ref:`mutexheader`, below.
 The following documentation assumes the use of macros.
 
+For historical reasons, prior versions of thread safety used macro names that
+were very lock-centric.  These macros have since been renamed to fit a more
+general capability model.  The prior names are still in use, and will be
+mentioned under the tag *previously* where appropriate.
+
 
 GUARDED_BY(c) and PT_GUARDED_BY(c)
 ----------------------------------
@@ -154,47 +159,49 @@ require shared access, while write operations require exclusive access.
 
 ``PT_GUARDED_BY`` is similar, but is intended for use on pointers and smart
 pointers. There is no constraint on the data member itself, but the *data that
-it points to* is protected by the given capability.  
+it points to* is protected by the given capability.
 
 .. code-block:: c++
 
   Mutex mu;
-  int *p1            GUARDED_BY(mu);
-  int *p2            PT_GUARDED_BY(mu);
-  unique_ptr p3 PT_GUARDED_BY(mu);
-  
+  int *p1             GUARDED_BY(mu);
+  int *p2             PT_GUARDED_BY(mu);
+  unique_ptr p3  PT_GUARDED_BY(mu);
+
   void test() {
     p1 = 0;             // Warning!
-  
-    p2 = new int;       // OK.
+
     *p2 = 42;           // Warning!
-  
-    p3.reset(new int);  // OK.
+    p2 = new int;       // OK.
+
     *p3 = 42;           // Warning!
+    p3.reset(new int);  // OK.
   }
 
 
-EXCLUSIVE_LOCKS_REQUIRED(...), SHARED_LOCKS_REQUIRED(...)
----------------------------------------------------------
+REQUIRES(...), REQUIRES_SHARED(...)
+-----------------------------------
+
+*Previously*: ``EXCLUSIVE_LOCKS_REQUIRED``, ``SHARED_LOCKS_REQUIRED``
 
-``EXCLUSIVE_LOCKS_REQUIRED`` is an attribute on functions or methods, which
+``REQUIRES`` is an attribute on functions or methods, which
 declares that the calling thread must have exclusive access to the given
 capabilities.  More than one capability may be specified.  The capabilities
-must be held on entry to the function, *and must still be held on exit*.  
+must be held on entry to the function, *and must still be held on exit*.
 
-``SHARED_LOCKS_REQUIRED`` is similar, but requires only shared access.
+``REQUIRES_SHARED`` is similar, but requires only shared access.
 
 .. code-block:: c++
 
   Mutex mu1, mu2;
   int a GUARDED_BY(mu1);
   int b GUARDED_BY(mu2);
-  
-  void foo() EXCLUSIVE_LOCKS_REQUIRED(mu1, mu2) {
+
+  void foo() REQUIRES(mu1, mu2) {
     a = 0;
     b = 0;
   }
-  
+
   void test() {
     mu1.Lock();
     foo();         // Warning!  Requires mu2.
@@ -202,32 +209,36 @@ must be held on entry to the function, *and must still be held on exit*.
   }
 
 
-EXCLUSIVE_LOCK_FUNCTION(...), SHARED_LOCK_FUNCTION(...), UNLOCK_FUNCTION(...)
------------------------------------------------------------------------------
+ACQUIRE(...), ACQUIRE_SHARED(...), RELEASE(...), RELEASE_SHARED(...)
+--------------------------------------------------------------------
+
+*Previously*: ``EXCLUSIVE_LOCK_FUNCTION``, ``SHARED_LOCK_FUNCTION``,
+``UNLOCK_FUNCTION``
 
-``EXCLUSIVE_LOCK_FUNCTION`` is an attribute on functions or methods, which
+``ACQUIRE`` is an attribute on functions or methods, which
 declares that the function acquires a capability, but does not release it.  The
 caller must not hold the given capability on entry, and it will hold the
-capability on exit.  ``SHARED_LOCK_FUNCTION`` is similar. 
+capability on exit.  ``ACQUIRE_SHARED`` is similar.
 
-``UNLOCK_FUNCTION`` declares that the function releases the given capability.
-The caller must hold the capability on entry, and will no longer hold it on
-exit. It does not matter whether the given capability is shared or exclusive.
+``RELEASE`` and ``RELEASE_SHARED`` declare that the function releases the given
+capability.  The caller must hold the capability on entry, and will no longer
+hold it on exit. It does not matter whether the given capability is shared or
+exclusive.
 
 .. code-block:: c++
 
   Mutex mu;
   MyClass myObject GUARDED_BY(mu);
-  
-  void lockAndInit() EXCLUSIVE_LOCK_FUNCTION(mu) {
+
+  void lockAndInit() ACQUIRE(mu) {
     mu.Lock();
     myObject.init();
   }
-  
-  void cleanupAndUnlock() UNLOCK_FUNCTION(mu) {
+
+  void cleanupAndUnlock() RELEASE(mu) {
     myObject.cleanup();
-  }  // Warning!  Need to unlock mu.
-  
+  }                          // Warning!  Need to unlock mu.
+
   void test() {
     lockAndInit();
     myObject.doSomething();
@@ -235,27 +246,27 @@ exit. It does not matter whether the given capability is shared or exclusive.
     myObject.doSomething();  // Warning, mu is not locked.
   }
 
-If no argument is passed to ``(UN)LOCK_FUNCTION``, then the argument is assumed
-to be ``this``, and the analysis will not check the body of the function.  This
-pattern is intended for use by classes which hide locking details behind an
-abstract interface.  E.g.
+If no argument is passed to ``ACQUIRE`` or ``RELEASE``, then the argument is
+assumed to be ``this``, and the analysis will not check the body of the
+function.  This pattern is intended for use by classes which hide locking
+details behind an abstract interface.  For example:
 
 .. code-block:: c++
 
   template 
-  class LOCKABLE Container {
+  class CAPABILITY("mutex") Container {
   private:
     Mutex mu;
     T* data;
-  
+
   public:
     // Hide mu from public interface.
-    void Lock() EXCLUSIVE_LOCK_FUNCTION() { mu.Lock(); }
-    void Unlock() UNLOCK_FUNCTION() { mu.Unlock(); }
-  
+    void Lock()   ACQUIRE() { mu.Lock(); }
+    void Unlock() RELEASE() { mu.Unlock(); }
+
     T& getElem(int i) { return data[i]; }
   };
-  
+
   void test() {
     Container c;
     c.Lock();
@@ -264,33 +275,36 @@ abstract interface.  E.g.
   }
 
 
-LOCKS_EXCLUDED(...)
--------------------
+EXCLUDES(...)
+-------------
+
+*Previously*: ``LOCKS_EXCLUDED``
 
-``LOCKS_EXCLUDED`` is an attribute on functions or methods, which declares that
+``EXCLUDES`` is an attribute on functions or methods, which declares that
 the caller must *not* hold the given capabilities.  This annotation is
 used to prevent deadlock.  Many mutex implementations are not re-entrant, so
-deadlock can occur if the function in question acquires the mutex a second time.
+deadlock can occur if the function acquires the mutex a second time.
 
 .. code-block:: c++
 
   Mutex mu;
   int a GUARDED_BY(mu);
-  
-  void clear() LOCKS_EXCLUDED(mu) {
+
+  void clear() EXCLUDES(mu) {
     mu.Lock();
     a = 0;
     mu.Unlock();
   }
-  
+
   void reset() {
     mu.Lock();
     clear();     // Warning!  Caller cannot hold 'mu'.
     mu.Unlock();
   }
 
-Unlike ``LOCKS_REQUIRED``, ``LOCKS_EXCLUDED`` is optional.  The analysis will
-not issue a warning if the attribute is missing.  See :ref:`limitations`.
+Unlike ``REQUIRES``, ``EXCLUDES`` is optional.  The analysis will not issue a
+warning if the attribute is missing, which can lead to false negatives in some
+cases.  This issue is discussed further in :ref:`negative`.
 
 
 NO_THREAD_SAFETY_ANALYSIS
@@ -307,16 +321,23 @@ thread-safe, but too complicated for the analysis to understand.  Reasons for
   class Counter {
     Mutex mu;
     int a GUARDED_BY(mu);
-  
+
     void unsafeIncrement() NO_THREAD_SAFETY_ANALYSIS { a++; }
   };
 
+Unlike the other attributes, NO_THREAD_SAFETY_ANALYSIS is not part of the
+interface of a function, and should thus be placed on the function definition
+(in the ``.cc`` or ``.cpp`` file) rather than on the function declaration
+(in the header).
 
-LOCK_RETURNED(c)
-----------------
 
-``LOCK_RETURNED`` is an attribute on functions or methods, which declares that
-the function returns a reference to the given capability.  It is used to
+RETURN_CAPABILITY(c)
+--------------------
+
+*Previously*: ``LOCK_RETURNED``
+
+``RETURN_CAPABILITY`` is an attribute on functions or methods, which declares
+that the function returns a reference to the given capability.  It is used to
 annotate getter methods that return mutexes.
 
 .. code-block:: c++
@@ -325,12 +346,12 @@ annotate getter methods that return mutexes.
   private:
     Mutex mu;
     int a GUARDED_BY(mu);
-  
+
   public:
-    Mutex* getMu() LOCK_RETURNED(mu) { return μ }
-  
+    Mutex* getMu() RETURN_CAPABILITY(mu) { return μ }
+
     // analysis knows that getMu() == mu
-    void clear() EXCLUSIVE_LOCKS_REQUIRED(getMu()) { a = 0; }
+    void clear() REQUIRES(getMu()) { a = 0; }
   };
 
 
@@ -346,11 +367,11 @@ acquired, in order to prevent deadlock.
 
   Mutex m1;
   Mutex m2 ACQUIRED_AFTER(m1);
-  
+
   // Alternative declaration
   // Mutex m2;
   // Mutex m1 ACQUIRED_BEFORE(m2);
-  
+
   void foo() {
     m2.Lock();
     m1.Lock();  // Warning!  m2 must be acquired after m1.
@@ -359,36 +380,45 @@ acquired, in order to prevent deadlock.
   }
 
 
-LOCKABLE
---------
+CAPABILITY()
+--------------------
 
-``LOCKABLE`` is an attribute on classes, which specifies that objects of the
-class can be used as a capability.  See the ``Container`` example given above,
-or the ``Mutex`` class in :ref:`mutexheader`.
+*Previously*: ``LOCKABLE``
 
+``CAPABILITY`` is an attribute on classes, which specifies that objects of the
+class can be used as a capability.  The string argument specifies the kind of
+capability in error messages, e.g. ``"mutex"``.  See the ``Container`` example
+given above, or the ``Mutex`` class in :ref:`mutexheader`.
 
-SCOPED_LOCKABLE
----------------
 
-``SCOPED_LOCKABLE`` is an attribute on classes that implement RAII-style
+SCOPED_CAPABILITY
+-----------------
+
+*Previously*: ``SCOPED_LOCKABLE``
+
+``SCOPED_CAPABILITY`` is an attribute on classes that implement RAII-style
 locking, in which a capability is acquired in the constructor, and released in
 the destructor.  Such classes require special handling because the constructor
 and destructor refer to the capability via different names; see the
 ``MutexLocker`` class in :ref:`mutexheader`, below.
 
 
-EXCLUSIVE_TRYLOCK_FUNCTION(, ...), SHARED_TRYLOCK_FUNCTION(, ...)
------------------------------------------------------------------------------
+TRY_ACQUIRE(, ...), TRY_ACQUIRE_SHARED(, ...)
+---------------------------------------------------------
+
+*Previously:* ``EXCLUSIVE_TRYLOCK_FUNCTION``, ``SHARED_TRYLOCK_FUNCTION``
 
 These are attributes on a function or method that tries to acquire the given
 capability, and returns a boolean value indicating success or failure.
 The first argument must be ``true`` or ``false``, to specify which return value
 indicates success, and the remaining arguments are interpreted in the same way
-as ``(UN)LOCK_FUNCTION``.  See :ref:`mutexheader`, below, for example uses.
+as ``ACQUIRE``.  See :ref:`mutexheader`, below, for example uses.
 
 
-ASSERT_EXCLUSIVE_LOCK(...) and ASSERT_SHARED_LOCK(...)
-------------------------------------------------------
+ASSERT_CAPABILITY(...) and ASSERT_SHARED_CAPABILITY(...)
+--------------------------------------------------------
+
+*Previously:*  ``ASSERT_EXCLUSIVE_LOCK``, ``ASSERT_SHARED_LOCK``
 
 These are attributes on a function or method that does a run-time test to see
 whether the calling thread holds the given capability.  The function is assumed
@@ -410,13 +440,104 @@ Warning flags
   + ``-Wthread-safety-attributes``: Sanity checks on attribute syntax.
   + ``-Wthread-safety-analysis``: The core analysis.
   + ``-Wthread-safety-precise``: Requires that mutex expressions match precisely.
-    This warning can be disabled for code which has a lot of aliases.
+       This warning can be disabled for code which has a lot of aliases.
+  + ``-Wthread-safety-reference``: Checks when guarded members are passed by reference.
+
+
+:ref:`negative` are an experimental feature, which are enabled with:
+
+* ``-Wthread-safety-negative``:  Negative capabilities.  Off by default.
 
 When new features and checks are added to the analysis, they can often introduce
 additional warnings.  Those warnings are initially released as *beta* warnings
-for a period of time, after which they are migrated to the standard analysis.  
+for a period of time, after which they are migrated into the standard analysis.
+
+* ``-Wthread-safety-beta``:  New features.  Off by default.
+
+
+.. _negative:
 
-* ``-Wthread-safety-beta``:  New features.  Off by default. 
+Negative Capabilities
+=====================
+
+Thread Safety Analysis is designed to prevent both race conditions and
+deadlock.  The GUARDED_BY and REQUIRES attributes prevent race conditions, by
+ensuring that a capability is held before reading or writing to guarded data,
+and the EXCLUDES attribute prevents deadlock, by making sure that a mutex is
+*not* held.
+
+However, EXCLUDES is an optional attribute, and does not provide the same
+safety guarantee as REQUIRES.  In particular:
+
+  * A function which acquires a capability does not have to exclude it.
+  * A function which calls a function that excludes a capability does not
+    have transitively exclude that capability.
+
+As a result, EXCLUDES can easily produce false negatives:
+
+.. code-block:: c++
+
+  class Foo {
+    Mutex mu;
+
+    void foo() {
+      mu.Lock();
+      bar();           // No warning.
+      baz();           // No warning.
+      mu.Unlock();
+    }
+
+    void bar() {       // No warning.  (Should have EXCLUDES(mu)).
+      mu.Lock();
+      // ...
+      mu.Unlock();
+    }
+
+    void baz() {
+      bif();           // No warning.  (Should have EXCLUDES(mu)).
+    }
+
+    void bif() EXCLUDES(mu);
+  };
+
+
+Negative requirements are an alternative EXCLUDES that provide
+a stronger safety guarantee.  A negative requirement uses the  REQUIRES
+attribute, in conjunction with the ``!`` operator, to indicate that a capability
+should *not* be held.
+
+For example, using ``REQUIRES(!mu)`` instead of ``EXCLUDES(mu)`` will produce
+the appropriate warnings:
+
+.. code-block:: c++
+
+  class FooNeg {
+    Mutex mu;
+
+    void foo() REQUIRES(!mu) {   // foo() now requires !mu.
+      mu.Lock();
+      bar();
+      baz();
+      mu.Unlock();
+    }
+
+    void bar() {
+      mu.Lock();       // WARNING!  Missing REQUIRES(!mu).
+      // ...
+      mu.Unlock();
+    }
+
+    void baz() {
+      bif();           // WARNING!  Missing REQUIRES(!mu).
+    }
+
+    void bif() REQUIRES(!mu);
+  };
+
+
+Negative requirements are an experimental feature which is off by default,
+because it will produce many warnings in existing code.  It can be enabled
+by passing ``-Wthread-safety-negative``.
 
 
 .. _faq:
@@ -426,7 +547,10 @@ Frequently Asked Questions
 
 (Q) Should I put attributes in the header file, or in the .cc/.cpp/.cxx file?
 
-(A) Attributes should always go in the header.
+(A) Attributes are part of the formal interface of a function, and should
+always go in the header, where they are visible to anything that includes
+the header.  Attributes in the .cpp file are not visible outside of the
+immediate translation unit, which leads to false negatives and false positives.
 
 
 (Q) "*Mutex is not locked on every path through here?*"  What does that mean?
@@ -436,7 +560,7 @@ Frequently Asked Questions
 
 .. _limitations:
 
-Known Limitations 
+Known Limitations
 =================
 
 Lexical scope
@@ -448,14 +572,14 @@ capabilities must be declared before they can be used in an attribute.
 Use-before-declaration is okay within a single class, because attributes are
 parsed at the same time as method bodies. (C++ delays parsing of method bodies
 until the end of the class.)  However, use-before-declaration is not allowed
-between classes, as illustrated below.  
+between classes, as illustrated below.
 
 .. code-block:: c++
 
   class Foo;
 
   class Bar {
-    void bar(Foo* f) EXCLUSIVE_LOCKS_REQUIRED(f->mu);  // Error: mu undeclared.
+    void bar(Foo* f) REQUIRES(f->mu);  // Error: mu undeclared.
   };
 
   class Foo {
@@ -474,9 +598,9 @@ Thread safety attributes follow normal C++ access restrictions, so if ``mu``
 is a private member of ``c``, then it is an error to write ``c.mu`` in an
 attribute.
 
-One workround is to (ab)use the ``LOCK_RETURNED`` attribute to provide a public
-*name* for a private mutex, without actually exposing the underlying mutex.
-For example:
+One workaround is to (ab)use the ``RETURN_CAPABILITY`` attribute to provide a
+public *name* for a private mutex, without actually exposing the underlying
+mutex.  For example:
 
 .. code-block:: c++
 
@@ -486,12 +610,12 @@ For example:
 
   public:
     // For thread safety analysis only.  Does not actually return mu.
-    Mutex* getMu() LOCK_RETURNED(mu) { return 0; }
+    Mutex* getMu() RETURN_CAPABILITY(mu) { return 0; }
 
-    void doSomething() EXCLUSIVE_LOCKS_REQUIRED(mu); 
+    void doSomething() REQUIRES(mu);
   };
 
-  void doSomethingTwice(MyClass& c) EXCLUSIVE_LOCKS_REQUIRED(c.getMu()) {
+  void doSomethingTwice(MyClass& c) REQUIRES(c.getMu()) {
     // The analysis thinks that c.getMu() == c.mu
     c.doSomething();
     c.doSomething();
@@ -506,43 +630,6 @@ as a fake getter method, which is provided only for the benefit of thread
 safety analysis.
 
 
-False negatives on pass by reference.
--------------------------------------
-
-The current version of the analysis only checks operations which refer to
-guarded data members directly by name.  If the data members are accessed
-indirectly, via a pointer or reference, then no warning is generated.  Thus,
-no warnings will be generated for the following code:
-
-.. code-block:: c++
-
-  Mutex mu;
-  int a GUARDED_BY(mu);
-
-  void clear(int& ra) { ra = 0; }
-
-  void test() {
-    int *p = &a;
-    *p = 0;       // No warning.  *p is an alias to a.  
-       
-    clear(a);     // No warning.  'a' is passed by reference.
-  }
-
-This issue is by far the biggest source of false negatives in the current
-version of the analysis.  At a fundamental level, the
-false negatives are caused by the fact that annotations are attached to data
-members, rather than types.  The type of ``&a`` should really be
-``int GUARDED_BY(mu)*``, rather than ``int*``, and the statement ``p = &a``
-should thus generate a type error.  However, attaching attributes to types
-would be an invasive change to the C++ type system, with potential
-ramifications with respect to template instantation, function overloading,
-and so on.  Thus, a complete solution to this issue is simply not feasible.
-
-Future versions of the analysis will include better support for pointer
-alias analysis, along with limited checking of guarded types, in order to
-reduce the number of false negatives.
-
-
 .. _conditional_locks:
 
 No conditionally held locks.
@@ -557,7 +644,7 @@ generate spurious warnings (false positives).  For example:
   void foo() {
     bool b = needsToLock();
     if (b) mu.Lock();
-    ...  // Warning!  Mutex 'mu' is not held on every path through here. 
+    ...  // Warning!  Mutex 'mu' is not held on every path through here.
     if (b) mu.Unlock();
   }
 
@@ -567,7 +654,7 @@ No checking inside constructors and destructors.
 
 The analysis currently does not do any checking inside constructors or
 destructors.  In other words, every constructor and destructor is treated as
-if it was annotated with ``NO_THREAD_SAFETY_ANALYSIS``.  
+if it was annotated with ``NO_THREAD_SAFETY_ANALYSIS``.
 The reason for this is that during initialization, only one thread typically
 has access to the object which is being initialized, and it is thus safe (and
 common practice) to initialize guarded members without acquiring any locks.
@@ -577,15 +664,15 @@ Ideally, the analysis would allow initialization of guarded members inside the
 object being initialized or destroyed, while still enforcing the usual access
 restrictions on everything else.  However, this is difficult to enforce in
 practice, because in complex pointer-based data structures, it is hard to
-determine what data is "owned by" the enclosing object.
+determine what data is owned by the enclosing object.
 
 No inlining.
 ------------
 
 Thread safety analysis is strictly intra-procedural, just like ordinary type
 checking.  It relies only on the declared attributes of a function, and will
-not attempt to "step inside", or inline any method calls.  As a result, code
-such as the following will not work:
+not attempt to inline any method calls.  As a result, code such as the
+following will not work:
 
 .. code-block:: c++
 
@@ -593,7 +680,7 @@ such as the following will not work:
   class AutoCleanup {
     T* object;
     void (T::*mp)();
-    
+
   public:
     AutoCleanup(T* obj, void (T::*imp)()) : object(obj), mp(imp) { }
     ~AutoCleanup() { (object->*mp)(); }
@@ -602,8 +689,8 @@ such as the following will not work:
   Mutex mu;
   void foo() {
     mu.Lock();
-    AutoCleanup(&mu, &Mutex::Unlock); 
-    ...
+    AutoCleanup(&mu, &Mutex::Unlock);
+    // ...
   }  // Warning, mu is not unlocked.
 
 In this case, the destructor of ``Autocleanup`` calls ``mu.Unlock()``, so
@@ -611,42 +698,14 @@ the warning is bogus.  However,
 thread safety analysis cannot see the unlock, because it does not attempt to
 inline the destructor.  Moreover, there is no way to annotate the destructor,
 because the destructor is calling a function that is not statically known.
-This pattern is simply not supported. 
-
-
-LOCKS_EXCLUDED is not transitive.
----------------------------------
-
-A function which calls a method marked with LOCKS_EXCLUDED is not required to
-put LOCKS_EXCLUDED in its own interface.  LOCKS_EXCLUDED behaves differently
-from LOCKS_REQUIRED in this respect, and it can result in false negatives:
-
-.. code-block:: c++
-
-  class Foo {
-    Mutex mu;
-    
-    void foo() {
-      mu.Lock();
-      bar();                // No warning
-      mu.Unlock();
-    }
-    
-    void bar() { baz(); }   // No warning.  (Should have LOCKS_EXCLUDED(mu).)
-    
-    void baz() LOCKS_EXCLUDED(mu);
-  };
-
-The lack of transitivity is due to the fact that LOCKS_EXCLUDED can easily
-break encapsulation; it would be a bad idea to require functions to list the
-names private locks which happen to be acquired internally.  
+This pattern is simply not supported.
 
 
 No alias analysis.
 ------------------
 
 The analysis currently does not track pointer aliases.  Thus, there can be
-false positives if two pointers both point to the same mutex.  
+false positives if two pointers both point to the same mutex.
 
 
 .. code-block:: c++
@@ -655,13 +714,13 @@ false positives if two pointers both point to the same mutex.
     Mutex* mu;
 
   public:
-    MutexUnlocker(Mutex* m) UNLOCK_FUNCTION(m) : mu(m)  { mu->Unlock(); }
-    ~MutexUnlocker() EXCLUSIVE_LOCK_FUNCTION(mu) { mu->Lock(); }
+    MutexUnlocker(Mutex* m) RELEASE(m) : mu(m)  { mu->Unlock(); }
+    ~MutexUnlocker() ACQUIRE(mu) { mu->Lock(); }
   };
 
   Mutex mutex;
-  void test() EXCLUSIVE_LOCKS_REQUIRED(mutex) {
-    { 
+  void test() REQUIRES(mutex) {
+    {
       MutexUnlocker munl(&mutex);  // unlocks mutex
       doSomeIO();
     }                              // Warning: locks munl.mu
@@ -669,14 +728,14 @@ false positives if two pointers both point to the same mutex.
 
 The MutexUnlocker class is intended to be the dual of the MutexLocker class,
 defined in :ref:`mutexheader`.  However, it doesn't work because the analysis
-doesn't know that munl.mu == mutex.  The SCOPED_LOCKABLE attribute handles
-aliasing 
+doesn't know that munl.mu == mutex.  The SCOPED_CAPABILITY attribute handles
+aliasing for MutexLocker, but does so only for that particular pattern.
 
 
 ACQUIRED_BEFORE(...) and ACQUIRED_AFTER(...) are currently unimplemented.
 -------------------------------------------------------------------------
 
-To be fixed in a future update. 
+To be fixed in a future update.
 
 
 .. _mutexheader:
@@ -688,14 +747,15 @@ Thread safety analysis can be used with any threading library, but it does
 require that the threading API be wrapped in classes and methods which have the
 appropriate annotations.  The following code provides ``mutex.h`` as an example;
 these methods should be filled in to call the appropriate underlying
-implementation. 
+implementation.
 
 
 .. code-block:: c++
 
+
   #ifndef THREAD_SAFETY_ANALYSIS_MUTEX_H
   #define THREAD_SAFETY_ANALYSIS_MUTEX_H
-  
+
   // Enable thread safety attributes only with clang.
   // The attributes can be safely erased when compiling with other compilers.
   #if defined(__clang__) && (!defined(SWIG))
@@ -703,116 +763,185 @@ implementation.
   #else
   #define THREAD_ANNOTATION_ATTRIBUTE__(x)   // no-op
   #endif
-  
+
   #define THREAD_ANNOTATION_ATTRIBUTE__(x)   __attribute__((x))
-  
+
+  #define CAPABILITY(x) \
+    THREAD_ANNOTATION_ATTRIBUTE__(capability(x))
+
+  #define SCOPED_CAPABILITY \
+    THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
   #define GUARDED_BY(x) \
     THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x))
-  
-  #define GUARDED_VAR \
-    THREAD_ANNOTATION_ATTRIBUTE__(guarded)
-  
+
   #define PT_GUARDED_BY(x) \
     THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x))
-  
-  #define PT_GUARDED_VAR \
-    THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded)
-  
-  #define ACQUIRED_AFTER(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
-  
+
   #define ACQUIRED_BEFORE(...) \
     THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__))
-  
-  #define EXCLUSIVE_LOCKS_REQUIRED(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
-  
-  #define SHARED_LOCKS_REQUIRED(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
-  
-  #define LOCKS_EXCLUDED(...) \
+
+  #define ACQUIRED_AFTER(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__))
+
+  #define REQUIRES(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__))
+
+  #define REQUIRES_SHARED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__))
+
+  #define ACQUIRE(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__))
+
+  #define ACQUIRE_SHARED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__))
+
+  #define RELEASE(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__))
+
+  #define RELEASE_SHARED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__))
+
+  #define TRY_ACQUIRE(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__))
+
+  #define TRY_ACQUIRE_SHARED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__))
+
+  #define EXCLUDES(...) \
     THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
-  
-  #define LOCK_RETURNED(x) \
+
+  #define ASSERT_CAPABILITY(x) \
+    THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x))
+
+  #define ASSERT_SHARED_CAPABILITY(x) \
+    THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x))
+
+  #define RETURN_CAPABILITY(x) \
     THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
-  
-  #define LOCKABLE \
-    THREAD_ANNOTATION_ATTRIBUTE__(lockable)
-  
-  #define SCOPED_LOCKABLE \
-    THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
-  
-  #define EXCLUSIVE_LOCK_FUNCTION(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
-  
-  #define SHARED_LOCK_FUNCTION(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
-  
-  #define ASSERT_EXCLUSIVE_LOCK(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
-  
-  #define ASSERT_SHARED_LOCK(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
-  
-  #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
-  
-  #define SHARED_TRYLOCK_FUNCTION(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
-  
-  #define UNLOCK_FUNCTION(...) \
-    THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
-  
+
   #define NO_THREAD_SAFETY_ANALYSIS \
     THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
-  
-  
+
+
   // Defines an annotated interface for mutexes.
   // These methods can be implemented to use any internal mutex implementation.
-  class LOCKABLE Mutex {
+  class CAPABILITY("mutex") Mutex {
   public:
     // Acquire/lock this mutex exclusively.  Only one thread can have exclusive
     // access at any one time.  Write operations to guarded data require an
     // exclusive lock.
-    void Lock() EXCLUSIVE_LOCK_FUNCTION();
-  
+    void Lock() ACQUIRE();
+
     // Acquire/lock this mutex for read operations, which require only a shared
     // lock.  This assumes a multiple-reader, single writer semantics.  Multiple
-    // threads may acquire the mutex simultaneously as readers, but a writer must
-    // wait for all of them to release the mutex before it can acquire it
-    // exclusively.  
-    void ReaderLock() SHARED_LOCK_FUNCTION();
-  
-    // Release/unlock the mutex, regardless of whether it is exclusive or shared.
-    void Unlock() UNLOCK_FUNCTION();
-  
+    // threads may acquire the mutex simultaneously as readers, but a writer
+    // must wait for all of them to release the mutex before it can acquire it
+    // exclusively.
+    void ReaderLock() ACQUIRE_SHARED();
+
+    // Release/unlock an exclusive mutex.
+    void Unlock() RELEASE();
+
+    // Release/unlock a shared mutex.
+    void ReaderUnlock() RELEASE_SHARED();
+
     // Try to acquire the mutex.  Returns true on success, and false on failure.
-    bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true);
-  
+    bool TryLock() TRY_ACQUIRE(true);
+
     // Try to acquire the mutex for read operations.
-    bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true);
-  
+    bool ReaderTryLock() TRY_ACQUIRE_SHARED(true);
+
     // Assert that this mutex is currently held by the calling thread.
-    void AssertHeld() ASSERT_EXCLUSIVE_LOCK();
-  
-    // Assert that is mutex is currently held for read operations. 
-    void AssertReaderHeld() ASSERT_SHARED_LOCK();
+    void AssertHeld() ASSERT_CAPABILITY(this);
+
+    // Assert that is mutex is currently held for read operations.
+    void AssertReaderHeld() ASSERT_SHARED_CAPABILITY(this);
   };
-  
-  
+
+
   // MutexLocker is an RAII class that acquires a mutex in its constructor, and
-  // releases it in its destructor.  
-  class SCOPED_LOCKABLE MutexLocker {
+  // releases it in its destructor.
+  class SCOPED_CAPABILITY MutexLocker {
   private:
     Mutex* mut;
-  
+
   public:
-    MutexLocker(Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mut(mu) {
+    MutexLocker(Mutex *mu) ACQUIRE(mu) : mut(mu) {
       mu->Lock();
-    }  
-    ~MutexLocker() UNLOCK_FUNCTION() {
+    }
+    ~MutexLocker() RELEASE() {
       mut->Unlock();
     }
   };
-  
+
+
+  #ifdef USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
+  // The original version of thread safety analysis the following attribute
+  // definitions.  These use a lock-based terminology.  They are still in use
+  // by existing thread safety code, and will continue to be supported.
+
+  // Deprecated.
+  #define PT_GUARDED_VAR \
+    THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded)
+
+  // Deprecated.
+  #define GUARDED_VAR \
+    THREAD_ANNOTATION_ATTRIBUTE__(guarded)
+
+  // Replaced by REQUIRES
+  #define EXCLUSIVE_LOCKS_REQUIRED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(exclusive_locks_required(__VA_ARGS__))
+
+  // Replaced by REQUIRES_SHARED
+  #define SHARED_LOCKS_REQUIRED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(shared_locks_required(__VA_ARGS__))
+
+  // Replaced by CAPABILITY
+  #define LOCKABLE \
+    THREAD_ANNOTATION_ATTRIBUTE__(lockable)
+
+  // Replaced by SCOPED_CAPABILITY
+  #define SCOPED_LOCKABLE \
+    THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable)
+
+  // Replaced by ACQUIRE
+  #define EXCLUSIVE_LOCK_FUNCTION(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(exclusive_lock_function(__VA_ARGS__))
+
+  // Replaced by ACQUIRE_SHARED
+  #define SHARED_LOCK_FUNCTION(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(shared_lock_function(__VA_ARGS__))
+
+  // Replaced by RELEASE and RELEASE_SHARED
+  #define UNLOCK_FUNCTION(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(unlock_function(__VA_ARGS__))
+
+  // Replaced by TRY_ACQUIRE
+  #define EXCLUSIVE_TRYLOCK_FUNCTION(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(exclusive_trylock_function(__VA_ARGS__))
+
+  // Replaced by TRY_ACQUIRE_SHARED
+  #define SHARED_TRYLOCK_FUNCTION(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(shared_trylock_function(__VA_ARGS__))
+
+  // Replaced by ASSERT_CAPABILITY
+  #define ASSERT_EXCLUSIVE_LOCK(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(assert_exclusive_lock(__VA_ARGS__))
+
+  // Replaced by ASSERT_SHARED_CAPABILITY
+  #define ASSERT_SHARED_LOCK(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_lock(__VA_ARGS__))
+
+  // Replaced by EXCLUDE_CAPABILITY.
+  #define LOCKS_EXCLUDED(...) \
+    THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__))
+
+  // Replaced by RETURN_CAPABILITY
+  #define LOCK_RETURNED(x) \
+    THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x))
+
+  #endif  // USE_LOCK_STYLE_THREAD_SAFETY_ATTRIBUTES
+
   #endif  // THREAD_SAFETY_ANALYSIS_MUTEX_H
+
diff --git a/docs/UsersManual.rst b/docs/UsersManual.rst
index 90f16ee..fc5af4e 100644
--- a/docs/UsersManual.rst
+++ b/docs/UsersManual.rst
@@ -73,7 +73,7 @@ Basic Usage
 Intro to how to use a C compiler for newbies.
 
 compile + link compile then link debug info enabling optimizations
-picking a language to use, defaults to C99 by default. Autosenses based
+picking a language to use, defaults to C11 by default. Autosenses based
 on extension. using a makefile
 
 Command Line Options
@@ -481,7 +481,7 @@ TODO: Generate this from tblgen. Define one anchor per warning group.
    Warn about an unusable copy constructor when binding a reference to a
    temporary.
 
-   This option, which defaults to on, enables warnings about binding a
+   This option enables warnings about binding a
    reference to a temporary when the temporary doesn't have a usable
    copy constructor. For example:
 
@@ -531,8 +531,6 @@ control the crash diagnostics.
 The -fno-crash-diagnostics flag can be helpful for speeding the process
 of generating a delta reduced test case.
 
-.. _opt_rpass:
-
 Options to Emit Optimization Reports
 ------------------------------------
 
@@ -979,6 +977,8 @@ are listed below.
    -  ``-fsanitize=function``: Indirect call of a function through a
       function pointer of the wrong type (Linux, C++ and x86/x86_64 only).
    -  ``-fsanitize=integer-divide-by-zero``: Integer division by zero.
+   -  ``-fsanitize=nonnull-attribute``: Passing null pointer as a function
+      parameter which is declared to never be null.
    -  ``-fsanitize=null``: Use of a null pointer or creation of a null
       reference.
    -  ``-fsanitize=object-size``: An attempt to use bytes which the
@@ -988,6 +988,8 @@ are listed below.
       more problems at higher optimization levels.
    -  ``-fsanitize=return``: In C++, reaching the end of a
       value-returning function without returning a value.
+   -  ``-fsanitize=returns-nonnull-attribute``: Returning null pointer
+      from a function which is declared to never return null.
    -  ``-fsanitize=shift``: Shift operators where the amount shifted is
       greater or equal to the promoted bit-width of the left hand side
       or less than zero, or where the left hand side is negative. For a
@@ -1031,10 +1033,6 @@ are listed below.
 
    Extra features of UndefinedBehaviorSanitizer:
 
-   -  ``-fno-sanitize-recover``: By default, after a sanitizer diagnoses
-      an issue, it will attempt to continue executing the program if there
-      is a reasonable behavior it can give to the faulting operation. This
-      option causes the program to abort instead.
    -  ``-fsanitize-undefined-trap-on-error``: Causes traps to be emitted
       rather than calls to runtime libraries when a problem is detected.
       This option is intended for use in cases where the sanitizer runtime
@@ -1054,6 +1052,17 @@ are listed below.
    program. The ``-fsanitize=undefined`` checks can be combined with other
    sanitizers.
 
+**-f[no-]sanitize-recover=check1,check2,...**
+
+   Controls which checks enabled by ``-fsanitize=`` flag are non-fatal.
+   If the check is fatal, program will halt after the first error
+   of this kind is detected and error report is printed.
+
+   By default, non-fatal checks are those enabled by UndefinedBehaviorSanitizer,
+   except for ``-fsanitize=return`` and ``-fsanitize=unreachable``. Some
+   sanitizers (e.g. :doc:`AddressSanitizer`) may not support recovery,
+   and always crash the program after the issue is detected.
+
 .. option:: -fno-assume-sane-operator-new
 
    Don't assume that the C++'s new operator is sane.
@@ -1113,6 +1122,37 @@ are listed below.
    This option restricts the generated code to use general registers
    only. This only applies to the AArch64 architecture.
 
+**-f[no-]max-unknown-pointer-align=[number]**
+   Instruct the code generator to not enforce a higher alignment than the given
+   number (of bytes) when accessing memory via an opaque pointer or reference.
+   This cap is ignored when directly accessing a variable or when the pointee
+   type has an explicit “aligned†attribute.
+
+   The value should usually be determined by the properties of the system allocator.
+   Some builtin types, especially vector types, have very high natural alignments;
+   when working with values of those types, Clang usually wants to use instructions
+   that take advantage of that alignment.  However, many system allocators do
+   not promise to return memory that is more than 8-byte or 16-byte-aligned.  Use
+   this option to limit the alignment that the compiler can assume for an arbitrary
+   pointer, which may point onto the heap.
+
+   This option does not affect the ABI alignment of types; the layout of structs and
+   unions and the value returned by the alignof operator remain the same.
+
+   This option can be overridden on a case-by-case basis by putting an explicit
+   “aligned†alignment on a struct, union, or typedef.  For example:
+
+   .. code-block:: console
+
+      #include 
+      // Make an aligned typedef of the AVX-512 16-int vector type.
+      typedef __v16si __aligned_v16si __attribute__((aligned(64)));
+
+      void initialize_vector(__aligned_v16si *v) {
+        // The compiler may assume that ‘v’ is 64-byte aligned, regardless of the
+        // value of -fmax-unknown-pointer-align.
+      }
+
 
 Profile Guided Optimization
 ---------------------------
@@ -1441,9 +1481,12 @@ Differences between various standard modes
 ------------------------------------------
 
 clang supports the -std option, which changes what language mode clang
-uses. The supported modes for C are c89, gnu89, c94, c99, gnu99 and
-various aliases for those modes. If no -std option is specified, clang
-defaults to gnu99 mode.
+uses. The supported modes for C are c89, gnu89, c94, c99, gnu99, c11,
+gnu11, and various aliases for those modes. If no -std option is
+specified, clang defaults to gnu11 mode. Many C99 and C11 features are
+supported in earlier modes as a conforming extension, with a warning. Use
+``-pedantic-errors`` to request an error if a feature from a later standard
+revision is used in an earlier mode.
 
 Differences between all ``c*`` and ``gnu*`` modes:
 
@@ -1481,6 +1524,11 @@ Differences between ``*89`` and ``*99`` modes:
    in ``*89`` modes.
 -  Some warnings are different.
 
+Differences between ``*99`` and ``*11`` modes:
+
+-  Warnings for use of C11 features are disabled.
+-  ``__STDC_VERSION__`` is defined to ``201112L`` rather than ``199901L``.
+
 c94 mode is identical to c89 mode except that digraphs are enabled in
 c94 mode (FIXME: And ``__STDC_VERSION__`` should be defined!).
 
@@ -1874,6 +1922,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
       /WX                    Treat warnings as errors
       /w                     Disable all warnings
       /Zi                    Enable debug information
+      /Zp                    Set the default maximum struct packing alignment to 1
+      /Zp             Specify the default maximum struct packing alignment
       /Zs                    Syntax-check only
 
     OPTIONS:
diff --git a/docs/conf.py b/docs/conf.py
index 1963a05..7c2ef2a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -48,9 +48,9 @@ copyright = u'2007-2014, The Clang Team'
 # built documents.
 #
 # The short X.Y version.
-version = '3.5'
+version = '3.6'
 # The full version, including alpha/beta/rc tags.
-release = '3.5'
+release = '3.6'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/tools/dump_format_style.py b/docs/tools/dump_format_style.py
index 66bad8b..fdf03c6 100644
--- a/docs/tools/dump_format_style.py
+++ b/docs/tools/dump_format_style.py
@@ -17,6 +17,7 @@ def substitute(text, tag, contents):
   return re.sub(pattern, '%s', text, flags=re.S) % replacement
 
 def doxygen2rst(text):
+  text = re.sub(r'([^/\*])\*', r'\1\\*', text)
   text = re.sub(r'\s*(.*?)\s*<\/tt>', r'``\1``', text)
   text = re.sub(r'\\c ([^ ,;\.]+)', r'``\1``', text)
   text = re.sub(r'\\\w+ ', '', text)
diff --git a/examples/PrintFunctionNames/PrintFunctionNames.cpp b/examples/PrintFunctionNames/PrintFunctionNames.cpp
index 3f18cd4..e8a361d 100644
--- a/examples/PrintFunctionNames/PrintFunctionNames.cpp
+++ b/examples/PrintFunctionNames/PrintFunctionNames.cpp
@@ -36,8 +36,9 @@ public:
 
 class PrintFunctionNamesAction : public PluginASTAction {
 protected:
-  ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef) {
-    return new PrintFunctionsConsumer();
+  std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+                                                 llvm::StringRef) {
+    return llvm::make_unique();
   }
 
   bool ParseArgs(const CompilerInstance &CI,
diff --git a/examples/clang-interpreter/CMakeLists.txt b/examples/clang-interpreter/CMakeLists.txt
index 3c66881..4c6db12 100644
--- a/examples/clang-interpreter/CMakeLists.txt
+++ b/examples/clang-interpreter/CMakeLists.txt
@@ -1,7 +1,8 @@
 set(LLVM_LINK_COMPONENTS
   Core
   ExecutionEngine
-  JIT
+  MC
+  MCJIT
   Support
   native
   )
diff --git a/examples/clang-interpreter/Makefile b/examples/clang-interpreter/Makefile
index d571337..2eff90b 100644
--- a/examples/clang-interpreter/Makefile
+++ b/examples/clang-interpreter/Makefile
@@ -15,12 +15,14 @@ NO_INSTALL = 1
 # No plugins, optimize startup time.
 TOOL_NO_EXPORTS = 1
 
-LINK_COMPONENTS := jit interpreter nativecodegen bitreader bitwriter irreader \
+LINK_COMPONENTS := mcjit interpreter nativecodegen bitreader bitwriter irreader \
 	ipo linker selectiondag asmparser instrumentation objcarcopts option
 USEDLIBS = clangFrontend.a clangSerialization.a clangDriver.a clangCodeGen.a \
            clangParse.a clangSema.a clangStaticAnalyzerFrontend.a \
            clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \
            clangAnalysis.a clangRewrite.a clangRewriteFrontend.a \
-           clangEdit.a clangAST.a clangLex.a clangBasic.a
+           clangEdit.a clangAST.a clangLex.a clangBasic.a LLVMCore.a \
+           LLVMExecutionEngine.a LLVMMC.a LLVMMCJIT.a LLVMRuntimeDyld.a \
+           LLVMObject.a LLVMSupport.a LLVMProfileData.a
 
 include $(CLANG_LEVEL)/Makefile
diff --git a/examples/clang-interpreter/main.cpp b/examples/clang-interpreter/main.cpp
index 8b8ccfd..9b4a257 100644
--- a/examples/clang-interpreter/main.cpp
+++ b/examples/clang-interpreter/main.cpp
@@ -18,7 +18,7 @@
 #include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Host.h"
@@ -42,18 +42,28 @@ std::string GetExecutablePath(const char *Argv0) {
   return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
 }
 
-static int Execute(llvm::Module *Mod, char * const *envp) {
+static llvm::ExecutionEngine *
+createExecutionEngine(std::unique_ptr M, std::string *ErrorStr) {
+  return llvm::EngineBuilder(std::move(M))
+      .setEngineKind(llvm::EngineKind::Either)
+      .setErrorStr(ErrorStr)
+      .create();
+}
+
+static int Execute(std::unique_ptr Mod, char *const *envp) {
   llvm::InitializeNativeTarget();
+  llvm::InitializeNativeTargetAsmPrinter();
 
+  llvm::Module &M = *Mod;
   std::string Error;
   std::unique_ptr EE(
-      llvm::ExecutionEngine::create(Mod, /*ForceInterpreter*/ false, &Error));
+      createExecutionEngine(std::move(Mod), &Error));
   if (!EE) {
     llvm::errs() << "unable to make execution engine: " << Error << "\n";
     return 255;
   }
 
-  llvm::Function *EntryFn = Mod->getFunction("main");
+  llvm::Function *EntryFn = M.getFunction("main");
   if (!EntryFn) {
     llvm::errs() << "'main' function not found in module.\n";
     return 255;
@@ -61,8 +71,9 @@ static int Execute(llvm::Module *Mod, char * const *envp) {
 
   // FIXME: Support passing arguments.
   std::vector Args;
-  Args.push_back(Mod->getModuleIdentifier());
+  Args.push_back(M.getModuleIdentifier());
 
+  EE->finalizeObject();
   return EE->runFunctionAsMain(EntryFn, Args, envp);
 }
 
@@ -75,7 +86,14 @@ int main(int argc, const char **argv, char * const *envp) {
 
   IntrusiveRefCntPtr DiagID(new DiagnosticIDs());
   DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient);
-  Driver TheDriver(Path, llvm::sys::getProcessTriple(), Diags);
+
+  // Use ELF on windows for now.
+  std::string TripleStr = llvm::sys::getProcessTriple();
+  llvm::Triple T(TripleStr);
+  if (T.isOSBinFormatCOFF())
+    T.setObjectFormat(llvm::Triple::ELF);
+
+  Driver TheDriver(Path, T.str(), Diags);
   TheDriver.setTitle("clang interpreter");
   TheDriver.setCheckInputsExist(false);
 
@@ -101,14 +119,14 @@ int main(int argc, const char **argv, char * const *envp) {
     return 1;
   }
 
-  const driver::Command *Cmd = cast(*Jobs.begin());
-  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
+  const driver::Command &Cmd = cast(*Jobs.begin());
+  if (llvm::StringRef(Cmd.getCreator().getName()) != "clang") {
     Diags.Report(diag::err_fe_expected_clang_command);
     return 1;
   }
 
   // Initialize a compiler invocation object from the clang (-cc1) arguments.
-  const driver::ArgStringList &CCArgs = Cmd->getArguments();
+  const driver::ArgStringList &CCArgs = Cmd.getArguments();
   std::unique_ptr CI(new CompilerInvocation);
   CompilerInvocation::CreateFromArgs(*CI,
                                      const_cast(CCArgs.data()),
@@ -146,8 +164,8 @@ int main(int argc, const char **argv, char * const *envp) {
     return 1;
 
   int Res = 255;
-  if (llvm::Module *Module = Act->takeModule())
-    Res = Execute(Module, envp);
+  if (std::unique_ptr Module = Act->takeModule())
+    Res = Execute(std::move(Module), envp);
 
   // Shutdown.
 
diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h
index ed3e8d9..7aa0191 100644
--- a/include/clang-c/BuildSystem.h
+++ b/include/clang-c/BuildSystem.h
@@ -11,8 +11,8 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef CLANG_C_BUILD_SYSTEM_H
-#define CLANG_C_BUILD_SYSTEM_H
+#ifndef LLVM_CLANG_C_BUILDSYSTEM_H
+#define LLVM_CLANG_C_BUILDSYSTEM_H
 
 #include "clang-c/Platform.h"
 #include "clang-c/CXErrorCode.h"
diff --git a/include/clang-c/CXCompilationDatabase.h b/include/clang-c/CXCompilationDatabase.h
index fd65418..068a677 100644
--- a/include/clang-c/CXCompilationDatabase.h
+++ b/include/clang-c/CXCompilationDatabase.h
@@ -12,8 +12,8 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef CLANG_CXCOMPILATIONDATABASE_H
-#define CLANG_CXCOMPILATIONDATABASE_H
+#ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
+#define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H
 
 #include "clang-c/Platform.h"
 #include "clang-c/CXString.h"
diff --git a/include/clang-c/CXErrorCode.h b/include/clang-c/CXErrorCode.h
index a026c95..aff73b7 100644
--- a/include/clang-c/CXErrorCode.h
+++ b/include/clang-c/CXErrorCode.h
@@ -11,8 +11,8 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef CLANG_C_CXERRORCODE_H
-#define CLANG_C_CXERRORCODE_H
+#ifndef LLVM_CLANG_C_CXERRORCODE_H
+#define LLVM_CLANG_C_CXERRORCODE_H
 
 #include "clang-c/Platform.h"
 
diff --git a/include/clang-c/CXString.h b/include/clang-c/CXString.h
index cf198cb..a649cdf 100644
--- a/include/clang-c/CXString.h
+++ b/include/clang-c/CXString.h
@@ -11,8 +11,8 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef CLANG_CXSTRING_H
-#define CLANG_CXSTRING_H
+#ifndef LLVM_CLANG_C_CXSTRING_H
+#define LLVM_CLANG_C_CXSTRING_H
 
 #include "clang-c/Platform.h"
 
diff --git a/include/clang-c/Documentation.h b/include/clang-c/Documentation.h
index ad2da07..89373b1 100644
--- a/include/clang-c/Documentation.h
+++ b/include/clang-c/Documentation.h
@@ -12,8 +12,8 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef CLANG_C_DOCUMENTATION_H
-#define CLANG_C_DOCUMENTATION_H
+#ifndef LLVM_CLANG_C_DOCUMENTATION_H
+#define LLVM_CLANG_C_DOCUMENTATION_H
 
 #include "clang-c/Index.h"
 
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index f69f567..ed7bd16 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -13,8 +13,8 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef CLANG_C_INDEX_H
-#define CLANG_C_INDEX_H
+#ifndef LLVM_CLANG_C_INDEX_H
+#define LLVM_CLANG_C_INDEX_H
 
 #include 
 
@@ -32,7 +32,7 @@
  * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable.
  */
 #define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 27
+#define CINDEX_VERSION_MINOR 29
 
 #define CINDEX_VERSION_ENCODE(major, minor) ( \
       ((major) * 10000)                       \
@@ -336,6 +336,12 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu,
                                     const char *file_name);
 
 /**
+ * \brief Returns non-zero if the \c file1 and \c file2 point to the same file,
+ * or they are both NULL.
+ */
+CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2);
+
+/**
  * @}
  */
 
@@ -2120,7 +2126,7 @@ enum CXCursorKind {
    */
   CXCursor_MSAsmStmt                     = 229,
 
-  /** \brief The null satement ";": C99 6.8.3p3.
+  /** \brief The null statement ";": C99 6.8.3p3.
    *
    * This cursor kind is used to describe the null statement.
    */
@@ -2135,7 +2141,7 @@ enum CXCursorKind {
    */
   CXCursor_OMPParallelDirective          = 232,
 
-  /** \brief OpenMP simd directive.
+  /** \brief OpenMP SIMD directive.
    */
   CXCursor_OMPSimdDirective              = 233,
 
@@ -2195,7 +2201,31 @@ enum CXCursorKind {
    */
   CXCursor_SEHLeaveStmt                  = 247,
 
-  CXCursor_LastStmt                      = CXCursor_SEHLeaveStmt,
+  /** \brief OpenMP ordered directive.
+   */
+  CXCursor_OMPOrderedDirective           = 248,
+
+  /** \brief OpenMP atomic directive.
+   */
+  CXCursor_OMPAtomicDirective            = 249,
+
+  /** \brief OpenMP for SIMD directive.
+   */
+  CXCursor_OMPForSimdDirective           = 250,
+
+  /** \brief OpenMP parallel for SIMD directive.
+   */
+  CXCursor_OMPParallelForSimdDirective   = 251,
+
+  /** \brief OpenMP target directive.
+   */
+  CXCursor_OMPTargetDirective            = 252,
+
+  /** \brief OpenMP teams directive.
+   */
+  CXCursor_OMPTeamsDirective             = 253,
+
+  CXCursor_LastStmt                      = CXCursor_OMPTeamsDirective,
 
   /**
    * \brief Cursor that represents the translation unit itself.
@@ -2228,7 +2258,8 @@ enum CXCursorKind {
   CXCursor_CUDADeviceAttr                = 413,
   CXCursor_CUDAGlobalAttr                = 414,
   CXCursor_CUDAHostAttr                  = 415,
-  CXCursor_LastAttr                      = CXCursor_CUDAHostAttr,
+  CXCursor_CUDASharedAttr                = 416,
+  CXCursor_LastAttr                      = CXCursor_CUDASharedAttr,
 
   /* Preprocessing */
   CXCursor_PreprocessingDirective        = 500,
@@ -2822,6 +2853,7 @@ enum CXCallingConv {
   CXCallingConv_IntelOclBicc = 9,
   CXCallingConv_X86_64Win64 = 10,
   CXCallingConv_X86_64SysV = 11,
+  CXCallingConv_X86VectorCall = 12,
 
   CXCallingConv_Invalid = 100,
   CXCallingConv_Unexposed = 200
@@ -2912,6 +2944,124 @@ CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C);
 CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
 
 /**
+ * \brief Describes the kind of a template argument.
+ *
+ * See the definition of llvm::clang::TemplateArgument::ArgKind for full
+ * element descriptions.
+ */
+enum CXTemplateArgumentKind {
+  CXTemplateArgumentKind_Null,
+  CXTemplateArgumentKind_Type,
+  CXTemplateArgumentKind_Declaration,
+  CXTemplateArgumentKind_NullPtr,
+  CXTemplateArgumentKind_Integral,
+  CXTemplateArgumentKind_Template,
+  CXTemplateArgumentKind_TemplateExpansion,
+  CXTemplateArgumentKind_Expression,
+  CXTemplateArgumentKind_Pack,
+  /* Indicates an error case, preventing the kind from being deduced. */
+  CXTemplateArgumentKind_Invalid
+};
+
+/**
+ *\brief Returns the number of template args of a function decl representing a
+ * template specialization.
+ *
+ * If the argument cursor cannot be converted into a template function
+ * declaration, -1 is returned.
+ *
+ * For example, for the following declaration and specialization:
+ *   template 
+ *   void foo() { ... }
+ *
+ *   template <>
+ *   void foo();
+ *
+ * The value 3 would be returned from this call.
+ */
+CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C);
+
+/**
+ * \brief Retrieve the kind of the I'th template argument of the CXCursor C.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl, an invalid
+ * template argument kind is returned.
+ *
+ * For example, for the following declaration and specialization:
+ *   template 
+ *   void foo() { ... }
+ *
+ *   template <>
+ *   void foo();
+ *
+ * For I = 0, 1, and 2, Type, Integral, and Integral will be returned,
+ * respectively.
+ */
+CINDEX_LINKAGE enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind(
+    CXCursor C, unsigned I);
+
+/**
+ * \brief Retrieve a CXType representing the type of a TemplateArgument of a
+ *  function decl representing a template specialization.
+ *
+ * If the argument CXCursor does not represent a FunctionDecl whose I'th
+ * template argument has a kind of CXTemplateArgKind_Integral, an invalid type
+ * is returned.
+ *
+ * For example, for the following declaration and specialization:
+ *   template 
+ *   void foo() { ... }
+ *
+ *   template <>
+ *   void foo();
+ *
+ * If called with I = 0, "float", will be returned.
+ * Invalid types will be returned for I == 1 or 2.
+ */
+CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C,
+                                                           unsigned I);
+
+/**
+ * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ *  decl representing a template specialization) as a signed long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl or whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ *   template 
+ *   void foo() { ... }
+ *
+ *   template <>
+ *   void foo();
+ *
+ * If called with I = 1 or 2, -7 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C,
+                                                               unsigned I);
+
+/**
+ * \brief Retrieve the value of an Integral TemplateArgument (of a function
+ *  decl representing a template specialization) as an unsigned long long.
+ *
+ * It is undefined to call this function on a CXCursor that does not represent a
+ * FunctionDecl or whose I'th template argument is not an integral value.
+ *
+ * For example, for the following declaration and specialization:
+ *   template 
+ *   void foo() { ... }
+ *
+ *   template <>
+ *   void foo();
+ *
+ * If called with I = 1 or 2, 2147483649 or true will be returned, respectively.
+ * For I == 0, this function's behavior is undefined.
+ */
+CINDEX_LINKAGE unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue(
+    CXCursor C, unsigned I);
+
+/**
  * \brief Determine whether two CXTypes represent the same type.
  *
  * \returns non-zero if the CXTypes represent the same type and
@@ -3194,6 +3344,29 @@ enum CX_CXXAccessSpecifier {
 CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
 
 /**
+ * \brief Represents the storage classes as declared in the source. CX_SC_Invalid
+ * was added for the case that the passed cursor in not a declaration.
+ */
+enum CX_StorageClass {
+  CX_SC_Invalid,
+  CX_SC_None,
+  CX_SC_Extern,
+  CX_SC_Static,
+  CX_SC_PrivateExtern,
+  CX_SC_OpenCLWorkGroupLocal,
+  CX_SC_Auto,
+  CX_SC_Register
+};
+
+/**
+ * \brief Returns the storage class for a function or variable declaration.
+ *
+ * If the passed in Cursor is not a function or variable declaration,
+ * CX_SC_Invalid is returned else the storage class.
+ */
+CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor);
+
+/**
  * \brief Determine the number of overloaded declarations referenced by a 
  * \c CXCursor_OverloadedDeclRef cursor.
  *
@@ -3631,6 +3804,20 @@ CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C);
  * @}
  */
 
+/** \defgroup CINDEX_MANGLE Name Mangling API Functions
+ *
+ * @{
+ */
+
+/**
+ * \brief Retrieve the CXString representing the mangled name of the cursor.
+ */
+CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor);
+
+/**
+ * @}
+ */
+
 /**
  * \defgroup CINDEX_MODULE Module introspection
  *
diff --git a/include/clang-c/Platform.h b/include/clang-c/Platform.h
index 0f866c6..e2a4dcc 100644
--- a/include/clang-c/Platform.h
+++ b/include/clang-c/Platform.h
@@ -11,8 +11,8 @@
 |*                                                                            *|
 \*===----------------------------------------------------------------------===*/
 
-#ifndef CLANG_C_PLATFORM_H
-#define CLANG_C_PLATFORM_H
+#ifndef LLVM_CLANG_C_PLATFORM_H
+#define LLVM_CLANG_C_PLATFORM_H
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h
index b3e74b9..c830aa3 100644
--- a/include/clang/ARCMigrate/ARCMTActions.h
+++ b/include/clang/ARCMigrate/ARCMTActions.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
-#define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H
+#ifndef LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H
+#define LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H
 
 #include "clang/ARCMigrate/FileRemapper.h"
 #include "clang/Frontend/FrontendAction.h"
@@ -37,8 +37,8 @@ class MigrateSourceAction : public ASTFrontendAction {
   FileRemapper Remapper;
 protected:
   bool BeginInvocation(CompilerInstance &CI) override;
-  ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
-                                 StringRef InFile) override;
+  std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
 };
 
 class MigrateAction : public WrapperFrontendAction {
@@ -65,8 +65,8 @@ public:
                     unsigned migrateAction);
 
 protected:
-  ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
-                                 StringRef InFile) override;
+  std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+                                                 StringRef InFile) override;
   bool BeginInvocation(CompilerInstance &CI) override;
 };
 
diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h
index e094301..53b88e9 100644
--- a/include/clang/ARCMigrate/FileRemapper.h
+++ b/include/clang/ARCMigrate/FileRemapper.h
@@ -52,14 +52,14 @@ public:
   bool overwriteOriginal(DiagnosticsEngine &Diag,
                          StringRef outputDir = StringRef());
 
-  void remap(StringRef filePath, llvm::MemoryBuffer *memBuf);
+  void remap(StringRef filePath, std::unique_ptr memBuf);
 
   void applyMappings(PreprocessorOptions &PPOpts) const;
 
   void clear(StringRef outputDir = StringRef());
 
 private:
-  void remap(const FileEntry *file, llvm::MemoryBuffer *memBuf);
+  void remap(const FileEntry *file, std::unique_ptr memBuf);
   void remap(const FileEntry *file, const FileEntry *newfile);
 
   const FileEntry *getOriginalFile(StringRef filePath);
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 8134f6b..195d748 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -30,6 +30,7 @@
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/Basic/PartialDiagnostic.h"
+#include "clang/Basic/SanitizerBlacklist.h"
 #include "clang/Basic/VersionTuple.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -74,6 +75,15 @@ namespace clang {
     class FullComment;
   }
 
+  struct TypeInfo {
+    uint64_t Width;
+    unsigned Align;
+    bool AlignIsRequired : 1;
+    TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {}
+    TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired)
+        : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {}
+  };
+
 /// \brief Holds long-lived AST nodes (such as types and decls) that can be
 /// referred to throughout the semantic analysis of a file.
 class ASTContext : public RefCountedBase {
@@ -144,8 +154,7 @@ class ASTContext : public RefCountedBase {
     ObjCLayouts;
 
   /// \brief A cache from types to size and alignment information.
-  typedef llvm::DenseMap > TypeInfoMap;
+  typedef llvm::DenseMap TypeInfoMap;
   mutable TypeInfoMap MemoizedTypeInfo;
 
   /// \brief A cache mapping from CXXRecordDecls to key functions.
@@ -264,8 +273,6 @@ class ASTContext : public RefCountedBase {
   /// \brief Declaration for the CUDA cudaConfigureCall function.
   FunctionDecl *cudaConfigureCallDecl;
 
-  TypeSourceInfo NullTypeSourceInfo;
-
   /// \brief Keeps track of all declaration attributes.
   ///
   /// Since so few decls have attrs, we keep them in a hash map instead of
@@ -384,6 +391,10 @@ private:
   ///  this ASTContext object.
   LangOptions &LangOpts;
 
+  /// \brief Blacklist object that is used by sanitizers to decide which
+  /// entities should not be instrumented.
+  std::unique_ptr SanitizerBL;
+
   /// \brief The allocator used to create AST objects.
   ///
   /// AST objects are never destructed; rather, all memory associated with the
@@ -453,11 +464,12 @@ public:
   /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc,
   /// NestedNameSpecifier or NestedNameSpecifierLoc.
   template 
-  ParentVector getParents(const NodeT &Node) {
+  ArrayRef getParents(const NodeT &Node) {
     return getParents(ast_type_traits::DynTypedNode::create(Node));
   }
 
-  ParentVector getParents(const ast_type_traits::DynTypedNode &Node);
+  ArrayRef
+  getParents(const ast_type_traits::DynTypedNode &Node);
 
   const clang::PrintingPolicy &getPrintingPolicy() const {
     return PrintingPolicy;
@@ -508,6 +520,10 @@ public:
   
   const LangOptions& getLangOpts() const { return LangOpts; }
 
+  const SanitizerBlacklist &getSanitizerBlacklist() const {
+    return *SanitizerBL;
+  }
+
   DiagnosticsEngine &getDiagnostics() const;
 
   FullSourceLoc getFullLoc(SourceLocation Loc) const {
@@ -912,6 +928,12 @@ public:
   /// \brief Change the result type of a function type once it is deduced.
   void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType);
 
+  /// \brief Change the exception specification on a function once it is
+  /// delay-parsed, instantiated, or computed.
+  void adjustExceptionSpec(FunctionDecl *FD,
+                           const FunctionProtoType::ExceptionSpecInfo &ESI,
+                           bool AsWritten = false);
+
   /// \brief Return the uniqued reference to the type for a complex
   /// number with the specified element type.
   QualType getComplexType(QualType T) const;
@@ -1371,7 +1393,8 @@ public:
   ///
   /// If \p Field is specified then record field names are also encoded.
   void getObjCEncodingForType(QualType T, std::string &S,
-                              const FieldDecl *Field=nullptr) const;
+                              const FieldDecl *Field=nullptr,
+                              QualType *NotEncodedT=nullptr) const;
 
   /// \brief Emit the Objective-C property type encoding for the given
   /// type \p T into \p S.
@@ -1581,7 +1604,7 @@ public:
 
 private:
   CanQualType getFromTargetType(unsigned Type) const;
-  std::pair getTypeInfoImpl(const Type *T) const;
+  TypeInfo getTypeInfoImpl(const Type *T) const;
 
   //===--------------------------------------------------------------------===//
   //                         Type Predicates.
@@ -1614,18 +1637,12 @@ public:
   const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const;
 
   /// \brief Get the size and alignment of the specified complete type in bits.
-  std::pair getTypeInfo(const Type *T) const;
-  std::pair getTypeInfo(QualType T) const {
-    return getTypeInfo(T.getTypePtr());
-  }
+  TypeInfo getTypeInfo(const Type *T) const;
+  TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); }
 
   /// \brief Return the size of the specified (complete) type \p T, in bits.
-  uint64_t getTypeSize(QualType T) const {
-    return getTypeInfo(T).first;
-  }
-  uint64_t getTypeSize(const Type *T) const {
-    return getTypeInfo(T).first;
-  }
+  uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; }
+  uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; }
 
   /// \brief Return the size of the character type, in bits.
   uint64_t getCharWidth() const {
@@ -1645,12 +1662,8 @@ public:
 
   /// \brief Return the ABI-specified alignment of a (complete) type \p T, in
   /// bits.
-  unsigned getTypeAlign(QualType T) const {
-    return getTypeInfo(T).second;
-  }
-  unsigned getTypeAlign(const Type *T) const {
-    return getTypeInfo(T).second;
-  }
+  unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; }
+  unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; }
 
   /// \brief Return the ABI-specified alignment of a (complete) type \p T, in 
   /// characters.
@@ -1664,6 +1677,11 @@ public:
   std::pair getTypeInfoInChars(const Type *T) const;
   std::pair getTypeInfoInChars(QualType T) const;
 
+  /// \brief Determine if the alignment the type has was required using an
+  /// alignment attribute.
+  bool isAlignmentRequired(const Type *T) const;
+  bool isAlignmentRequired(QualType T) const;
+
   /// \brief Return the "preferred" alignment of the specified type \p T for
   /// the current target, in bits.
   ///
@@ -2153,8 +2171,6 @@ public:
   getTrivialTypeSourceInfo(QualType T, 
                            SourceLocation Loc = SourceLocation()) const;
 
-  TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; }
-
   /// \brief Add a deallocation callback that will be invoked when the 
   /// ASTContext is destroyed.
   ///
@@ -2272,12 +2288,14 @@ private:
                                   bool StructField = false,
                                   bool EncodeBlockParameters = false,
                                   bool EncodeClassNames = false,
-                                  bool EncodePointerToObjCTypedef = false) const;
+                                  bool EncodePointerToObjCTypedef = false,
+                                  QualType *NotEncodedT=nullptr) const;
 
   // Adds the encoding of the structure's members.
   void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S,
                                        const FieldDecl *Field,
-                                       bool includeVBases = true) const;
+                                       bool includeVBases = true,
+                                       QualType *NotEncodedT=nullptr) const;
 public:
   // Adds the encoding of a method parameter or return type.
   void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT,
@@ -2312,6 +2330,31 @@ private:
   std::unique_ptr AllParents;
 
   std::unique_ptr VTContext;
+
+public:
+  enum PragmaSectionFlag : unsigned {
+    PSF_None = 0,
+    PSF_Read = 0x1,
+    PSF_Write = 0x2,
+    PSF_Execute = 0x4,
+    PSF_Implicit = 0x8,
+    PSF_Invalid = 0x80000000U,
+  };
+
+  struct SectionInfo {
+    DeclaratorDecl *Decl;
+    SourceLocation PragmaSectionLocation;
+    int SectionFlags;
+    SectionInfo() {}
+    SectionInfo(DeclaratorDecl *Decl,
+                SourceLocation PragmaSectionLocation,
+                int SectionFlags)
+      : Decl(Decl),
+        PragmaSectionLocation(PragmaSectionLocation),
+        SectionFlags(SectionFlags) {}
+  };
+
+  llvm::StringMap SectionInfos;
 };
 
 /// \brief Utility function for constructing a nullary selector.
@@ -2349,9 +2392,9 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) {
 /// // Specific alignment
 /// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments);
 /// @endcode
-/// Please note that you cannot use delete on the pointer; it must be
-/// deallocated using an explicit destructor call followed by
-/// @c Context.Deallocate(Ptr).
+/// Memory allocated through this placement new operator does not need to be
+/// explicitly freed, as ASTContext will free all of this memory when it gets
+/// destroyed. Please note that you cannot use delete on the pointer.
 ///
 /// @param Bytes The number of bytes to allocate. Calculated by the compiler.
 /// @param C The ASTContext that provides the allocator.
@@ -2386,9 +2429,9 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) {
 /// // Specific alignment
 /// char *data = new (Context, 4) char[10];
 /// @endcode
-/// Please note that you cannot use delete on the pointer; it must be
-/// deallocated using an explicit destructor call followed by
-/// @c Context.Deallocate(Ptr).
+/// Memory allocated through this placement new[] operator does not need to be
+/// explicitly freed, as ASTContext will free all of this memory when it gets
+/// destroyed. Please note that you cannot use delete on the pointer.
 ///
 /// @param Bytes The number of bytes to allocate. Calculated by the compiler.
 /// @param C The ASTContext that provides the allocator.
diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h
index 484ca4c..27c85e6 100644
--- a/include/clang/AST/ASTDiagnostic.h
+++ b/include/clang/AST/ASTDiagnostic.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_DIAGNOSTICAST_H
-#define LLVM_CLANG_DIAGNOSTICAST_H
+#ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H
 
 #include "clang/Basic/Diagnostic.h"
 
diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h
index 4f32798..003d489 100644
--- a/include/clang/AST/ASTFwd.h
+++ b/include/clang/AST/ASTFwd.h
@@ -12,6 +12,9 @@
 ///
 //===-------------------------------------------------------------===//
 
+#ifndef LLVM_CLANG_AST_ASTFWD_H
+#define LLVM_CLANG_AST_ASTFWD_H
+
 namespace clang {
 
 class Decl;
@@ -26,3 +29,5 @@ class Type;
 class CXXCtorInitializer;
 
 } // end namespace clang
+
+#endif
diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h
index 9af016b..69df2d8 100644
--- a/include/clang/AST/ASTLambda.h
+++ b/include/clang/AST/ASTLambda.h
@@ -13,8 +13,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_LAMBDA_H
-#define LLVM_CLANG_AST_LAMBDA_H
+#ifndef LLVM_CLANG_AST_ASTLAMBDA_H
+#define LLVM_CLANG_AST_ASTLAMBDA_H
 
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/DeclTemplate.h"
@@ -77,4 +77,4 @@ inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {
 
 } // clang
 
-#endif // LLVM_CLANG_AST_LAMBDA_H
+#endif
diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h
index a89bfed..48eb629 100644
--- a/include/clang/AST/ASTMutationListener.h
+++ b/include/clang/AST/ASTMutationListener.h
@@ -102,6 +102,12 @@ public:
   /// \param D the declaration marked used
   virtual void DeclarationMarkedUsed(const Decl *D) {}
 
+  /// \brief A declaration is marked as OpenMP threadprivate which was not
+  /// previously marked as threadprivate.
+  ///
+  /// \param D the declaration marked OpenMP threadprivate.
+  virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {}
+
   // NOTE: If new methods are added they should also be added to
   // MultiplexASTMutationListener.
 };
diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h
index 0e06e26..dc3c34f 100644
--- a/include/clang/AST/ASTTypeTraits.h
+++ b/include/clang/AST/ASTTypeTraits.h
@@ -13,8 +13,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H
-#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H
+#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H
+#define LLVM_CLANG_AST_ASTTYPETRAITS_H
 
 #include "clang/AST/ASTFwd.h"
 #include "clang/AST/Decl.h"
@@ -23,6 +23,7 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/LLVM.h"
+#include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/Support/AlignOf.h"
 
 namespace llvm {
@@ -53,9 +54,19 @@ public:
     return ASTNodeKind(KindToKindId::Id);
   }
 
+  /// \{
+  /// \brief Construct an identifier for the dynamic type of the node
+  static ASTNodeKind getFromNode(const Decl &D);
+  static ASTNodeKind getFromNode(const Stmt &S);
+  static ASTNodeKind getFromNode(const Type &T);
+  /// \}
+
   /// \brief Returns \c true if \c this and \c Other represent the same kind.
   bool isSame(ASTNodeKind Other) const;
 
+  /// \brief Returns \c true only for the default \c ASTNodeKind()
+  bool isNone() const { return KindId == NKI_None; }
+
   /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
   /// \param Distance If non-null, used to return the distance between \c this
   /// and \c Other in the class hierarchy.
@@ -69,6 +80,32 @@ public:
     return KindId < Other.KindId;
   }
 
+  /// \brief Return the most derived type between \p Kind1 and \p Kind2.
+  ///
+  /// Return ASTNodeKind() if they are not related.
+  static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
+
+  /// \brief Return the most derived common ancestor between Kind1 and Kind2.
+  ///
+  /// Return ASTNodeKind() if they are not related.
+  static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
+                                                  ASTNodeKind Kind2);
+
+  /// \brief Hooks for using ASTNodeKind as a key in a DenseMap.
+  struct DenseMapInfo {
+    // ASTNodeKind() is a good empty key because it is represented as a 0.
+    static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
+    // NKI_NumberOfKinds is not a valid value, so it is good for a
+    // tombstone key.
+    static inline ASTNodeKind getTombstoneKey() {
+      return ASTNodeKind(NKI_NumberOfKinds);
+    }
+    static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; }
+    static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) {
+      return LHS.KindId == RHS.KindId;
+    }
+  };
+
 private:
   /// \brief Kind ids.
   ///
@@ -108,6 +145,8 @@ private:
   template  struct KindToKindId {
     static const NodeKindId Id = NKI_None;
   };
+  template 
+  struct KindToKindId : KindToKindId {};
 
   /// \brief Per kind info.
   struct KindInfo {
@@ -184,12 +223,22 @@ public:
     return BaseConverter::get(NodeKind, Storage.buffer);
   }
 
+  /// \brief Retrieve the stored node as type \c T.
+  ///
+  /// Similar to \c get(), but asserts that the type is what we are expecting.
+  template 
+  const T &getUnchecked() const {
+    return BaseConverter::getUnchecked(NodeKind, Storage.buffer);
+  }
+
+  ASTNodeKind getNodeKind() const { return NodeKind; }
+
   /// \brief Returns a pointer that identifies the stored AST node.
   ///
   /// Note that this is not supported by all AST nodes. For AST nodes
   /// that don't have a pointer-defined identity inside the AST, this
   /// method returns NULL.
-  const void *getMemoizationData() const;
+  const void *getMemoizationData() const { return MemoizationData; }
 
   /// \brief Prints the node to the given output stream.
   void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
@@ -212,14 +261,15 @@ public:
     return getMemoizationData() < Other.getMemoizationData();
   }
   bool operator==(const DynTypedNode &Other) const {
-    if (!NodeKind.isBaseOf(Other.NodeKind) &&
-        !Other.NodeKind.isBaseOf(NodeKind))
+    // DynTypedNode::create() stores the exact kind of the node in NodeKind.
+    // If they contain the same node, their NodeKind must be the same.
+    if (!NodeKind.isSame(Other.NodeKind))
       return false;
 
     // FIXME: Implement for other types.
-    if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
-      return *get() == *Other.get();
-    }
+    if (ASTNodeKind::getFromNodeKind().isSame(NodeKind))
+      return getUnchecked() == Other.getUnchecked();
+
     assert(getMemoizationData() && Other.getMemoizationData());
     return getMemoizationData() == Other.getMemoizationData();
   }
@@ -235,13 +285,18 @@ private:
   /// \brief Converter that uses dyn_cast from a stored BaseT*.
   template  struct DynCastPtrConverter {
     static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
-      if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
-        return dyn_cast(*reinterpret_cast(Storage));
+      if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind))
+        return cast(*reinterpret_cast(Storage));
       return nullptr;
     }
+    static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+      assert(ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind));
+      return *cast(*reinterpret_cast(Storage));
+    }
     static DynTypedNode create(const BaseT &Node) {
       DynTypedNode Result;
-      Result.NodeKind = ASTNodeKind::getFromNodeKind();
+      Result.NodeKind = ASTNodeKind::getFromNode(Node);
+      Result.MemoizationData = &Node;
       new (Result.Storage.buffer) const BaseT * (&Node);
       return Result;
     }
@@ -254,9 +309,14 @@ private:
         return *reinterpret_cast(Storage);
       return nullptr;
     }
+    static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+      assert(ASTNodeKind::getFromNodeKind().isSame(NodeKind));
+      return **reinterpret_cast(Storage);
+    }
     static DynTypedNode create(const T &Node) {
       DynTypedNode Result;
       Result.NodeKind = ASTNodeKind::getFromNodeKind();
+      Result.MemoizationData = &Node;
       new (Result.Storage.buffer) const T * (&Node);
       return Result;
     }
@@ -269,15 +329,21 @@ private:
         return reinterpret_cast(Storage);
       return nullptr;
     }
+    static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
+      assert(ASTNodeKind::getFromNodeKind().isSame(NodeKind));
+      return *reinterpret_cast(Storage);
+    }
     static DynTypedNode create(const T &Node) {
       DynTypedNode Result;
       Result.NodeKind = ASTNodeKind::getFromNodeKind();
+      Result.MemoizationData = nullptr;
       new (Result.Storage.buffer) T(Node);
       return Result;
     }
   };
 
   ASTNodeKind NodeKind;
+  const void *MemoizationData;
 
   /// \brief Stores the data of the node.
   ///
@@ -345,20 +411,15 @@ template  struct DynTypedNode::BaseConverter {
   }
 };
 
-inline const void *DynTypedNode::getMemoizationData() const {
-  if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
-    return BaseConverter::get(NodeKind, Storage.buffer);
-  } else if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
-    return BaseConverter::get(NodeKind, Storage.buffer);
-  } else if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
-    return BaseConverter::get(NodeKind, Storage.buffer);
-  } else if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) {
-    return BaseConverter::get(NodeKind, Storage.buffer);
-  }
-  return nullptr;
-}
-
 } // end namespace ast_type_traits
 } // end namespace clang
 
-#endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H
+namespace llvm {
+
+template <>
+struct DenseMapInfo
+    : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
+
+}  // end namespace llvm
+
+#endif
diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h
index d92167e..6ec0545 100644
--- a/include/clang/AST/ASTVector.h
+++ b/include/clang/AST/ASTVector.h
@@ -15,8 +15,8 @@
 // FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h.
 // We can refactor this core logic into something common.
 
-#ifndef LLVM_CLANG_AST_VECTOR
-#define LLVM_CLANG_AST_VECTOR
+#ifndef LLVM_CLANG_AST_ASTVECTOR_H
+#define LLVM_CLANG_AST_ASTVECTOR_H
 
 #include "clang/AST/AttrIterator.h"
 #include "llvm/ADT/PointerIntPair.h"
@@ -236,14 +236,14 @@ public:
 
   iterator insert(const ASTContext &C, iterator I, size_type NumToInsert,
                   const T &Elt) {
-    if (I == this->end()) {  // Important special case for empty vector.
-      append(C, NumToInsert, Elt);
-      return this->end()-1;
-    }
-
     // Convert iterator to elt# to avoid invalidating iterator when we reserve()
     size_t InsertElt = I - this->begin();
 
+    if (I == this->end()) { // Important special case for empty vector.
+      append(C, NumToInsert, Elt);
+      return this->begin() + InsertElt;
+    }
+
     // Ensure there is enough space.
     reserve(C, static_cast(this->size() + NumToInsert));
 
@@ -284,14 +284,15 @@ public:
 
   template
   iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) {
-    if (I == this->end()) {  // Important special case for empty vector.
+    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
+    size_t InsertElt = I - this->begin();
+
+    if (I == this->end()) { // Important special case for empty vector.
       append(C, From, To);
-      return this->end()-1;
+      return this->begin() + InsertElt;
     }
 
     size_t NumToInsert = std::distance(From, To);
-    // Convert iterator to elt# to avoid invalidating iterator when we reserve()
-    size_t InsertElt = I - this->begin();
 
     // Ensure there is enough space.
     reserve(C, static_cast(this->size() + NumToInsert));
diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h
index fc48816..787843e 100644
--- a/include/clang/AST/Attr.h
+++ b/include/clang/AST/Attr.h
@@ -16,6 +16,7 @@
 
 #include "clang/AST/AttrIterator.h"
 #include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/AttrKinds.h"
 #include "clang/Basic/LLVM.h"
diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h
index 7cccef6..aa3c846 100644
--- a/include/clang/AST/CanonicalType.h
+++ b/include/clang/AST/CanonicalType.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H
-#define LLVM_CLANG_AST_CANONICAL_TYPE_H
+#ifndef LLVM_CLANG_AST_CANONICALTYPE_H
+#define LLVM_CLANG_AST_CANONICALTYPE_H
 
 #include "clang/AST/Type.h"
 #include "llvm/Support/Casting.h"
@@ -736,4 +736,4 @@ CanTypeIterator::operator->() const {
 }
 
 
-#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H
+#endif
diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h
index e18fe9a..94470cb 100644
--- a/include/clang/AST/Comment.h
+++ b/include/clang/AST/Comment.h
@@ -96,9 +96,10 @@ protected:
     unsigned : NumInlineContentCommentBits;
 
     unsigned RenderKind : 2;
-    unsigned CommandID : 8;
+    unsigned CommandID : CommandInfo::NumCommandIDBits;
   };
-  enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 };
+  enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + 
+                                       CommandInfo::NumCommandIDBits };
 
   class HTMLTagCommentBitfields {
     friend class HTMLTagComment;
@@ -139,13 +140,14 @@ protected:
 
     unsigned : NumCommentBits;
 
-    unsigned CommandID : 8;
+    unsigned CommandID : CommandInfo::NumCommandIDBits;
 
     /// Describes the syntax that was used in a documentation command.
     /// Contains values from CommandMarkerKind enum.
     unsigned CommandMarker : 1;
   };
-  enum { NumBlockCommandCommentBits = NumCommentBits + 9 };
+  enum { NumBlockCommandCommentBits = NumCommentBits + 
+                                      CommandInfo::NumCommandIDBits + 1 };
 
   class ParamCommandCommentBitfields {
     friend class ParamCommandComment;
diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h
index 5d50886..be5b8ee 100644
--- a/include/clang/AST/CommentBriefParser.h
+++ b/include/clang/AST/CommentBriefParser.h
@@ -12,8 +12,8 @@
 //===----------------------------------------------------------------------===//
 
 
-#ifndef LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
-#define LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H
+#ifndef LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
+#define LLVM_CLANG_AST_COMMENTBRIEFPARSER_H
 
 #include "clang/AST/CommentLexer.h"
 
diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h
index dde7a14..ec6d83c 100644
--- a/include/clang/AST/CommentCommandTraits.h
+++ b/include/clang/AST/CommentCommandTraits.h
@@ -13,8 +13,8 @@
 //===----------------------------------------------------------------------===//
 
 
-#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
-#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H
+#ifndef LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
+#define LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H
 
 #include "clang/Basic/CommentOptions.h"
 #include "clang/Basic/LLVM.h"
@@ -40,7 +40,11 @@ struct CommandInfo {
   /// Name of the command that ends the verbatim block.
   const char *EndCommandName;
 
-  unsigned ID : 8;
+  /// DRY definition of the number of bits used for a command ID.
+  enum { NumCommandIDBits = 20 };
+
+  /// The ID of the command.
+  unsigned ID : NumCommandIDBits;
 
   /// Number of word-like arguments for a given block command, except for
   /// \\param and \\tparam commands -- these have special argument parsers.
diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h
index 312da06..f3a209b 100644
--- a/include/clang/AST/CommentDiagnostic.h
+++ b/include/clang/AST/CommentDiagnostic.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H
-#define LLVM_CLANG_COMMENTDIAGNOSTIC_H
+#ifndef LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H
 
 #include "clang/Basic/Diagnostic.h"
 
diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h
index a6e3ed8..d995df9 100644
--- a/include/clang/AST/CommentLexer.h
+++ b/include/clang/AST/CommentLexer.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H
-#define LLVM_CLANG_AST_COMMENT_LEXER_H
+#ifndef LLVM_CLANG_AST_COMMENTLEXER_H
+#define LLVM_CLANG_AST_COMMENTLEXER_H
 
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h
index 7e00813..2c444f0 100644
--- a/include/clang/AST/CommentParser.h
+++ b/include/clang/AST/CommentParser.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_COMMENT_PARSER_H
-#define LLVM_CLANG_AST_COMMENT_PARSER_H
+#ifndef LLVM_CLANG_AST_COMMENTPARSER_H
+#define LLVM_CLANG_AST_COMMENTPARSER_H
 
 #include "clang/AST/Comment.h"
 #include "clang/AST/CommentLexer.h"
diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h
index 027c3b9..4ae6fe0 100644
--- a/include/clang/AST/CommentSema.h
+++ b/include/clang/AST/CommentSema.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_COMMENT_SEMA_H
-#define LLVM_CLANG_AST_COMMENT_SEMA_H
+#ifndef LLVM_CLANG_AST_COMMENTSEMA_H
+#define LLVM_CLANG_AST_COMMENTSEMA_H
 
 #include "clang/AST/Comment.h"
 #include "clang/Basic/Diagnostic.h"
@@ -85,7 +85,7 @@ public:
       std::uninitialized_copy(Source.begin(), Source.end(), Mem);
       return llvm::makeArrayRef(Mem, Size);
     }
-    return ArrayRef();
+    return None;
   }
 
   ParagraphComment *actOnParagraphComment(
diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h
index 9ef0087..c0526e1 100644
--- a/include/clang/AST/DataRecursiveASTVisitor.h
+++ b/include/clang/AST/DataRecursiveASTVisitor.h
@@ -424,6 +424,7 @@ private:
   bool TraverseFunctionHelper(FunctionDecl *D);
   bool TraverseVarHelper(VarDecl *D);
   bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
+  bool TraverseOMPLoopDirective(OMPLoopDirective *S);
   bool TraverseOMPClause(OMPClause *C);
 #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
 #include "clang/Basic/OpenMPKinds.def"
@@ -623,6 +624,7 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifier(
   case NestedNameSpecifier::Namespace:
   case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Super:
     return true;
 
   case NestedNameSpecifier::TypeSpec:
@@ -647,6 +649,7 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
   case NestedNameSpecifier::Namespace:
   case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Super:
     return true;
 
   case NestedNameSpecifier::TypeSpec:
@@ -875,6 +878,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
+
+  if (Expr *NE = T->getNoexceptExpr())
+    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
@@ -1083,6 +1089,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
+
+  if (Expr *NE = T->getNoexceptExpr())
+    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
@@ -2122,21 +2131,29 @@ bool RecursiveASTVisitor::TraverseLambdaExpr(LambdaExpr *S) {
     TRY_TO(TraverseLambdaCapture(S, C));
   }
 
-  if (S->hasExplicitParameters() || S->hasExplicitResultType()) {
-    TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
-    if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
-      // Visit the whole type.
-      TRY_TO(TraverseTypeLoc(TL));
-    } else if (FunctionProtoTypeLoc Proto = TL.getAs()) {
-      if (S->hasExplicitParameters()) {
-        // Visit parameters.
-        for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
-          TRY_TO(TraverseDecl(Proto.getParam(I)));
-        }
-      } else {
-        TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+  TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+  FunctionProtoTypeLoc Proto = TL.castAs();
+
+  if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+    // Visit the whole type.
+    TRY_TO(TraverseTypeLoc(TL));
+  } else {
+    if (S->hasExplicitParameters()) {
+      // Visit parameters.
+      for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+        TRY_TO(TraverseDecl(Proto.getParam(I)));
       }
+    } else if (S->hasExplicitResultType()) {
+      TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+    }
+
+    auto *T = Proto.getTypePtr();
+    for (const auto &E : T->exceptions()) {
+      TRY_TO(TraverseType(E));
     }
+
+    if (Expr *NE = T->getNoexceptExpr())
+      TRY_TO(TraverseStmt(NE));
   }
 
   TRY_TO(TraverseLambdaBody(S));
@@ -2237,6 +2254,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
 
 DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
 DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
+DEF_TRAVERSE_STMT(TypoExpr, {})
 DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
 
 // These operators (all of them) do not need any action except
@@ -2253,6 +2271,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
 DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
 DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
 DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
+DEF_TRAVERSE_STMT(CXXFoldExpr, {})
 DEF_TRAVERSE_STMT(AtomicExpr, {})
 
 // These literals (all of them) do not need any action.
@@ -2279,6 +2298,12 @@ bool RecursiveASTVisitor::TraverseOMPExecutableDirective(
   return true;
 }
 
+template 
+bool
+RecursiveASTVisitor::TraverseOMPLoopDirective(OMPLoopDirective *S) {
+  return TraverseOMPExecutableDirective(S);
+}
+
 DEF_TRAVERSE_STMT(OMPParallelDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
@@ -2288,6 +2313,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective,
 DEF_TRAVERSE_STMT(OMPForDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPForSimdDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 DEF_TRAVERSE_STMT(OMPSectionsDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
@@ -2308,6 +2336,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, {
 DEF_TRAVERSE_STMT(OMPParallelForDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
@@ -2326,6 +2357,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
 DEF_TRAVERSE_STMT(OMPFlushDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPOrderedDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPAtomicDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 // OpenMP clauses.
 template 
 bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) {
@@ -2415,6 +2458,31 @@ RecursiveASTVisitor::VisitOMPMergeableClause(OMPMergeableClause *) {
 }
 
 template 
+bool RecursiveASTVisitor::VisitOMPReadClause(OMPReadClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPWriteClause(OMPWriteClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPUpdateClause(OMPUpdateClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPCaptureClause(OMPCaptureClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+  return true;
+}
+
+template 
 template 
 bool RecursiveASTVisitor::VisitOMPClauseList(T *Node) {
   for (auto *E : Node->varlists()) {
@@ -2426,6 +2494,9 @@ bool RecursiveASTVisitor::VisitOMPClauseList(T *Node) {
 template 
 bool RecursiveASTVisitor::VisitOMPPrivateClause(OMPPrivateClause *C) {
   TRY_TO(VisitOMPClauseList(C));
+  for (auto *E : C->private_copies()) {
+    TRY_TO(TraverseStmt(E));
+  }
   return true;
 }
 
@@ -2433,6 +2504,12 @@ template 
 bool RecursiveASTVisitor::VisitOMPFirstprivateClause(
     OMPFirstprivateClause *C) {
   TRY_TO(VisitOMPClauseList(C));
+  for (auto *E : C->private_copies()) {
+    TRY_TO(TraverseStmt(E));
+  }
+  for (auto *E : C->inits()) {
+    TRY_TO(TraverseStmt(E));
+  }
   return true;
 }
 
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index ce8b8b7..a39888f 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -43,6 +43,7 @@ class Stmt;
 class StringLiteral;
 class TemplateArgumentList;
 class TemplateParameterList;
+class TypeAliasTemplateDecl;
 class TypeLoc;
 class UnresolvedSetImpl;
 class VarTemplateDecl;
@@ -67,6 +68,9 @@ public:
 
   /// \brief Return the TypeLoc wrapper for the type source info.
   TypeLoc getTypeLoc() const; // implemented in TypeLoc.h
+  
+  /// \brief Override the type stored in this TypeSourceInfo. Use with caution!
+  void overrideType(QualType T) { Ty = T; }
 };
 
 /// TranslationUnitDecl - The top declaration context.
@@ -288,6 +292,8 @@ public:
     return const_cast(this)->getMostRecentDecl();
   }
 
+  ObjCStringFormatFamily getObjCFStringFormattingFamily() const;
+
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; }
 };
@@ -305,6 +311,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
 class LabelDecl : public NamedDecl {
   void anchor() override;
   LabelStmt *TheStmt;
+  StringRef MSAsmName;
+  bool MSAsmNameResolved;
   /// LocStart - For normal labels, this is the same as the main declaration
   /// label, i.e., the location of the identifier; for GNU local labels,
   /// this is the location of the __label__ keyword.
@@ -312,7 +320,10 @@ class LabelDecl : public NamedDecl {
 
   LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
             LabelStmt *S, SourceLocation StartL)
-    : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {}
+    : NamedDecl(Label, DC, IdentL, II),
+      TheStmt(S),
+      MSAsmNameResolved(false),
+      LocStart(StartL) {}
 
 public:
   static LabelDecl *Create(ASTContext &C, DeclContext *DC,
@@ -332,6 +343,12 @@ public:
     return SourceRange(LocStart, getLocation());
   }
 
+  bool isMSAsmLabel() const { return MSAsmName.size() != 0; }
+  bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
+  void setMSAsmLabel(StringRef Name);
+  StringRef getMSAsmLabel() const { return MSAsmName; }
+  void setMSAsmLabelResolved() { MSAsmNameResolved = true; }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == Label; }
@@ -648,8 +665,6 @@ struct EvaluatedStmt {
 /// declaration or definition.
 class VarDecl : public DeclaratorDecl, public Redeclarable {
 public:
-  typedef clang::StorageClass StorageClass;
-
   /// getStorageClassSpecifierString - Return the string used to
   /// specify the storage class \p SC.
   ///
@@ -891,6 +906,11 @@ public:
     return false;
   }
 
+  /// \brief Similar to isLocalVarDecl but also includes parameters.
+  bool isLocalVarDeclOrParm() const {
+    return isLocalVarDecl() || getKind() == Decl::ParmVar;
+  }
+
   /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but
   /// excludes variables declared in blocks.
   bool isFunctionOrMethodVarDecl() const {
@@ -1423,8 +1443,6 @@ private:
 class FunctionDecl : public DeclaratorDecl, public DeclContext,
                      public Redeclarable {
 public:
-  typedef clang::StorageClass StorageClass;
-
   /// \brief The kind of templated function a FunctionDecl can be.
   enum TemplatedKind {
     TK_NonTemplate,
@@ -1650,7 +1668,7 @@ public:
   /// unnecessary AST de-serialization of the body.
   Stmt *getBody(const FunctionDecl *&Definition) const;
 
-   Stmt *getBody() const override {
+  Stmt *getBody() const override {
     const FunctionDecl* Definition;
     return getBody(Definition);
   }
@@ -1880,7 +1898,7 @@ public:
     return llvm::makeArrayRef(ParamInfo, getNumParams());
   }
 
-  const ArrayRef &getDeclsInPrototypeScope() const {
+  ArrayRef getDeclsInPrototypeScope() const {
     return DeclsInPrototypeScope;
   }
   void setDeclsInPrototypeScope(ArrayRef NewDecls);
@@ -2154,17 +2172,41 @@ class FieldDecl : public DeclaratorDecl, public Mergeable {
   bool Mutable : 1;
   mutable unsigned CachedFieldIndex : 31;
 
-  /// \brief An InClassInitStyle value, and either a bit width expression (if
-  /// the InClassInitStyle value is ICIS_NoInit), or a pointer to the in-class
-  /// initializer for this field (otherwise).
+  /// The kinds of value we can store in InitializerOrBitWidth.
   ///
-  /// We can safely combine these two because in-class initializers are not
-  /// permitted for bit-fields.
+  /// Note that this is compatible with InClassInitStyle except for
+  /// ISK_CapturedVLAType.
+  enum InitStorageKind {
+    /// If the pointer is null, there's nothing special.  Otherwise,
+    /// this is a bitfield and the pointer is the Expr* storing the
+    /// bit-width.
+    ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit,
+
+    /// The pointer is an (optional due to delayed parsing) Expr*
+    /// holding the copy-initializer.
+    ISK_InClassCopyInit = (unsigned) ICIS_CopyInit,
+
+    /// The pointer is an (optional due to delayed parsing) Expr*
+    /// holding the list-initializer.
+    ISK_InClassListInit = (unsigned) ICIS_ListInit,
+
+    /// The pointer is a VariableArrayType* that's been captured;
+    /// the enclosing context is a lambda or captured statement.
+    ISK_CapturedVLAType,
+  };
+
+  /// \brief Storage for either the bit-width, the in-class
+  /// initializer, or the captured variable length array bound.
+  ///
+  /// We can safely combine these because in-class initializers are
+  /// not permitted for bit-fields, and both are exclusive with VLA
+  /// captures.
   ///
-  /// If the InClassInitStyle is not ICIS_NoInit and the initializer is null,
-  /// then this field has an in-class initializer which has not yet been parsed
+  /// If the storage kind is ISK_InClassCopyInit or
+  /// ISK_InClassListInit, but the initializer is null, then this
+  /// field has an in-class initializer which has not yet been parsed
   /// and attached.
-  llvm::PointerIntPair InitializerOrBitWidth;
+  llvm::PointerIntPair InitStorage;
 protected:
   FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc,
             SourceLocation IdLoc, IdentifierInfo *Id,
@@ -2172,7 +2214,7 @@ protected:
             InClassInitStyle InitStyle)
     : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc),
       Mutable(Mutable), CachedFieldIndex(0),
-      InitializerOrBitWidth(BW, InitStyle) {
+      InitStorage(BW, (InitStorageKind) InitStyle) {
     assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield");
   }
 
@@ -2192,10 +2234,10 @@ public:
   /// isMutable - Determines whether this field is mutable (C++ only).
   bool isMutable() const { return Mutable; }
 
-  /// isBitfield - Determines whether this field is a bitfield.
+  /// \brief Determines whether this field is a bitfield.
   bool isBitField() const {
-    return getInClassInitStyle() == ICIS_NoInit &&
-           InitializerOrBitWidth.getPointer();
+    return InitStorage.getInt() == ISK_BitWidthOrNothing &&
+           InitStorage.getPointer() != nullptr;
   }
 
   /// @brief Determines whether this is an unnamed bitfield.
@@ -2208,24 +2250,34 @@ public:
   bool isAnonymousStructOrUnion() const;
 
   Expr *getBitWidth() const {
-    return isBitField() ? InitializerOrBitWidth.getPointer() : nullptr;
+    return isBitField()
+               ? static_cast(InitStorage.getPointer())
+               : nullptr;
   }
   unsigned getBitWidthValue(const ASTContext &Ctx) const;
 
   /// setBitWidth - Set the bit-field width for this member.
   // Note: used by some clients (i.e., do not remove it).
-  void setBitWidth(Expr *Width);
+  void setBitWidth(Expr *Width) {
+    assert(InitStorage.getInt() == ISK_BitWidthOrNothing &&
+           InitStorage.getPointer() == nullptr &&
+           "bit width, initializer or captured type already set");
+    InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing);
+  }
+
   /// removeBitWidth - Remove the bit-field width from this member.
   // Note: used by some clients (i.e., do not remove it).
   void removeBitWidth() {
     assert(isBitField() && "no bitfield width to remove");
-    InitializerOrBitWidth.setPointer(nullptr);
+    InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
   }
 
   /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which
   /// this field has.
   InClassInitStyle getInClassInitStyle() const {
-    return static_cast(InitializerOrBitWidth.getInt());
+    InitStorageKind storageKind = InitStorage.getInt();
+    return (storageKind == ISK_CapturedVLAType
+              ? ICIS_NoInit : (InClassInitStyle) storageKind);
   }
 
   /// hasInClassInitializer - Determine whether this member has a C++11 in-class
@@ -2233,24 +2285,47 @@ public:
   bool hasInClassInitializer() const {
     return getInClassInitStyle() != ICIS_NoInit;
   }
+
   /// getInClassInitializer - Get the C++11 in-class initializer for this
   /// member, or null if one has not been set. If a valid declaration has an
   /// in-class initializer, but this returns null, then we have not parsed and
   /// attached it yet.
   Expr *getInClassInitializer() const {
-    return hasInClassInitializer() ? InitializerOrBitWidth.getPointer()
-                                   : nullptr;
+    return hasInClassInitializer()
+               ? static_cast(InitStorage.getPointer())
+               : nullptr;
   }
+
   /// setInClassInitializer - Set the C++11 in-class initializer for this
   /// member.
-  void setInClassInitializer(Expr *Init);
+  void setInClassInitializer(Expr *Init) {
+    assert(hasInClassInitializer() &&
+           InitStorage.getPointer() == nullptr &&
+           "bit width, initializer or captured type already set");
+    InitStorage.setPointer(Init);
+  }
+
   /// removeInClassInitializer - Remove the C++11 in-class initializer from this
   /// member.
   void removeInClassInitializer() {
     assert(hasInClassInitializer() && "no initializer to remove");
-    InitializerOrBitWidth.setPointer(nullptr);
-    InitializerOrBitWidth.setInt(ICIS_NoInit);
+    InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing);
+  }
+
+  /// \brief Determine whether this member captures the variable length array
+  /// type.
+  bool hasCapturedVLAType() const {
+    return InitStorage.getInt() == ISK_CapturedVLAType;
+  }
+
+  /// \brief Get the captured variable length array type.
+  const VariableArrayType *getCapturedVLAType() const {
+    return hasCapturedVLAType() ? static_cast(
+                                      InitStorage.getPointer())
+                                : nullptr;
   }
+  /// \brief Set the captured variable length array type for this field.
+  void setCapturedVLAType(const VariableArrayType *VLAType);
 
   /// getParent - Returns the parent of this field declaration, which
   /// is the struct in which this method is defined.
@@ -2492,9 +2567,13 @@ public:
 /// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x
 /// alias-declaration.
 class TypeAliasDecl : public TypedefNameDecl {
+  /// The template for which this is the pattern, if any.
+  TypeAliasTemplateDecl *Template;
+
   TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
                 SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo)
-      : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo) {}
+      : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo),
+        Template(nullptr) {}
 
 public:
   static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC,
@@ -2504,6 +2583,9 @@ public:
 
   SourceRange getSourceRange() const override LLVM_READONLY;
 
+  TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; }
+  void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; }
+
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == TypeAlias; }
@@ -2647,7 +2729,7 @@ public:
   }
 
   /// isThisDeclarationADefinition() - Return true if this declaration
-  /// is a completion definintion of the type.  Provided for consistency.
+  /// is a completion definition of the type.  Provided for consistency.
   bool isThisDeclarationADefinition() const {
     return isCompleteDefinition();
   }
@@ -3136,6 +3218,17 @@ public:
   /// \endcode
   bool isInjectedClassName() const;
 
+  /// \brief Determine whether this record is a class describing a lambda
+  /// function object.
+  bool isLambda() const;
+
+  /// \brief Determine whether this record is a record for captured variables in
+  /// CapturedStmt construct.
+  bool isCapturedRecord() const;
+  /// \brief Mark the record as a record for captured variables in CapturedStmt
+  /// construct.
+  void setCapturedRecord();
+
   /// getDefinition - Returns the RecordDecl that actually defines
   ///  this struct/union/class.  When determining whether or not a
   ///  struct/union/class is completely defined, one should use this
@@ -3181,6 +3274,15 @@ public:
   /// commandline option.
   bool isMsStruct(const ASTContext &C) const;
 
+  /// \brief Whether we are allowed to insert extra padding between fields.
+  /// These padding are added to help AddressSanitizer detect
+  /// intra-object-overflow bugs.
+  bool mayInsertExtraPadding(bool EmitRemark = false) const;
+
+  /// Finds the first data member which has a name.
+  /// nullptr is returned if no named data member exists.
+  const FieldDecl *findFirstNamedDataMember() const;  
+
 private:
   /// \brief Deserialize just the fields.
   void LoadFieldsFromExternalStorage() const;
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 607ca4e..984ab13 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -48,6 +48,7 @@ class ObjCInterfaceDecl;
 class ObjCMethodDecl;
 class ObjCProtocolDecl;
 struct PrintingPolicy;
+class RecordDecl;
 class Stmt;
 class StoredDeclsMap;
 class TranslationUnitDecl;
@@ -515,9 +516,13 @@ public:
   /// indicating the declaration is used.
   void markUsed(ASTContext &C);
 
-  /// \brief Whether this declaration was referenced.
+  /// \brief Whether any declaration of this entity was referenced.
   bool isReferenced() const;
 
+  /// \brief Whether this declaration was referenced. This should not be relied
+  /// upon for anything other than debugging.
+  bool isThisDeclarationReferenced() const { return Referenced; }
+
   void setReferenced(bool R = true) { Referenced = R; }
 
   /// \brief Whether this declaration is a top-level declaration (function,
@@ -675,9 +680,9 @@ public:
     return const_cast(this)->getLexicalDeclContext();
   }
 
-  virtual bool isOutOfLine() const {
-    return getLexicalDeclContext() != getDeclContext();
-  }
+  /// Determine whether this declaration is declared out of line (outside its
+  /// semantic context).
+  virtual bool isOutOfLine() const;
 
   /// setDeclContext - Set both the semantic and lexical DeclContext
   /// to DC.
@@ -1234,6 +1239,12 @@ public:
     return const_cast(this)->getEnclosingNamespaceContext();
   }
 
+  /// \brief Retrieve the outermost lexically enclosing record context.
+  RecordDecl *getOuterLexicalRecordContext();
+  const RecordDecl *getOuterLexicalRecordContext() const {
+    return const_cast(this)->getOuterLexicalRecordContext();
+  }
+
   /// \brief Test if this context is part of the enclosing namespace set of
   /// the context NS, as defined in C++0x [namespace.def]p9. If either context
   /// isn't a namespace, this is equivalent to Equals().
@@ -1642,7 +1653,7 @@ public:
 
   void dumpDeclContext() const;
   void dumpLookups() const;
-  void dumpLookups(llvm::raw_ostream &OS) const;
+  void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const;
 
 private:
   void reconcileExternalVisibleStorage() const;
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 72fad7c..027b41e 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -538,6 +538,12 @@ class CXXRecordDecl : public RecordDecl {
         ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr),
         MethodTyInfo(Info) {
       IsLambda = true;
+
+      // C++11 [expr.prim.lambda]p3:
+      //   This class type is neither an aggregate nor a literal type.
+      Aggregate = false;
+      PlainOldData = false;
+      HasNonLiteralTypeFieldsOrBases = true;
     }
 
     /// \brief Whether this lambda is known to be dependent, even if its
@@ -820,7 +826,11 @@ public:
   /// This value is used for lazy creation of default constructors.
   bool needsImplicitDefaultConstructor() const {
     return !data().UserDeclaredConstructor &&
-           !(data().DeclaredSpecialMembers & SMF_DefaultConstructor);
+           !(data().DeclaredSpecialMembers & SMF_DefaultConstructor) &&
+           // C++14 [expr.prim.lambda]p20:
+           //   The closure type associated with a lambda-expression has no
+           //   default constructor.
+           !isLambda();
   }
 
   /// \brief Determine whether this class has any user-declared constructors.
@@ -1371,6 +1381,15 @@ public:
   /// \brief Set the kind of specialization or template instantiation this is.
   void setTemplateSpecializationKind(TemplateSpecializationKind TSK);
 
+  /// \brief Retrieve the record declaration from which this record could be
+  /// instantiated. Returns null if this class is not a template instantiation.
+  const CXXRecordDecl *getTemplateInstantiationPattern() const;
+
+  CXXRecordDecl *getTemplateInstantiationPattern() {
+    return const_cast(const_cast(this)
+                                           ->getTemplateInstantiationPattern());
+  }
+
   /// \brief Returns the destructor decl for this class.
   CXXDestructorDecl *getDestructor() const;
 
@@ -2104,8 +2123,8 @@ public:
   }
   ArrayRef getArrayIndexes() {
     assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init");
-    return ArrayRef(reinterpret_cast(this + 1),
-                               getNumArrayIndices());
+    return llvm::makeArrayRef(reinterpret_cast(this + 1),
+                              getNumArrayIndices());
   }
 
   /// \brief Get the initializer.
@@ -2636,7 +2655,8 @@ public:
 /// \code
 /// namespace Foo = Bar;
 /// \endcode
-class NamespaceAliasDecl : public NamedDecl {
+class NamespaceAliasDecl : public NamedDecl,
+                           public Redeclarable {
   void anchor() override;
 
   /// \brief The location of the \c namespace keyword.
@@ -2654,17 +2674,47 @@ class NamespaceAliasDecl : public NamedDecl {
   /// a NamespaceAliasDecl.
   NamedDecl *Namespace;
 
-  NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc,
-                     SourceLocation AliasLoc, IdentifierInfo *Alias,
-                     NestedNameSpecifierLoc QualifierLoc,
+  NamespaceAliasDecl(ASTContext &C, DeclContext *DC,
+                     SourceLocation NamespaceLoc, SourceLocation AliasLoc,
+                     IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc,
                      SourceLocation IdentLoc, NamedDecl *Namespace)
-    : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias),
-      NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
-      QualifierLoc(QualifierLoc), Namespace(Namespace) { }
+      : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), redeclarable_base(C),
+        NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc),
+        QualifierLoc(QualifierLoc), Namespace(Namespace) {}
+
+  typedef Redeclarable redeclarable_base;
+  NamespaceAliasDecl *getNextRedeclarationImpl() override;
+  NamespaceAliasDecl *getPreviousDeclImpl() override;
+  NamespaceAliasDecl *getMostRecentDeclImpl() override;
 
   friend class ASTDeclReader;
 
 public:
+  static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
+                                    SourceLocation NamespaceLoc,
+                                    SourceLocation AliasLoc,
+                                    IdentifierInfo *Alias,
+                                    NestedNameSpecifierLoc QualifierLoc,
+                                    SourceLocation IdentLoc,
+                                    NamedDecl *Namespace);
+
+  static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+  typedef redeclarable_base::redecl_range redecl_range;
+  typedef redeclarable_base::redecl_iterator redecl_iterator;
+  using redeclarable_base::redecls_begin;
+  using redeclarable_base::redecls_end;
+  using redeclarable_base::redecls;
+  using redeclarable_base::getPreviousDecl;
+  using redeclarable_base::getMostRecentDecl;
+
+  NamespaceAliasDecl *getCanonicalDecl() override {
+    return getFirstDecl();
+  }
+  const NamespaceAliasDecl *getCanonicalDecl() const {
+    return getFirstDecl();
+  }
+
   /// \brief Retrieve the nested-name-specifier that qualifies the
   /// name of the namespace, with source-location information.
   NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; }
@@ -2701,16 +2751,6 @@ public:
   /// may either be a NamespaceDecl or a NamespaceAliasDecl.
   NamedDecl *getAliasedNamespace() const { return Namespace; }
 
-  static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC,
-                                    SourceLocation NamespaceLoc,
-                                    SourceLocation AliasLoc,
-                                    IdentifierInfo *Alias,
-                                    NestedNameSpecifierLoc QualifierLoc,
-                                    SourceLocation IdentLoc,
-                                    NamedDecl *Namespace);
-
-  static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID);
-
   SourceRange getSourceRange() const override LLVM_READONLY {
     return SourceRange(NamespaceLoc, IdentLoc);
   }
@@ -2824,7 +2864,7 @@ public:
 /// \code
 ///    using someNameSpace::someIdentifier;
 /// \endcode
-class UsingDecl : public NamedDecl {
+class UsingDecl : public NamedDecl, public Mergeable {
   void anchor() override;
 
   /// \brief The source location of the 'using' keyword itself.
@@ -2948,6 +2988,10 @@ public:
 
   SourceRange getSourceRange() const override LLVM_READONLY;
 
+  /// Retrieves the canonical declaration of this declaration.
+  UsingDecl *getCanonicalDecl() override { return getFirstDecl(); }
+  const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); }
+
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == Using; }
 
@@ -2966,7 +3010,8 @@ public:
 ///   using Base::foo;
 /// };
 /// \endcode
-class UnresolvedUsingValueDecl : public ValueDecl {
+class UnresolvedUsingValueDecl : public ValueDecl,
+                                 public Mergeable {
   void anchor() override;
 
   /// \brief The source location of the 'using' keyword
@@ -3022,6 +3067,14 @@ public:
 
   SourceRange getSourceRange() const override LLVM_READONLY;
 
+  /// Retrieves the canonical declaration of this declaration.
+  UnresolvedUsingValueDecl *getCanonicalDecl() override {
+    return getFirstDecl();
+  }
+  const UnresolvedUsingValueDecl *getCanonicalDecl() const {
+    return getFirstDecl();
+  }
+
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == UnresolvedUsingValue; }
 
@@ -3040,7 +3093,9 @@ public:
 ///
 /// The type associated with an unresolved using typename decl is
 /// currently always a typename type.
-class UnresolvedUsingTypenameDecl : public TypeDecl {
+class UnresolvedUsingTypenameDecl
+    : public TypeDecl,
+      public Mergeable {
   void anchor() override;
 
   /// \brief The source location of the 'typename' keyword
@@ -3084,6 +3139,14 @@ public:
   static UnresolvedUsingTypenameDecl *
   CreateDeserialized(ASTContext &C, unsigned ID);
 
+  /// Retrieves the canonical declaration of this declaration.
+  UnresolvedUsingTypenameDecl *getCanonicalDecl() override {
+    return getFirstDecl();
+  }
+  const UnresolvedUsingTypenameDecl *getCanonicalDecl() const {
+    return getFirstDecl();
+  }
+
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; }
 };
diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h
index d2016af..eba2266 100644
--- a/include/clang/AST/DeclLookups.h
+++ b/include/clang/AST/DeclLookups.h
@@ -75,7 +75,10 @@ inline DeclContext::lookups_range DeclContext::lookups() const {
   if (StoredDeclsMap *Map = Primary->buildLookup())
     return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
                          all_lookups_iterator(Map->end(), Map->end()));
-  return lookups_range();
+
+  // Synthesize an empty range. This requires that two default constructed
+  // versions of these iterators form a valid empty range.
+  return lookups_range(all_lookups_iterator(), all_lookups_iterator());
 }
 
 inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const {
@@ -91,7 +94,10 @@ inline DeclContext::lookups_range DeclContext::noload_lookups() const {
   if (StoredDeclsMap *Map = Primary->getLookupPtr())
     return lookups_range(all_lookups_iterator(Map->begin(), Map->end()),
                          all_lookups_iterator(Map->end(), Map->end()));
-  return lookups_range();
+
+  // Synthesize an empty range. This requires that two default constructed
+  // versions of these iterators form a valid empty range.
+  return lookups_range(all_lookups_iterator(), all_lookups_iterator());
 }
 
 inline
diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h
index db3b084..55d4b0f 100644
--- a/include/clang/AST/DeclObjC.h
+++ b/include/clang/AST/DeclObjC.h
@@ -329,6 +329,7 @@ public:
 
   QualType getReturnType() const { return MethodDeclType; }
   void setReturnType(QualType T) { MethodDeclType = T; }
+  SourceRange getReturnTypeSourceRange() const;
 
   /// \brief Determine the type of an expression that sends a message to this
   /// function.
@@ -378,8 +379,7 @@ public:
   /// ignored.
   void setMethodParams(ASTContext &C,
                        ArrayRef Params,
-                       ArrayRef SelLocs =
-                           ArrayRef());
+                       ArrayRef SelLocs = llvm::None);
 
   // Iterator access to parameter types.
   typedef std::const_mem_fun_t deref_fun;
@@ -591,7 +591,8 @@ public:
   bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const;
   ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
 
-  ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
+  ObjCPropertyDecl *
+  FindPropertyDeclaration(const IdentifierInfo *PropertyId) const;
 
   typedef llvm::DenseMap PropertyMap;
   
@@ -2354,7 +2355,7 @@ public:
 
   /// Lookup a property by name in the specified DeclContext.
   static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
-                                            IdentifierInfo *propertyID);
+                                            const IdentifierInfo *propertyID);
 
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classofKind(Kind K) { return K == ObjCProperty; }
diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h
index 1b329dc..7f0616f 100644
--- a/include/clang/AST/DeclOpenMP.h
+++ b/include/clang/AST/DeclOpenMP.h
@@ -12,13 +12,14 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_OPENMP_H
-#define LLVM_CLANG_AST_OPENMP_H
+#ifndef LLVM_CLANG_AST_DECLOPENMP_H
+#define LLVM_CLANG_AST_DECLOPENMP_H
 
 #include "clang/AST/DeclBase.h"
 #include "llvm/ADT/ArrayRef.h"
 
 namespace clang {
+class Expr;
 
 /// \brief This represents '#pragma omp threadprivate ...' directive.
 /// For example, in the following, both 'a' and 'A::b' are threadprivate:
@@ -42,9 +43,8 @@ class OMPThreadPrivateDecl : public Decl {
     Decl(DK, DC, L), NumVars(0) { }
 
   ArrayRef getVars() const {
-    return ArrayRef(
-                   reinterpret_cast(this + 1),
-                   NumVars);
+    return llvm::makeArrayRef(reinterpret_cast(this + 1),
+                              NumVars);
   }
 
   MutableArrayRef getVars() {
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 980a06e..9283d2d 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -87,10 +87,10 @@ public:
   unsigned size() const { return NumParams; }
 
   ArrayRef asArray() {
-    return ArrayRef(begin(), size());
+    return llvm::makeArrayRef(begin(), end());
   }
   ArrayRef asArray() const {
-    return ArrayRef(begin(), size());
+    return llvm::makeArrayRef(begin(), size());
   }
 
   NamedDecl* getParam(unsigned Idx) {
@@ -204,7 +204,7 @@ public:
 
   /// \brief Produce this as an array ref.
   ArrayRef asArray() const {
-    return ArrayRef(data(), size());
+    return llvm::makeArrayRef(data(), size());
   }
 
   /// \brief Retrieve the number of template arguments in this
@@ -236,7 +236,7 @@ protected:
       TemplateParams(nullptr) {}
 
   // Construct a template decl with the given name and parameters.
-  // Used when there is not templated element (tt-params, alias?).
+  // Used when there is not templated element (tt-params).
   TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
                DeclarationName Name, TemplateParameterList *Params)
     : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h
index 3076b30..49e51e0 100644
--- a/include/clang/AST/DeclarationName.h
+++ b/include/clang/AST/DeclarationName.h
@@ -59,6 +59,7 @@ public:
     CXXLiteralOperatorName,
     CXXUsingDirective
   };
+  static const unsigned NumNameKinds = CXXUsingDirective + 1;
 
 private:
   /// StoredNameKind - The kind of name that is actually stored in the
diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h
index 63047ec..8e038c8 100644
--- a/include/clang/AST/DependentDiagnostic.h
+++ b/include/clang/AST/DependentDiagnostic.h
@@ -15,8 +15,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
-#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H
+#ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
+#define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H
 
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/DeclContextInternals.h"
@@ -178,7 +178,8 @@ inline DeclContext::ddiag_range DeclContext::ddiags() const {
     = static_cast(getPrimaryContext()->getLookupPtr());
 
   if (!Map)
-    return ddiag_range();
+    // Return an empty range using the always-end default constructor.
+    return ddiag_range(ddiag_iterator(), ddiag_iterator());
 
   return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator());
 }
diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h
index 12c4fcc..59de104 100644
--- a/include/clang/AST/EvaluatedExprVisitor.h
+++ b/include/clang/AST/EvaluatedExprVisitor.h
@@ -56,6 +56,17 @@ public:
     return this->Visit(E->getChosenSubExpr());
   }
 
+  void VisitGenericSelectionExpr(GenericSelectionExpr *E) {
+    // The controlling expression of a generic selection is not evaluated.
+
+    // Don't visit either child expression if the condition is type-dependent.
+    if (E->isResultDependent())
+      return;
+    // Only the selected subexpression matters; the other subexpressions and the
+    // controlling expression are not evaluated.
+    return this->Visit(E->getResultExpr());
+  }
+
   void VisitDesignatedInitExpr(DesignatedInitExpr *E) {
     // Only the actual initializer matters; the designators are all constant
     // expressions.
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index b4bb0b6..c410f23 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -45,6 +45,7 @@ namespace clang {
   class ObjCPropertyRefExpr;
   class OpaqueValueExpr;
   class ParmVarDecl;
+  class StringLiteral;
   class TargetInfo;
   class ValueDecl;
 
@@ -124,8 +125,7 @@ public:
   QualType getType() const { return TR; }
   void setType(QualType t) {
     // In C++, the type of an expression is always adjusted so that it
-    // will not have reference type an expression will never have
-    // reference type (C++ [expr]p6). Use
+    // will not have reference type (C++ [expr]p6). Use
     // QualType::getNonReferenceType() to retrieve the non-reference
     // type. Additionally, inspect Expr::isLvalue to determine whether
     // an expression that is adjusted in this manner should be
@@ -586,8 +586,13 @@ public:
 
   /// HasSideEffects - This routine returns true for all those expressions
   /// which have any effect other than producing a value. Example is a function
-  /// call, volatile variable read, or throwing an exception.
-  bool HasSideEffects(const ASTContext &Ctx) const;
+  /// call, volatile variable read, or throwing an exception. If
+  /// IncludePossibleEffects is false, this call treats certain expressions with
+  /// potential side effects (such as function call-like expressions,
+  /// instantiation-dependent expressions, or invocations from a macro) as not
+  /// having side effects.
+  bool HasSideEffects(const ASTContext &Ctx,
+                      bool IncludePossibleEffects = true) const;
 
   /// \brief Determine whether this expression involves a call to any function
   /// that is not trivial.
@@ -886,9 +891,9 @@ public:
 ///   DeclRefExprBits.HasTemplateKWAndArgsInfo:
 ///       Specifies when this declaration reference expression has an explicit
 ///       C++ template keyword and/or template argument list.
-///   DeclRefExprBits.RefersToEnclosingLocal
+///   DeclRefExprBits.RefersToEnclosingVariableOrCapture
 ///       Specifies when this declaration reference expression (validly)
-///       refers to a local variable from a different function.
+///       refers to an enclosed local or a captured variable.
 class DeclRefExpr : public Expr {
   /// \brief The declaration that we are referencing.
   ValueDecl *D;
@@ -933,7 +938,7 @@ class DeclRefExpr : public Expr {
   DeclRefExpr(const ASTContext &Ctx,
               NestedNameSpecifierLoc QualifierLoc,
               SourceLocation TemplateKWLoc,
-              ValueDecl *D, bool refersToEnclosingLocal,
+              ValueDecl *D, bool RefersToEnlosingVariableOrCapture,
               const DeclarationNameInfo &NameInfo,
               NamedDecl *FoundD,
               const TemplateArgumentListInfo *TemplateArgs,
@@ -948,7 +953,7 @@ class DeclRefExpr : public Expr {
   void computeDependence(const ASTContext &C);
 
 public:
-  DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T,
+  DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T,
               ExprValueKind VK, SourceLocation L,
               const DeclarationNameLoc &LocInfo = DeclarationNameLoc())
     : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false),
@@ -957,20 +962,22 @@ public:
     DeclRefExprBits.HasTemplateKWAndArgsInfo = 0;
     DeclRefExprBits.HasFoundDecl = 0;
     DeclRefExprBits.HadMultipleCandidates = 0;
-    DeclRefExprBits.RefersToEnclosingLocal = refersToEnclosingLocal;
+    DeclRefExprBits.RefersToEnclosingVariableOrCapture =
+        RefersToEnclosingVariableOrCapture;
     computeDependence(D->getASTContext());
   }
 
   static DeclRefExpr *
   Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
-         SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal,
-         SourceLocation NameLoc, QualType T, ExprValueKind VK,
-         NamedDecl *FoundD = nullptr,
+         SourceLocation TemplateKWLoc, ValueDecl *D,
+         bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc,
+         QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr,
          const TemplateArgumentListInfo *TemplateArgs = nullptr);
 
   static DeclRefExpr *
   Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc,
-         SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal,
+         SourceLocation TemplateKWLoc, ValueDecl *D,
+         bool RefersToEnclosingVariableOrCapture,
          const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK,
          NamedDecl *FoundD = nullptr,
          const TemplateArgumentListInfo *TemplateArgs = nullptr);
@@ -1144,10 +1151,10 @@ public:
     DeclRefExprBits.HadMultipleCandidates = V;
   }
 
-  /// Does this DeclRefExpr refer to a local declaration from an
-  /// enclosing function scope?
-  bool refersToEnclosingLocal() const {
-    return DeclRefExprBits.RefersToEnclosingLocal;
+  /// \brief Does this DeclRefExpr refer to an enclosing local or a captured
+  /// variable?
+  bool refersToEnclosingVariableOrCapture() const {
+    return DeclRefExprBits.RefersToEnclosingVariableOrCapture;
   }
 
   static bool classof(const Stmt *T) {
@@ -1161,7 +1168,7 @@ public:
   friend class ASTStmtWriter;
 };
 
-/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__.
+/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__.
 class PredefinedExpr : public Expr {
 public:
   enum IdentType {
@@ -1171,7 +1178,7 @@ public:
     FuncDName,
     FuncSig,
     PrettyFunction,
-    /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the
+    /// \brief The same as PrettyFunction, except that the
     /// 'virtual' keyword is omitted for virtual member functions.
     PrettyFunctionNoVirtual
   };
@@ -1179,24 +1186,27 @@ public:
 private:
   SourceLocation Loc;
   IdentType Type;
+  Stmt *FnName;
+
 public:
-  PredefinedExpr(SourceLocation l, QualType type, IdentType IT)
-    : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary,
-           type->isDependentType(), type->isDependentType(),
-           type->isInstantiationDependentType(),
-           /*ContainsUnexpandedParameterPack=*/false),
-      Loc(l), Type(IT) {}
+  PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT,
+                 StringLiteral *SL);
 
   /// \brief Construct an empty predefined expression.
   explicit PredefinedExpr(EmptyShell Empty)
-    : Expr(PredefinedExprClass, Empty) { }
+      : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {}
 
   IdentType getIdentType() const { return Type; }
-  void setIdentType(IdentType IT) { Type = IT; }
 
   SourceLocation getLocation() const { return Loc; }
   void setLocation(SourceLocation L) { Loc = L; }
 
+  StringLiteral *getFunctionName();
+  const StringLiteral *getFunctionName() const {
+    return const_cast(this)->getFunctionName();
+  }
+
+  static StringRef getIdentTypeName(IdentType IT);
   static std::string ComputeName(IdentType IT, const Decl *CurrentDecl);
 
   SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
@@ -1207,7 +1217,9 @@ public:
   }
 
   // Iterators
-  child_range children() { return child_range(); }
+  child_range children() { return child_range(&FnName, &FnName + 1); }
+
+  friend class ASTStmtReader;
 };
 
 /// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without
@@ -2212,11 +2224,11 @@ public:
   /// getArg - Return the specified argument.
   Expr *getArg(unsigned Arg) {
     assert(Arg < NumArgs && "Arg access out of range!");
-    return cast(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
+    return cast_or_null(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
   }
   const Expr *getArg(unsigned Arg) const {
     assert(Arg < NumArgs && "Arg access out of range!");
-    return cast(SubExprs[Arg+getNumPreArgs()+PREARGS_START]);
+    return cast_or_null(SubExprs[Arg + getNumPreArgs() + PREARGS_START]);
   }
 
   /// setArg - Set the specified argument.
@@ -2256,8 +2268,8 @@ public:
   /// interface.  This provides efficient reverse iteration of the
   /// subexpressions.  This is currently used for CFG construction.
   ArrayRef getRawSubExprs() {
-    return ArrayRef(SubExprs,
-                           getNumPreArgs() + PREARGS_START + getNumArgs());
+    return llvm::makeArrayRef(SubExprs,
+                              getNumPreArgs() + PREARGS_START + getNumArgs());
   }
 
   /// getNumCommas - Return the number of commas that must have been present in
@@ -2653,9 +2665,6 @@ public:
 /// representation in the source code (ExplicitCastExpr's derived
 /// classes).
 class CastExpr : public Expr {
-public:
-  typedef clang::CastKind CastKind;
-
 private:
   Stmt *Op;
 
@@ -2673,20 +2682,23 @@ private:
   }
 
 protected:
-  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK,
-           const CastKind kind, Expr *op, unsigned BasePathSize) :
-    Expr(SC, ty, VK, OK_Ordinary,
-         // Cast expressions are type-dependent if the type is
-         // dependent (C++ [temp.dep.expr]p3).
-         ty->isDependentType(),
-         // Cast expressions are value-dependent if the type is
-         // dependent or if the subexpression is value-dependent.
-         ty->isDependentType() || (op && op->isValueDependent()),
-         (ty->isInstantiationDependentType() ||
-          (op && op->isInstantiationDependent())),
-         (ty->containsUnexpandedParameterPack() ||
-          (op && op->containsUnexpandedParameterPack()))),
-    Op(op) {
+  CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind,
+           Expr *op, unsigned BasePathSize)
+      : Expr(SC, ty, VK, OK_Ordinary,
+             // Cast expressions are type-dependent if the type is
+             // dependent (C++ [temp.dep.expr]p3).
+             ty->isDependentType(),
+             // Cast expressions are value-dependent if the type is
+             // dependent or if the subexpression is value-dependent.
+             ty->isDependentType() || (op && op->isValueDependent()),
+             (ty->isInstantiationDependentType() ||
+              (op && op->isInstantiationDependent())),
+             // An implicit cast expression doesn't (lexically) contain an
+             // unexpanded pack, even if its target type does.
+             ((SC != ImplicitCastExprClass &&
+               ty->containsUnexpandedParameterPack()) ||
+              (op && op->containsUnexpandedParameterPack()))),
+        Op(op) {
     assert(kind != CK_Invalid && "creating cast with invalid cast kind");
     CastExprBits.Kind = kind;
     setBasePathSize(BasePathSize);
@@ -4841,6 +4853,24 @@ public:
     return child_range(SubExprs, SubExprs+NumSubExprs);
   }
 };
+
+/// TypoExpr - Internal placeholder for expressions where typo correction
+/// still needs to be performed and/or an error diagnostic emitted.
+class TypoExpr : public Expr {
+public:
+  TypoExpr(QualType T)
+      : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary,
+             /*isTypeDependent*/ true,
+             /*isValueDependent*/ true,
+             /*isInstantiationDependent*/ true,
+             /*containsUnexpandedParameterPack*/ false) {
+    assert(T->isDependentType() && "TypoExpr given a non-dependent type");
+  }
+
+  child_range children() { return child_range(); }
+  SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); }
+  SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); }
+};
 }  // end namespace clang
 
 #endif
diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h
index 3a43d6d..1768178 100644
--- a/include/clang/AST/ExprCXX.h
+++ b/include/clang/AST/ExprCXX.h
@@ -17,10 +17,10 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
+#include "clang/AST/LambdaCapture.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/UnresolvedSet.h"
 #include "clang/Basic/ExpressionTraits.h"
-#include "clang/AST/LambdaCapture.h"
 #include "clang/Basic/TypeTraits.h"
 #include "llvm/Support/Compiler.h"
 
@@ -967,8 +967,14 @@ public:
   const FieldDecl *getField() const { return Field; }
 
   /// \brief Get the initialization expression that will be used.
-  const Expr *getExpr() const { return Field->getInClassInitializer(); }
-  Expr *getExpr() { return Field->getInClassInitializer(); }
+  const Expr *getExpr() const {
+    assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
+    return Field->getInClassInitializer();
+  }
+  Expr *getExpr() {
+    assert(Field->getInClassInitializer() && "initializer hasn't been parsed");
+    return Field->getInClassInitializer();
+  }
 
   SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
   SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
@@ -1165,6 +1171,13 @@ public:
 
   typedef ExprIterator arg_iterator;
   typedef ConstExprIterator const_arg_iterator;
+  typedef llvm::iterator_range arg_range;
+  typedef llvm::iterator_range arg_const_range;
+
+  arg_range arguments() { return arg_range(arg_begin(), arg_end()); }
+  arg_const_range arguments() const {
+    return arg_const_range(arg_begin(), arg_end());
+  }
 
   arg_iterator arg_begin() { return Args; }
   arg_iterator arg_end() { return Args + NumArgs; }
@@ -1569,12 +1582,12 @@ class CXXScalarValueInitExpr : public Expr {
 public:
   /// \brief Create an explicitly-written scalar-value initialization
   /// expression.
-  CXXScalarValueInitExpr(QualType Type,
-                         TypeSourceInfo *TypeInfo,
-                         SourceLocation rParenLoc ) :
-    Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
-         false, false, Type->isInstantiationDependentType(), false),
-    RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
+  CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo,
+                         SourceLocation rParenLoc)
+      : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary,
+             false, false, Type->isInstantiationDependentType(),
+             Type->containsUnexpandedParameterPack()),
+        RParenLoc(rParenLoc), TypeInfo(TypeInfo) {}
 
   explicit CXXScalarValueInitExpr(EmptyShell Shell)
     : Expr(CXXScalarValueInitExprClass, Shell) { }
@@ -2113,7 +2126,7 @@ public:
   
   /// \brief Retrieve the argument types.
   ArrayRef getArgs() const { 
-    return ArrayRef(getTypeSourceInfos(), getNumArgs());
+    return llvm::makeArrayRef(getTypeSourceInfos(), getNumArgs());
   }
   
   typedef TypeSourceInfo **arg_iterator;
@@ -2767,7 +2780,7 @@ public:
                                   ArrayRef objects);
 
   ArrayRef getObjects() const {
-    return ArrayRef(getObjectsBuffer(), getNumObjects());
+    return llvm::makeArrayRef(getObjectsBuffer(), getNumObjects());
   }
 
   unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; }
@@ -2902,8 +2915,9 @@ public:
 
   SourceLocation getLocStart() const LLVM_READONLY;
   SourceLocation getLocEnd() const LLVM_READONLY {
-    assert(RParenLoc.isValid() || NumArgs == 1);
-    return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd();
+    if (!RParenLoc.isValid() && NumArgs > 0)
+      return getArg(NumArgs - 1)->getLocEnd();
+    return RParenLoc;
   }
 
   static bool classof(const Stmt *T) {
@@ -3811,6 +3825,69 @@ public:
   }
 };
 
+/// \brief Represents a folding of a pack over an operator.
+///
+/// This expression is always dependent and represents a pack expansion of the
+/// forms:
+///
+///    ( expr op ... )
+///    ( ... op expr )
+///    ( expr op ... op expr )
+class CXXFoldExpr : public Expr {
+  SourceLocation LParenLoc;
+  SourceLocation EllipsisLoc;
+  SourceLocation RParenLoc;
+  Stmt *SubExprs[2];
+  BinaryOperatorKind Opcode;
+
+  friend class ASTStmtReader;
+  friend class ASTStmtWriter;
+public:
+  CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS,
+              BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS,
+              SourceLocation RParenLoc)
+      : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary,
+             /*Dependent*/ true, true, true,
+             /*ContainsUnexpandedParameterPack*/ false),
+        LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc),
+        Opcode(Opcode) {
+    SubExprs[0] = LHS;
+    SubExprs[1] = RHS;
+  }
+  CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {}
+
+  Expr *getLHS() const { return static_cast(SubExprs[0]); }
+  Expr *getRHS() const { return static_cast(SubExprs[1]); }
+
+  /// Does this produce a right-associated sequence of operators?
+  bool isRightFold() const {
+    return getLHS() && getLHS()->containsUnexpandedParameterPack();
+  }
+  /// Does this produce a left-associated sequence of operators?
+  bool isLeftFold() const { return !isRightFold(); }
+  /// Get the pattern, that is, the operand that contains an unexpanded pack.
+  Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); }
+  /// Get the operand that doesn't contain a pack, for a binary fold.
+  Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); }
+
+  SourceLocation getEllipsisLoc() const { return EllipsisLoc; }
+  BinaryOperatorKind getOperator() const { return Opcode; }
+
+  SourceLocation getLocStart() const LLVM_READONLY {
+    return LParenLoc;
+  }
+  SourceLocation getLocEnd() const LLVM_READONLY {
+    return RParenLoc;
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXFoldExprClass;
+  }
+
+  // Iterators
+  child_range children() { return child_range(SubExprs, SubExprs + 2); }
+};
+
 }  // end namespace clang
 
 #endif
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 817c0cc..f296e8f 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -124,6 +124,15 @@ public:
   
   // Iterators
   child_range children() { return child_range(&SubExpr, &SubExpr+1); }
+
+  typedef ConstExprIterator const_arg_iterator;
+
+  const_arg_iterator arg_begin() const {
+    return reinterpret_cast(&SubExpr);
+  }
+  const_arg_iterator arg_end() const {
+    return reinterpret_cast(&SubExpr + 1);
+  }
   
   friend class ASTStmtReader;
 };
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index 1e8eff3..ff1d180 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -11,8 +11,8 @@
 //  construction of AST nodes from some external source.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
-#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
+#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H
+#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H
 
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclBase.h"
@@ -650,4 +650,4 @@ typedef LazyOffsetPtr(DeclAndBits.getPointer());
   }
 
+  /// \brief Determine whether this captures a variable length array bound
+  /// expression.
+  bool capturesVLAType() const {
+    return (DeclAndBits.getPointer() == nullptr) &&
+           (DeclAndBits.getInt() & Capture_ByCopy);
+  }
+
   /// \brief Determine whether this is an init-capture.
   bool isInitCapture() const {
     return capturesVariable() && getCapturedVar()->isInitCapture();
diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h
index a8d1199..cbe08a1 100644
--- a/include/clang/AST/Mangle.h
+++ b/include/clang/AST/Mangle.h
@@ -156,6 +156,11 @@ public:
   virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D,
                                                raw_ostream &) = 0;
 
+  virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D,
+                                   raw_ostream &) = 0;
+  virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
+                                   raw_ostream &) = 0;
+
   static bool classof(const MangleContext *C) {
     return C->getKind() == MK_Itanium;
   }
diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h
index 56c9952..7a81855 100644
--- a/include/clang/AST/MangleNumberingContext.h
+++ b/include/clang/AST/MangleNumberingContext.h
@@ -12,8 +12,8 @@
 //  literals.
 //
 //===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
-#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H
+#ifndef LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H
+#define LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H
 
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/DenseMap.h"
@@ -30,23 +30,20 @@ class VarDecl;
 
 /// \brief Keeps track of the mangled names of lambda expressions and block
 /// literals within a particular context.
-class MangleNumberingContext 
-    : public RefCountedBase {
-  llvm::DenseMap ManglingNumbers;
-
+class MangleNumberingContext : public RefCountedBase {
 public:
   virtual ~MangleNumberingContext() {}
 
   /// \brief Retrieve the mangling number of a new lambda expression with the
   /// given call operator within this context.
-  unsigned getManglingNumber(const CXXMethodDecl *CallOperator);
+  virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0;
 
   /// \brief Retrieve the mangling number of a new block literal within this
   /// context.
-  unsigned getManglingNumber(const BlockDecl *BD);
+  virtual unsigned getManglingNumber(const BlockDecl *BD) = 0;
 
   /// Static locals are numbered by source order.
-  unsigned getStaticLocalNumber(const VarDecl *VD);
+  virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0;
 
   /// \brief Retrieve the mangling number of a static local variable within
   /// this context.
@@ -58,6 +55,6 @@ public:
   virtual unsigned getManglingNumber(const TagDecl *TD,
                                      unsigned MSLocalManglingNumber) = 0;
 };
-  
+
 } // end namespace clang
 #endif
diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h
index 0b21b03..33fcce2 100644
--- a/include/clang/AST/NSAPI.h
+++ b/include/clang/AST/NSAPI.h
@@ -42,7 +42,8 @@ public:
     NSStr_stringWithUTF8String,
     NSStr_stringWithCStringEncoding,
     NSStr_stringWithCString,
-    NSStr_initWithString
+    NSStr_initWithString,
+    NSStr_initWithUTF8String
   };
   static const unsigned NumNSStringMethods = 5;
 
@@ -100,8 +101,8 @@ public:
     NSDict_objectForKey,
     NSMutableDict_setObjectForKey
   };
-  static const unsigned NumNSDictionaryMethods = 11;
-
+  static const unsigned NumNSDictionaryMethods = 12;
+  
   /// \brief The Objective-C NSDictionary selectors.
   Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const;
 
@@ -184,6 +185,9 @@ public:
   bool isObjCNSIntegerType(QualType T) const;
   /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
   bool isObjCNSUIntegerType(QualType T) const;
+  /// \brief Returns one of NSIntegral typedef names if \param T is a typedef
+  /// of that name in objective-c.
+  StringRef GetNSIntegralKind(QualType T) const;
 
 private:
   bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const;
diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h
index fc719bd..518f123 100644
--- a/include/clang/AST/NestedNameSpecifier.h
+++ b/include/clang/AST/NestedNameSpecifier.h
@@ -22,6 +22,7 @@
 namespace clang {
 
 class ASTContext;
+class CXXRecordDecl;
 class NamespaceAliasDecl;
 class NamespaceDecl;
 class IdentifierInfo;
@@ -45,7 +46,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode {
   /// \brief Enumeration describing
   enum StoredSpecifierKind {
     StoredIdentifier = 0,
-    StoredNamespaceOrAlias = 1,
+    StoredDecl = 1,
     StoredTypeSpec = 2,
     StoredTypeSpecWithTemplate = 3
   };
@@ -83,7 +84,10 @@ public:
     /// stored as a Type*.
     TypeSpecWithTemplate,
     /// \brief The global specifier '::'. There is no stored value.
-    Global
+    Global,
+    /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of
+    /// the class it appeared in.
+    Super
   };
 
 private:
@@ -143,6 +147,11 @@ public:
   /// scope.
   static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context);
 
+  /// \brief Returns the nested name specifier representing the __super scope
+  /// for the given CXXRecordDecl.
+  static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context,
+                                             CXXRecordDecl *RD);
+
   /// \brief Return the prefix of this nested name specifier.
   ///
   /// The prefix contains all of the parts of the nested name
@@ -172,6 +181,10 @@ public:
   /// specifier.
   NamespaceAliasDecl *getAsNamespaceAlias() const;
 
+  /// \brief Retrieve the record declaration stored in this nested name
+  /// specifier.
+  CXXRecordDecl *getAsRecordDecl() const;
+
   /// \brief Retrieve the type stored in this nested name specifier.
   const Type *getAsType() const {
     if (Prefix.getInt() == StoredTypeSpec ||
@@ -421,7 +434,22 @@ public:
   /// \brief Turn this (empty) nested-name-specifier into the global
   /// nested-name-specifier '::'.
   void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc);
-
+  
+  /// \brief Turns this (empty) nested-name-specifier into '__super'
+  /// nested-name-specifier.
+  ///
+  /// \param Context The AST context in which this nested-name-specifier
+  /// resides.
+  ///
+  /// \param RD The declaration of the class in which nested-name-specifier
+  /// appeared.
+  ///
+  /// \param SuperLoc The location of the '__super' keyword.
+  /// name.
+  ///
+  /// \param ColonColonLoc The location of the trailing '::'.
+  void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, 
+                 SourceLocation SuperLoc, SourceLocation ColonColonLoc);
   /// \brief Make a new nested-name-specifier from incomplete source-location
   /// information.
   ///
diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h
index 3345959..0c3002c 100644
--- a/include/clang/AST/OpenMPClause.h
+++ b/include/clang/AST/OpenMPClause.h
@@ -61,7 +61,7 @@ public:
   ConstStmtRange children() const {
     return const_cast(this)->children();
   }
-  static bool classof(const OMPClause *T) { return true; }
+  static bool classof(const OMPClause *) { return true; }
 };
 
 /// \brief This represents clauses with the list of variables like 'private',
@@ -135,10 +135,10 @@ public:
 
   /// \brief Fetches list of all variables in the clause.
   ArrayRef getVarRefs() const {
-    return ArrayRef(
+    return llvm::makeArrayRef(
         reinterpret_cast(
             reinterpret_cast(this) +
-            llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf())),
+            llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf())),
         NumVars);
   }
 };
@@ -770,6 +770,153 @@ public:
   StmtRange children() { return StmtRange(); }
 };
 
+/// \brief This represents 'read' clause in the '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic read
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'read' clause.
+///
+class OMPReadClause : public OMPClause {
+public:
+  /// \brief Build 'read' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  ///
+  OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_read, StartLoc, EndLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {}
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_read;
+  }
+
+  StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'write' clause in the '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic write
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'write' clause.
+///
+class OMPWriteClause : public OMPClause {
+public:
+  /// \brief Build 'write' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  ///
+  OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_write, StartLoc, EndLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPWriteClause()
+      : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {}
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_write;
+  }
+
+  StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'update' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic update
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'update' clause.
+///
+class OMPUpdateClause : public OMPClause {
+public:
+  /// \brief Build 'update' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  ///
+  OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_update, StartLoc, EndLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPUpdateClause()
+      : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {}
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_update;
+  }
+
+  StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'capture' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic capture
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'capture' clause.
+///
+class OMPCaptureClause : public OMPClause {
+public:
+  /// \brief Build 'capture' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  ///
+  OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_capture, StartLoc, EndLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPCaptureClause()
+      : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {}
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_capture;
+  }
+
+  StmtRange children() { return StmtRange(); }
+};
+
+/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic'
+/// directive.
+///
+/// \code
+/// #pragma omp atomic seq_cst
+/// \endcode
+/// In this example directive '#pragma omp atomic' has 'seq_cst' clause.
+///
+class OMPSeqCstClause : public OMPClause {
+public:
+  /// \brief Build 'seq_cst' clause.
+  ///
+  /// \param StartLoc Starting location of the clause.
+  /// \param EndLoc Ending location of the clause.
+  ///
+  OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {}
+
+  /// \brief Build an empty clause.
+  ///
+  OMPSeqCstClause()
+      : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {}
+
+  static bool classof(const OMPClause *T) {
+    return T->getClauseKind() == OMPC_seq_cst;
+  }
+
+  StmtRange children() { return StmtRange(); }
+};
+
 /// \brief This represents clause 'private' in the '#pragma omp ...' directives.
 ///
 /// \code
@@ -779,6 +926,7 @@ public:
 /// with the variables 'a' and 'b'.
 ///
 class OMPPrivateClause : public OMPVarListClause {
+  friend class OMPClauseReader;
   /// \brief Build clause with number of variables \a N.
   ///
   /// \param StartLoc Starting location of the clause.
@@ -800,6 +948,20 @@ class OMPPrivateClause : public OMPVarListClause {
                                            SourceLocation(), SourceLocation(),
                                            N) {}
 
+  /// \brief Sets the list of references to private copies with initializers for
+  /// new private variables.
+  /// \param VL List of references.
+  void setPrivateCopies(ArrayRef VL);
+
+  /// \brief Gets the list of references to private copies with initializers for
+  /// new private variables.
+  MutableArrayRef getPrivateCopies() {
+    return MutableArrayRef(varlist_end(), varlist_size());
+  }
+  ArrayRef getPrivateCopies() const {
+    return llvm::makeArrayRef(varlist_end(), varlist_size());
+  }
+
 public:
   /// \brief Creates clause with a list of variables \a VL.
   ///
@@ -808,10 +970,12 @@ public:
   /// \param LParenLoc Location of '('.
   /// \param EndLoc Ending location of the clause.
   /// \param VL List of references to the variables.
+  /// \param PrivateVL List of references to private copies with initializers.
   ///
   static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc,
                                   SourceLocation LParenLoc,
-                                  SourceLocation EndLoc, ArrayRef VL);
+                                  SourceLocation EndLoc, ArrayRef VL,
+                                  ArrayRef PrivateVL);
   /// \brief Creates an empty clause with the place for \a N variables.
   ///
   /// \param C AST context.
@@ -819,6 +983,21 @@ public:
   ///
   static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N);
 
+  typedef MutableArrayRef::iterator private_copies_iterator;
+  typedef ArrayRef::iterator private_copies_const_iterator;
+  typedef llvm::iterator_range private_copies_range;
+  typedef llvm::iterator_range
+      private_copies_const_range;
+
+  private_copies_range private_copies() {
+    return private_copies_range(getPrivateCopies().begin(),
+                                getPrivateCopies().end());
+  }
+  private_copies_const_range private_copies() const {
+    return private_copies_const_range(getPrivateCopies().begin(),
+                                      getPrivateCopies().end());
+  }
+
   StmtRange children() {
     return StmtRange(reinterpret_cast(varlist_begin()),
                      reinterpret_cast(varlist_end()));
@@ -839,6 +1018,8 @@ public:
 /// with the variables 'a' and 'b'.
 ///
 class OMPFirstprivateClause : public OMPVarListClause {
+  friend class OMPClauseReader;
+
   /// \brief Build clause with number of variables \a N.
   ///
   /// \param StartLoc Starting location of the clause.
@@ -859,6 +1040,33 @@ class OMPFirstprivateClause : public OMPVarListClause {
       : OMPVarListClause(
             OMPC_firstprivate, SourceLocation(), SourceLocation(),
             SourceLocation(), N) {}
+  /// \brief Sets the list of references to private copies with initializers for
+  /// new private variables.
+  /// \param VL List of references.
+  void setPrivateCopies(ArrayRef VL);
+
+  /// \brief Gets the list of references to private copies with initializers for
+  /// new private variables.
+  MutableArrayRef getPrivateCopies() {
+    return MutableArrayRef(varlist_end(), varlist_size());
+  }
+  ArrayRef getPrivateCopies() const {
+    return llvm::makeArrayRef(varlist_end(), varlist_size());
+  }
+
+  /// \brief Sets the list of references to initializer variables for new
+  /// private variables.
+  /// \param VL List of references.
+  void setInits(ArrayRef VL);
+
+  /// \brief Gets the list of references to initializer variables for new
+  /// private variables.
+  MutableArrayRef getInits() {
+    return MutableArrayRef(getPrivateCopies().end(), varlist_size());
+  }
+  ArrayRef getInits() const {
+    return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size());
+  }
 
 public:
   /// \brief Creates clause with a list of variables \a VL.
@@ -867,11 +1075,16 @@ public:
   /// \param StartLoc Starting location of the clause.
   /// \param LParenLoc Location of '('.
   /// \param EndLoc Ending location of the clause.
-  /// \param VL List of references to the variables.
+  /// \param VL List of references to the original variables.
+  /// \param PrivateVL List of references to private copies with initializers.
+  /// \param InitVL List of references to auto generated variables used for
+  /// initialization of a single array element. Used if firstprivate variable is
+  /// of array type.
   ///
   static OMPFirstprivateClause *
   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
-         SourceLocation EndLoc, ArrayRef VL);
+         SourceLocation EndLoc, ArrayRef VL, ArrayRef PrivateVL,
+         ArrayRef InitVL);
   /// \brief Creates an empty clause with the place for \a N variables.
   ///
   /// \param C AST context.
@@ -879,6 +1092,33 @@ public:
   ///
   static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N);
 
+  typedef MutableArrayRef::iterator private_copies_iterator;
+  typedef ArrayRef::iterator private_copies_const_iterator;
+  typedef llvm::iterator_range private_copies_range;
+  typedef llvm::iterator_range
+      private_copies_const_range;
+
+  private_copies_range private_copies() {
+    return private_copies_range(getPrivateCopies().begin(),
+                                getPrivateCopies().end());
+  }
+  private_copies_const_range private_copies() const {
+    return private_copies_const_range(getPrivateCopies().begin(),
+                                      getPrivateCopies().end());
+  }
+
+  typedef MutableArrayRef::iterator inits_iterator;
+  typedef ArrayRef::iterator inits_const_iterator;
+  typedef llvm::iterator_range inits_range;
+  typedef llvm::iterator_range inits_const_range;
+
+  inits_range inits() {
+    return inits_range(getInits().begin(), getInits().end());
+  }
+  inits_const_range inits() const {
+    return inits_const_range(getInits().begin(), getInits().end());
+  }
+
   StmtRange children() {
     return StmtRange(reinterpret_cast(varlist_begin()),
                      reinterpret_cast(varlist_end()));
@@ -1390,13 +1630,17 @@ public:
   }
 };
 
-/// \brief This represents pseudo clause 'flush' for the '#pragma omp flush'
+/// \brief This represents implicit clause 'flush' for the '#pragma omp flush'
 /// directive.
+/// This clause does not exist by itself, it can be only as a part of 'omp
+/// flush' directive. This clause is introduced to keep the original structure
+/// of \a OMPExecutableDirective class and its derivatives and to use the
+/// existing infrastructure of clauses with the list of variables.
 ///
 /// \code
 /// #pragma omp flush(a,b)
 /// \endcode
-/// In this example directive '#pragma omp flush' has pseudo clause 'flush'
+/// In this example directive '#pragma omp flush' has implicit clause 'flush'
 /// with the variables 'a' and 'b'.
 ///
 class OMPFlushClause : public OMPVarListClause {
@@ -1453,3 +1697,4 @@ public:
 } // end namespace clang
 
 #endif
+
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index aba88d6..e3f0126 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H
-#define LLVM_CLANG_AST_OPERATION_KINDS_H
+#ifndef LLVM_CLANG_AST_OPERATIONKINDS_H
+#define LLVM_CLANG_AST_OPERATIONKINDS_H
 
 namespace clang {
   
diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h
index eece851..8945c41 100644
--- a/include/clang/AST/ParentMap.h
+++ b/include/clang/AST/ParentMap.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_PARENTMAP_H
-#define LLVM_CLANG_PARENTMAP_H
+#ifndef LLVM_CLANG_AST_PARENTMAP_H
+#define LLVM_CLANG_AST_PARENTMAP_H
 
 namespace clang {
 class Stmt;
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h
index 349f4c4..35ceabb 100644
--- a/include/clang/AST/PrettyPrinter.h
+++ b/include/clang/AST/PrettyPrinter.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H
-#define LLVM_CLANG_AST_PRETTY_PRINTER_H
+#ifndef LLVM_CLANG_AST_PRETTYPRINTER_H
+#define LLVM_CLANG_AST_PRETTYPRINTER_H
 
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h
index 8ba85c4..2e005dd 100644
--- a/include/clang/AST/RawCommentList.h
+++ b/include/clang/AST/RawCommentList.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H
-#define LLVM_CLANG_AST_RAW_COMMENT_LIST_H
+#ifndef LLVM_CLANG_AST_RAWCOMMENTLIST_H
+#define LLVM_CLANG_AST_RAWCOMMENTLIST_H
 
 #include "clang/Basic/CommentOptions.h"
 #include "clang/Basic/SourceManager.h"
diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h
index 4befb45..7b77998 100644
--- a/include/clang/AST/RecordLayout.h
+++ b/include/clang/AST/RecordLayout.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
-#define LLVM_CLANG_AST_LAYOUTINFO_H
+#ifndef LLVM_CLANG_AST_RECORDLAYOUT_H
+#define LLVM_CLANG_AST_RECORDLAYOUT_H
 
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclCXX.h"
diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h
index ff46ffb..a1d3618 100644
--- a/include/clang/AST/RecursiveASTVisitor.h
+++ b/include/clang/AST/RecursiveASTVisitor.h
@@ -429,6 +429,7 @@ private:
   bool TraverseFunctionHelper(FunctionDecl *D);
   bool TraverseVarHelper(VarDecl *D);
   bool TraverseOMPExecutableDirective(OMPExecutableDirective *S);
+  bool TraverseOMPLoopDirective(OMPLoopDirective *S);
   bool TraverseOMPClause(OMPClause *C);
 #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C);
 #include "clang/Basic/OpenMPKinds.def"
@@ -689,6 +690,7 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifier(
   case NestedNameSpecifier::Namespace:
   case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Super:
     return true;
 
   case NestedNameSpecifier::TypeSpec:
@@ -713,6 +715,7 @@ bool RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(
   case NestedNameSpecifier::Namespace:
   case NestedNameSpecifier::NamespaceAlias:
   case NestedNameSpecifier::Global:
+  case NestedNameSpecifier::Super:
     return true;
 
   case NestedNameSpecifier::TypeSpec:
@@ -940,6 +943,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
+
+  if (Expr *NE = T->getNoexceptExpr())
+    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPE(UnresolvedUsingType, {})
@@ -1148,6 +1154,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
   for (const auto &E : T->exceptions()) {
     TRY_TO(TraverseType(E));
   }
+
+  if (Expr *NE = T->getNoexceptExpr())
+    TRY_TO(TraverseStmt(NE));
 })
 
 DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {})
@@ -2144,21 +2153,29 @@ bool RecursiveASTVisitor::TraverseLambdaExpr(LambdaExpr *S) {
     TRY_TO(TraverseLambdaCapture(S, C));
   }
 
-  if (S->hasExplicitParameters() || S->hasExplicitResultType()) {
-    TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
-    if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
-      // Visit the whole type.
-      TRY_TO(TraverseTypeLoc(TL));
-    } else if (FunctionProtoTypeLoc Proto = TL.getAs()) {
-      if (S->hasExplicitParameters()) {
-        // Visit parameters.
-        for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
-          TRY_TO(TraverseDecl(Proto.getParam(I)));
-        }
-      } else {
-        TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+  TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+  FunctionProtoTypeLoc Proto = TL.castAs();
+
+  if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+    // Visit the whole type.
+    TRY_TO(TraverseTypeLoc(TL));
+  } else {
+    if (S->hasExplicitParameters()) {
+      // Visit parameters.
+      for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) {
+        TRY_TO(TraverseDecl(Proto.getParam(I)));
       }
+    } else if (S->hasExplicitResultType()) {
+      TRY_TO(TraverseTypeLoc(Proto.getReturnLoc()));
+    }
+
+    auto *T = Proto.getTypePtr();
+    for (const auto &E : T->exceptions()) {
+      TRY_TO(TraverseType(E));
     }
+
+    if (Expr *NE = T->getNoexceptExpr())
+      TRY_TO(TraverseStmt(NE));
   }
 
   TRY_TO(TraverseLambdaBody(S));
@@ -2259,6 +2276,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); })
 
 DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {})
 DEF_TRAVERSE_STMT(OpaqueValueExpr, {})
+DEF_TRAVERSE_STMT(TypoExpr, {})
 DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {})
 
 // These operators (all of them) do not need any action except
@@ -2275,6 +2293,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {})
 DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {})
 DEF_TRAVERSE_STMT(FunctionParmPackExpr, {})
 DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {})
+DEF_TRAVERSE_STMT(CXXFoldExpr, {})
 DEF_TRAVERSE_STMT(AtomicExpr, {})
 
 // These literals (all of them) do not need any action.
@@ -2301,6 +2320,12 @@ bool RecursiveASTVisitor::TraverseOMPExecutableDirective(
   return true;
 }
 
+template 
+bool
+RecursiveASTVisitor::TraverseOMPLoopDirective(OMPLoopDirective *S) {
+  return TraverseOMPExecutableDirective(S);
+}
+
 DEF_TRAVERSE_STMT(OMPParallelDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
@@ -2310,6 +2335,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective,
 DEF_TRAVERSE_STMT(OMPForDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPForSimdDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 DEF_TRAVERSE_STMT(OMPSectionsDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
@@ -2330,6 +2358,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, {
 DEF_TRAVERSE_STMT(OMPParallelForDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPParallelForSimdDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 DEF_TRAVERSE_STMT(OMPParallelSectionsDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
@@ -2348,6 +2379,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective,
 DEF_TRAVERSE_STMT(OMPFlushDirective,
                   { TRY_TO(TraverseOMPExecutableDirective(S)); })
 
+DEF_TRAVERSE_STMT(OMPOrderedDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPAtomicDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTargetDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
+DEF_TRAVERSE_STMT(OMPTeamsDirective,
+                  { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
 // OpenMP clauses.
 template 
 bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) {
@@ -2437,6 +2480,31 @@ RecursiveASTVisitor::VisitOMPMergeableClause(OMPMergeableClause *) {
 }
 
 template 
+bool RecursiveASTVisitor::VisitOMPReadClause(OMPReadClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPWriteClause(OMPWriteClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPUpdateClause(OMPUpdateClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPCaptureClause(OMPCaptureClause *) {
+  return true;
+}
+
+template 
+bool RecursiveASTVisitor::VisitOMPSeqCstClause(OMPSeqCstClause *) {
+  return true;
+}
+
+template 
 template 
 bool RecursiveASTVisitor::VisitOMPClauseList(T *Node) {
   for (auto *E : Node->varlists()) {
@@ -2448,6 +2516,9 @@ bool RecursiveASTVisitor::VisitOMPClauseList(T *Node) {
 template 
 bool RecursiveASTVisitor::VisitOMPPrivateClause(OMPPrivateClause *C) {
   TRY_TO(VisitOMPClauseList(C));
+  for (auto *E : C->private_copies()) {
+    TRY_TO(TraverseStmt(E));
+  }
   return true;
 }
 
@@ -2455,6 +2526,12 @@ template 
 bool RecursiveASTVisitor::VisitOMPFirstprivateClause(
     OMPFirstprivateClause *C) {
   TRY_TO(VisitOMPClauseList(C));
+  for (auto *E : C->private_copies()) {
+    TRY_TO(TraverseStmt(E));
+  }
+  for (auto *E : C->inits()) {
+    TRY_TO(TraverseStmt(E));
+  }
   return true;
 }
 
diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h
index fb94097..eb6836f 100644
--- a/include/clang/AST/Stmt.h
+++ b/include/clang/AST/Stmt.h
@@ -212,7 +212,7 @@ protected:
     unsigned HasTemplateKWAndArgsInfo : 1;
     unsigned HasFoundDecl : 1;
     unsigned HadMultipleCandidates : 1;
-    unsigned RefersToEnclosingLocal : 1;
+    unsigned RefersToEnclosingVariableOrCapture : 1;
   };
 
   class CastExprBitfields {
@@ -393,6 +393,10 @@ public:
   /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
   Stmt *IgnoreImplicit();
 
+  /// \brief Skip no-op (attributed, compound) container stmts and skip captured
+  /// stmt at the top, if \a IgnoreCaptured is true.
+  Stmt *IgnoreContainers(bool IgnoreCaptured = false);
+
   const Stmt *stripLabelLikeStatements() const;
   Stmt *stripLabelLikeStatements() {
     return const_cast(
@@ -548,14 +552,17 @@ public:
 ///
 class CompoundStmt : public Stmt {
   Stmt** Body;
-  SourceLocation LBracLoc, RBracLoc;
+  SourceLocation LBraceLoc, RBraceLoc;
+
+  friend class ASTStmtReader;
+
 public:
   CompoundStmt(const ASTContext &C, ArrayRef Stmts,
                SourceLocation LB, SourceLocation RB);
 
   // \brief Build an empty compound statement with a location.
   explicit CompoundStmt(SourceLocation Loc)
-    : Stmt(CompoundStmtClass), Body(nullptr), LBracLoc(Loc), RBracLoc(Loc) {
+    : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) {
     CompoundStmtBits.NumStmts = 0;
   }
 
@@ -614,13 +621,11 @@ public:
     return const_reverse_body_iterator(body_begin());
   }
 
-  SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; }
-  SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; }
+  SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; }
+  SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; }
 
-  SourceLocation getLBracLoc() const { return LBracLoc; }
-  void setLBracLoc(SourceLocation L) { LBracLoc = L; }
-  SourceLocation getRBracLoc() const { return RBracLoc; }
-  void setRBracLoc(SourceLocation L) { RBracLoc = L; }
+  SourceLocation getLBracLoc() const { return LBraceLoc; }
+  SourceLocation getRBracLoc() const { return RBraceLoc; }
 
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == CompoundStmtClass;
@@ -846,7 +851,7 @@ public:
 
   SourceLocation getAttrLoc() const { return AttrLoc; }
   ArrayRef getAttrs() const {
-    return ArrayRef(getAttrArrayPtr(), NumAttrs);
+    return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs);
   }
   Stmt *getSubStmt() { return SubStmt; }
   const Stmt *getSubStmt() const { return SubStmt; }
@@ -1010,7 +1015,7 @@ public:
 
   SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; }
   SourceLocation getLocEnd() const LLVM_READONLY {
-    return SubExprs[BODY]->getLocEnd();
+    return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd();
   }
 
   // Iterators
@@ -1580,18 +1585,21 @@ public:
     Kind MyKind;
     std::string Str;
     unsigned OperandNo;
+
+    // Source range for operand references.
+    CharSourceRange Range;
   public:
     AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {}
-    AsmStringPiece(unsigned OpNo, char Modifier)
-      : MyKind(Operand), Str(), OperandNo(OpNo) {
-      Str += Modifier;
+    AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin,
+                   SourceLocation End)
+      : MyKind(Operand), Str(S), OperandNo(OpNo),
+        Range(CharSourceRange::getCharRange(Begin, End)) {
     }
 
     bool isString() const { return MyKind == String; }
     bool isOperand() const { return MyKind == Operand; }
 
     const std::string &getString() const {
-      assert(isString());
       return Str;
     }
 
@@ -1600,12 +1608,14 @@ public:
       return OperandNo;
     }
 
+    CharSourceRange getRange() const {
+      assert(isOperand() && "Range is currently used only for Operands.");
+      return Range;
+    }
+
     /// getModifier - Get the modifier for this operand, if present.  This
     /// returns '\0' if there was no modifier.
-    char getModifier() const {
-      assert(isOperand());
-      return Str[0];
-    }
+    char getModifier() const;
   };
 
   /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
@@ -1780,14 +1790,14 @@ public:
   //===--- Other ---===//
 
   ArrayRef getAllConstraints() const {
-    return ArrayRef(Constraints, NumInputs + NumOutputs);
+    return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs);
   }
   ArrayRef getClobbers() const {
-    return ArrayRef(Clobbers, NumClobbers);
+    return llvm::makeArrayRef(Clobbers, NumClobbers);
   }
   ArrayRef getAllExprs() const {
-    return ArrayRef(reinterpret_cast(Exprs),
-                           NumInputs + NumOutputs);
+    return llvm::makeArrayRef(reinterpret_cast(Exprs),
+                              NumInputs + NumOutputs);
   }
 
   StringRef getClobber(unsigned i) const { return getClobbers()[i]; }
@@ -1892,24 +1902,22 @@ class SEHTryStmt : public Stmt {
   bool            IsCXXTry;
   SourceLocation  TryLoc;
   Stmt           *Children[2];
-  int             HandlerIndex;
-  int             HandlerParentIndex;
 
   enum { TRY = 0, HANDLER = 1 };
 
   SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try'
-             SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler,
-             int HandlerIndex, int HandlerParentIndex);
+             SourceLocation TryLoc,
+             Stmt *TryBlock,
+             Stmt *Handler);
 
   friend class ASTReader;
   friend class ASTStmtReader;
   explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { }
 
 public:
-  static SEHTryStmt *Create(const ASTContext &C, bool isCXXTry,
+  static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry,
                             SourceLocation TryLoc, Stmt *TryBlock,
-                            Stmt *Handler, int HandlerIndex,
-                            int HandlerParentIndex);
+                            Stmt *Handler);
 
   SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); }
   SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); }
@@ -1936,9 +1944,6 @@ public:
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == SEHTryStmtClass;
   }
-
-  int getHandlerIndex() const { return HandlerIndex; }
-  int getHandlerParentIndex() const { return HandlerParentIndex; }
 };
 
 /// Represents a __leave statement.
@@ -1977,15 +1982,18 @@ public:
 /// @endcode
 class CapturedStmt : public Stmt {
 public:
-  /// \brief The different capture forms: by 'this' or by reference, etc.
+  /// \brief The different capture forms: by 'this', by reference, capture for
+  /// variable-length array type etc.
   enum VariableCaptureKind {
     VCK_This,
-    VCK_ByRef
+    VCK_ByRef,
+    VCK_VLAType,
   };
 
-  /// \brief Describes the capture of either a variable or 'this'.
+  /// \brief Describes the capture of either a variable, or 'this', or
+  /// variable-length array type.
   class Capture {
-    llvm::PointerIntPair VarAndKind;
+    llvm::PointerIntPair VarAndKind;
     SourceLocation Loc;
 
   public:
@@ -2007,6 +2015,10 @@ public:
       case VCK_ByRef:
         assert(Var && "capturing by reference must have a variable!");
         break;
+      case VCK_VLAType:
+        assert(!Var &&
+               "Variable-length array type capture cannot have a variable!");
+        break;
       }
     }
 
@@ -2021,13 +2033,20 @@ public:
     bool capturesThis() const { return getCaptureKind() == VCK_This; }
 
     /// \brief Determine whether this capture handles a variable.
-    bool capturesVariable() const { return getCaptureKind() != VCK_This; }
+    bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; }
+
+    /// \brief Determine whether this capture handles a variable-length array
+    /// type.
+    bool capturesVariableArrayType() const {
+      return getCaptureKind() == VCK_VLAType;
+    }
 
     /// \brief Retrieve the declaration of the variable being captured.
     ///
-    /// This operation is only valid if this capture does not capture 'this'.
+    /// This operation is only valid if this capture captures a variable.
     VarDecl *getCapturedVar() const {
-      assert(!capturesThis() && "No variable available for 'this' capture");
+      assert(capturesVariable() &&
+             "No variable available for 'this' or VAT capture");
       return VarAndKind.getPointer();
     }
     friend class ASTStmtReader;
diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h
index a3e9e1e..ab636a5 100644
--- a/include/clang/AST/StmtGraphTraits.h
+++ b/include/clang/AST/StmtGraphTraits.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
-#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H
+#ifndef LLVM_CLANG_AST_STMTGRAPHTRAITS_H
+#define LLVM_CLANG_AST_STMTGRAPHTRAITS_H
 
 #include "clang/AST/Stmt.h"
 #include "llvm/ADT/DepthFirstIterator.h"
diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h
index 18c5516..6ffe74f 100644
--- a/include/clang/AST/StmtIterator.h
+++ b/include/clang/AST/StmtIterator.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_STMT_ITR_H
-#define LLVM_CLANG_AST_STMT_ITR_H
+#ifndef LLVM_CLANG_AST_STMTITERATOR_H
+#define LLVM_CLANG_AST_STMTITERATOR_H
 
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataTypes.h"
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index db02afe0..aed7691 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -128,6 +128,13 @@ public:
     operator bool() { return Current != End; }
   };
 
+  /// \brief Gets a single clause of the specified kind \a K associated with the
+  /// current directive iff there is only one clause of this kind (and assertion
+  /// is fired if there is more than one clause is associated with the
+  /// directive). Returns nullptr if no clause of kind \a K is associated with
+  /// the directive.
+  const OMPClause *getSingleClause(OpenMPClauseKind K) const;
+
   /// \brief Returns starting location of directive kind.
   SourceLocation getLocStart() const { return StartLoc; }
   /// \brief Returns ending location of directive.
@@ -238,6 +245,353 @@ public:
   }
 };
 
+/// \brief This is a common base class for loop directives ('omp simd', 'omp
+/// for', 'omp for simd' etc.). It is responsible for the loop code generation.
+///
+class OMPLoopDirective : public OMPExecutableDirective {
+  friend class ASTStmtReader;
+  /// \brief Number of collapsed loops as specified by 'collapse' clause.
+  unsigned CollapsedNum;
+
+  /// \brief Offsets to the stored exprs.
+  /// This enumeration contains offsets to all the pointers to children
+  /// expressions stored in OMPLoopDirective.
+  /// The first 9 children are nesessary for all the loop directives, and
+  /// the next 7 are specific to the worksharing ones.
+  /// After the fixed children, three arrays of length CollapsedNum are
+  /// allocated: loop counters, their updates and final values.
+  ///
+  enum {
+    AssociatedStmtOffset = 0,
+    IterationVariableOffset = 1,
+    LastIterationOffset = 2,
+    CalcLastIterationOffset = 3,
+    PreConditionOffset = 4,
+    CondOffset = 5,
+    SeparatedCondOffset = 6,
+    InitOffset = 7,
+    IncOffset = 8,
+    // The '...End' enumerators do not correspond to child expressions - they
+    // specify the offset to the end (and start of the following counters/
+    // updates/finals arrays).
+    DefaultEnd = 9,
+    // The following 7 exprs are used by worksharing loops only.
+    IsLastIterVariableOffset = 9,
+    LowerBoundVariableOffset = 10,
+    UpperBoundVariableOffset = 11,
+    StrideVariableOffset = 12,
+    EnsureUpperBoundOffset = 13,
+    NextLowerBoundOffset = 14,
+    NextUpperBoundOffset = 15,
+    // Offset to the end (and start of the following counters/updates/finals
+    // arrays) for worksharing loop directives.
+    WorksharingEnd = 16,
+  };
+
+  /// \brief Get the counters storage.
+  MutableArrayRef getCounters() {
+    Expr **Storage = reinterpret_cast(
+        &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind())))));
+    return MutableArrayRef(Storage, CollapsedNum);
+  }
+
+  /// \brief Get the updates storage.
+  MutableArrayRef getUpdates() {
+    Expr **Storage = reinterpret_cast(
+        &*std::next(child_begin(),
+                    getArraysOffset(getDirectiveKind()) + CollapsedNum));
+    return MutableArrayRef(Storage, CollapsedNum);
+  }
+
+  /// \brief Get the final counter updates storage.
+  MutableArrayRef getFinals() {
+    Expr **Storage = reinterpret_cast(
+        &*std::next(child_begin(),
+                    getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum));
+    return MutableArrayRef(Storage, CollapsedNum);
+  }
+
+protected:
+  /// \brief Build instance of loop directive of class \a Kind.
+  ///
+  /// \param SC Statement class.
+  /// \param Kind Kind of OpenMP directive.
+  /// \param StartLoc Starting location of the directive (directive keyword).
+  /// \param EndLoc Ending location of the directive.
+  /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
+  /// \param NumClauses Number of clauses.
+  /// \param NumSpecialChildren Number of additional directive-specific stmts.
+  ///
+  template 
+  OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind,
+                   SourceLocation StartLoc, SourceLocation EndLoc,
+                   unsigned CollapsedNum, unsigned NumClauses,
+                   unsigned NumSpecialChildren = 0)
+      : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses,
+                               numLoopChildren(CollapsedNum, Kind) +
+                                   NumSpecialChildren),
+        CollapsedNum(CollapsedNum) {}
+
+  /// \brief Offset to the start of children expression arrays.
+  static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
+    return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd
+                                              : DefaultEnd;
+  }
+
+  /// \brief Children number.
+  static unsigned numLoopChildren(unsigned CollapsedNum,
+                                  OpenMPDirectiveKind Kind) {
+    return getArraysOffset(Kind) +
+           3 * CollapsedNum; // Counters, Updates and Finals
+  }
+
+  void setIterationVariable(Expr *IV) {
+    *std::next(child_begin(), IterationVariableOffset) = IV;
+  }
+  void setLastIteration(Expr *LI) {
+    *std::next(child_begin(), LastIterationOffset) = LI;
+  }
+  void setCalcLastIteration(Expr *CLI) {
+    *std::next(child_begin(), CalcLastIterationOffset) = CLI;
+  }
+  void setPreCond(Expr *PC) {
+    *std::next(child_begin(), PreConditionOffset) = PC;
+  }
+  void setCond(Expr *Cond, Expr *SeparatedCond) {
+    *std::next(child_begin(), CondOffset) = Cond;
+    *std::next(child_begin(), SeparatedCondOffset) = SeparatedCond;
+  }
+  void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; }
+  void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; }
+  void setIsLastIterVariable(Expr *IL) {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    *std::next(child_begin(), IsLastIterVariableOffset) = IL;
+  }
+  void setLowerBoundVariable(Expr *LB) {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    *std::next(child_begin(), LowerBoundVariableOffset) = LB;
+  }
+  void setUpperBoundVariable(Expr *UB) {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    *std::next(child_begin(), UpperBoundVariableOffset) = UB;
+  }
+  void setStrideVariable(Expr *ST) {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    *std::next(child_begin(), StrideVariableOffset) = ST;
+  }
+  void setEnsureUpperBound(Expr *EUB) {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    *std::next(child_begin(), EnsureUpperBoundOffset) = EUB;
+  }
+  void setNextLowerBound(Expr *NLB) {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    *std::next(child_begin(), NextLowerBoundOffset) = NLB;
+  }
+  void setNextUpperBound(Expr *NUB) {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    *std::next(child_begin(), NextUpperBoundOffset) = NUB;
+  }
+  void setCounters(ArrayRef A);
+  void setUpdates(ArrayRef A);
+  void setFinals(ArrayRef A);
+
+public:
+  /// \brief The expressions built for the OpenMP loop CodeGen for the
+  /// whole collapsed loop nest.
+  struct HelperExprs {
+    /// \brief Loop iteration variable.
+    Expr *IterationVarRef;
+    /// \brief Loop last iteration number.
+    Expr *LastIteration;
+    /// \brief Calculation of last iteration.
+    Expr *CalcLastIteration;
+    /// \brief Loop pre-condition.
+    Expr *PreCond;
+    /// \brief Loop condition.
+    Expr *Cond;
+    /// \brief A condition with 1 iteration separated.
+    Expr *SeparatedCond;
+    /// \brief Loop iteration variable init.
+    Expr *Init;
+    /// \brief Loop increment.
+    Expr *Inc;
+    /// \brief IsLastIteration - local flag variable passed to runtime.
+    Expr *IL;
+    /// \brief LowerBound - local variable passed to runtime.
+    Expr *LB;
+    /// \brief UpperBound - local variable passed to runtime.
+    Expr *UB;
+    /// \brief Stride - local variable passed to runtime.
+    Expr *ST;
+    /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations).
+    Expr *EUB;
+    /// \brief Update of LowerBound for statically sheduled 'omp for' loops.
+    Expr *NLB;
+    /// \brief Update of UpperBound for statically sheduled 'omp for' loops.
+    Expr *NUB;
+    /// \brief Counters Loop counters.
+    SmallVector Counters;
+    /// \brief Expressions for loop counters update for CodeGen.
+    SmallVector Updates;
+    /// \brief Final loop counter values for GodeGen.
+    SmallVector Finals;
+
+    /// \brief Check if all the expressions are built (does not check the
+    /// worksharing ones).
+    bool builtAll() {
+      return IterationVarRef != nullptr && LastIteration != nullptr &&
+             PreCond != nullptr && Cond != nullptr &&
+             SeparatedCond != nullptr && Init != nullptr && Inc != nullptr;
+    }
+
+    /// \brief Initialize all the fields to null.
+    /// \param Size Number of elements in the counters/finals/updates arrays.
+    void clear(unsigned Size) {
+      IterationVarRef = nullptr;
+      LastIteration = nullptr;
+      CalcLastIteration = nullptr;
+      PreCond = nullptr;
+      Cond = nullptr;
+      SeparatedCond = nullptr;
+      Init = nullptr;
+      Inc = nullptr;
+      IL = nullptr;
+      LB = nullptr;
+      UB = nullptr;
+      ST = nullptr;
+      EUB = nullptr;
+      NLB = nullptr;
+      NUB = nullptr;
+      Counters.resize(Size);
+      Updates.resize(Size);
+      Finals.resize(Size);
+      for (unsigned i = 0; i < Size; ++i) {
+        Counters[i] = nullptr;
+        Updates[i] = nullptr;
+        Finals[i] = nullptr;
+      }
+    }
+  };
+
+  /// \brief Get number of collapsed loops.
+  unsigned getCollapsedNumber() const { return CollapsedNum; }
+
+  Expr *getIterationVariable() const {
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), IterationVariableOffset)));
+  }
+  Expr *getLastIteration() const {
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), LastIterationOffset)));
+  }
+  Expr *getCalcLastIteration() const {
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), CalcLastIterationOffset)));
+  }
+  Expr *getPreCond() const {
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), PreConditionOffset)));
+  }
+  Expr *getCond(bool SeparateIter) const {
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(),
+                   (SeparateIter ? SeparatedCondOffset : CondOffset))));
+  }
+  Expr *getInit() const {
+    return const_cast(
+        reinterpret_cast(*std::next(child_begin(), InitOffset)));
+  }
+  Expr *getInc() const {
+    return const_cast(
+        reinterpret_cast(*std::next(child_begin(), IncOffset)));
+  }
+  Expr *getIsLastIterVariable() const {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), IsLastIterVariableOffset)));
+  }
+  Expr *getLowerBoundVariable() const {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), LowerBoundVariableOffset)));
+  }
+  Expr *getUpperBoundVariable() const {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), UpperBoundVariableOffset)));
+  }
+  Expr *getStrideVariable() const {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), StrideVariableOffset)));
+  }
+  Expr *getEnsureUpperBound() const {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), EnsureUpperBoundOffset)));
+  }
+  Expr *getNextLowerBound() const {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), NextLowerBoundOffset)));
+  }
+  Expr *getNextUpperBound() const {
+    assert(isOpenMPWorksharingDirective(getDirectiveKind()) &&
+           "expected worksharing loop directive");
+    return const_cast(reinterpret_cast(
+        *std::next(child_begin(), NextUpperBoundOffset)));
+  }
+  const Stmt *getBody() const {
+    // This relies on the loop form is already checked by Sema.
+    Stmt *Body = getAssociatedStmt()->IgnoreContainers(true);
+    Body = cast(Body)->getBody();
+    for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
+      Body = Body->IgnoreContainers();
+      Body = cast(Body)->getBody();
+    }
+    return Body;
+  }
+
+  ArrayRef counters() { return getCounters(); }
+
+  ArrayRef counters() const {
+    return const_cast(this)->getCounters();
+  }
+
+  ArrayRef updates() { return getUpdates(); }
+
+  ArrayRef updates() const {
+    return const_cast(this)->getUpdates();
+  }
+
+  ArrayRef finals() { return getFinals(); }
+
+  ArrayRef finals() const {
+    return const_cast(this)->getFinals();
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPSimdDirectiveClass ||
+           T->getStmtClass() == OMPForDirectiveClass ||
+           T->getStmtClass() == OMPForSimdDirectiveClass ||
+           T->getStmtClass() == OMPParallelForDirectiveClass ||
+           T->getStmtClass() == OMPParallelForSimdDirectiveClass;
+  }
+};
+
 /// \brief This represents '#pragma omp simd' directive.
 ///
 /// \code
@@ -247,10 +601,8 @@ public:
 /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
 /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
 ///
-class OMPSimdDirective : public OMPExecutableDirective {
+class OMPSimdDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
-  /// \brief Number of collapsed loops as specified by 'collapse' clause.
-  unsigned CollapsedNum;
   /// \brief Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
@@ -260,9 +612,8 @@ class OMPSimdDirective : public OMPExecutableDirective {
   ///
   OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
                    unsigned CollapsedNum, unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc,
-                               EndLoc, NumClauses, 1),
-        CollapsedNum(CollapsedNum) {}
+      : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc,
+                         EndLoc, CollapsedNum, NumClauses) {}
 
   /// \brief Build an empty directive.
   ///
@@ -270,10 +621,9 @@ class OMPSimdDirective : public OMPExecutableDirective {
   /// \param NumClauses Number of clauses.
   ///
   explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd,
-                               SourceLocation(), SourceLocation(), NumClauses,
-                               1),
-        CollapsedNum(CollapsedNum) {}
+      : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd,
+                         SourceLocation(), SourceLocation(), CollapsedNum,
+                         NumClauses) {}
 
 public:
   /// \brief Creates directive with a list of \a Clauses.
@@ -284,11 +634,13 @@ public:
   /// \param CollapsedNum Number of collapsed loops.
   /// \param Clauses List of clauses.
   /// \param AssociatedStmt Statement, associated with the directive.
+  /// \param Exprs Helper expressions for CodeGen.
   ///
   static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
                                   SourceLocation EndLoc, unsigned CollapsedNum,
                                   ArrayRef Clauses,
-                                  Stmt *AssociatedStmt);
+                                  Stmt *AssociatedStmt,
+                                  const HelperExprs &Exprs);
 
   /// \brief Creates an empty directive with the place
   /// for \a NumClauses clauses.
@@ -300,8 +652,6 @@ public:
   static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                        unsigned CollapsedNum, EmptyShell);
 
-  unsigned getCollapsedNumber() const { return CollapsedNum; }
-
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPSimdDirectiveClass;
   }
@@ -316,10 +666,8 @@ public:
 /// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c'
 /// and 'd'.
 ///
-class OMPForDirective : public OMPExecutableDirective {
+class OMPForDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
-  /// \brief Number of collapsed loops as specified by 'collapse' clause.
-  unsigned CollapsedNum;
   /// \brief Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
@@ -329,9 +677,8 @@ class OMPForDirective : public OMPExecutableDirective {
   ///
   OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
                   unsigned CollapsedNum, unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc,
-                               EndLoc, NumClauses, 1),
-        CollapsedNum(CollapsedNum) {}
+      : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc,
+                         CollapsedNum, NumClauses) {}
 
   /// \brief Build an empty directive.
   ///
@@ -339,10 +686,8 @@ class OMPForDirective : public OMPExecutableDirective {
   /// \param NumClauses Number of clauses.
   ///
   explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for,
-                               SourceLocation(), SourceLocation(), NumClauses,
-                               1),
-        CollapsedNum(CollapsedNum) {}
+      : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(),
+                         SourceLocation(), CollapsedNum, NumClauses) {}
 
 public:
   /// \brief Creates directive with a list of \a Clauses.
@@ -353,11 +698,13 @@ public:
   /// \param CollapsedNum Number of collapsed loops.
   /// \param Clauses List of clauses.
   /// \param AssociatedStmt Statement, associated with the directive.
+  /// \param Exprs Helper expressions for CodeGen.
   ///
   static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
                                  SourceLocation EndLoc, unsigned CollapsedNum,
                                  ArrayRef Clauses,
-                                 Stmt *AssociatedStmt);
+                                 Stmt *AssociatedStmt,
+                                 const HelperExprs &Exprs);
 
   /// \brief Creates an empty directive with the place
   /// for \a NumClauses clauses.
@@ -369,13 +716,76 @@ public:
   static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
                                       unsigned CollapsedNum, EmptyShell);
 
-  unsigned getCollapsedNumber() const { return CollapsedNum; }
-
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPForDirectiveClass;
   }
 };
 
+/// \brief This represents '#pragma omp for simd' directive.
+///
+/// \code
+/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp for simd' has clauses 'private'
+/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
+/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
+///
+class OMPForSimdDirective : public OMPLoopDirective {
+  friend class ASTStmtReader;
+  /// \brief Build directive with the given start and end location.
+  ///
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending location of the directive.
+  /// \param CollapsedNum Number of collapsed nested loops.
+  /// \param NumClauses Number of clauses.
+  ///
+  OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+                      unsigned CollapsedNum, unsigned NumClauses)
+      : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd,
+                         StartLoc, EndLoc, CollapsedNum, NumClauses) {}
+
+  /// \brief Build an empty directive.
+  ///
+  /// \param CollapsedNum Number of collapsed nested loops.
+  /// \param NumClauses Number of clauses.
+  ///
+  explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses)
+      : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd,
+                         SourceLocation(), SourceLocation(), CollapsedNum,
+                         NumClauses) {}
+
+public:
+  /// \brief Creates directive with a list of \a Clauses.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending Location of the directive.
+  /// \param CollapsedNum Number of collapsed loops.
+  /// \param Clauses List of clauses.
+  /// \param AssociatedStmt Statement, associated with the directive.
+  /// \param Exprs Helper expressions for CodeGen.
+  ///
+  static OMPForSimdDirective *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+         unsigned CollapsedNum, ArrayRef Clauses,
+         Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+  /// \brief Creates an empty directive with the place
+  /// for \a NumClauses clauses.
+  ///
+  /// \param C AST context.
+  /// \param CollapsedNum Number of collapsed nested loops.
+  /// \param NumClauses Number of clauses.
+  ///
+  static OMPForSimdDirective *CreateEmpty(const ASTContext &C,
+                                          unsigned NumClauses,
+                                          unsigned CollapsedNum, EmptyShell);
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPForSimdDirectiveClass;
+  }
+};
+
 /// \brief This represents '#pragma omp sections' directive.
 ///
 /// \code
@@ -657,10 +1067,8 @@ public:
 /// with the variables 'a' and 'b' and 'reduction' with operator '+' and
 /// variables 'c' and 'd'.
 ///
-class OMPParallelForDirective : public OMPExecutableDirective {
+class OMPParallelForDirective : public OMPLoopDirective {
   friend class ASTStmtReader;
-  /// \brief Number of collapsed loops as specified by 'collapse' clause.
-  unsigned CollapsedNum;
   /// \brief Build directive with the given start and end location.
   ///
   /// \param StartLoc Starting location of the directive kind.
@@ -670,10 +1078,8 @@ class OMPParallelForDirective : public OMPExecutableDirective {
   ///
   OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
                           unsigned CollapsedNum, unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelForDirectiveClass,
-                               OMPD_parallel_for, StartLoc, EndLoc, NumClauses,
-                               1),
-        CollapsedNum(CollapsedNum) {}
+      : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
+                         StartLoc, EndLoc, CollapsedNum, NumClauses) {}
 
   /// \brief Build an empty directive.
   ///
@@ -681,10 +1087,9 @@ class OMPParallelForDirective : public OMPExecutableDirective {
   /// \param NumClauses Number of clauses.
   ///
   explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses)
-      : OMPExecutableDirective(this, OMPParallelForDirectiveClass,
-                               OMPD_parallel_for, SourceLocation(),
-                               SourceLocation(), NumClauses, 1),
-        CollapsedNum(CollapsedNum) {}
+      : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for,
+                         SourceLocation(), SourceLocation(), CollapsedNum,
+                         NumClauses) {}
 
 public:
   /// \brief Creates directive with a list of \a Clauses.
@@ -695,11 +1100,12 @@ public:
   /// \param CollapsedNum Number of collapsed loops.
   /// \param Clauses List of clauses.
   /// \param AssociatedStmt Statement, associated with the directive.
+  /// \param Exprs Helper expressions for CodeGen.
   ///
   static OMPParallelForDirective *
   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
          unsigned CollapsedNum, ArrayRef Clauses,
-         Stmt *AssociatedStmt);
+         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
   /// \brief Creates an empty directive with the place
   /// for \a NumClauses clauses.
@@ -713,13 +1119,80 @@ public:
                                               unsigned CollapsedNum,
                                               EmptyShell);
 
-  unsigned getCollapsedNumber() const { return CollapsedNum; }
-
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == OMPParallelForDirectiveClass;
   }
 };
 
+/// \brief This represents '#pragma omp parallel for simd' directive.
+///
+/// \code
+/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
+/// \endcode
+/// In this example directive '#pragma omp parallel for simd' has clauses
+/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j'
+/// and linear step 's', 'reduction' with operator '+' and variables 'c' and
+/// 'd'.
+///
+class OMPParallelForSimdDirective : public OMPLoopDirective {
+  friend class ASTStmtReader;
+  /// \brief Build directive with the given start and end location.
+  ///
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending location of the directive.
+  /// \param CollapsedNum Number of collapsed nested loops.
+  /// \param NumClauses Number of clauses.
+  ///
+  OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+                              unsigned CollapsedNum, unsigned NumClauses)
+      : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+                         OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum,
+                         NumClauses) {}
+
+  /// \brief Build an empty directive.
+  ///
+  /// \param CollapsedNum Number of collapsed nested loops.
+  /// \param NumClauses Number of clauses.
+  ///
+  explicit OMPParallelForSimdDirective(unsigned CollapsedNum,
+                                       unsigned NumClauses)
+      : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass,
+                         OMPD_parallel_for_simd, SourceLocation(),
+                         SourceLocation(), CollapsedNum, NumClauses) {}
+
+public:
+  /// \brief Creates directive with a list of \a Clauses.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending Location of the directive.
+  /// \param CollapsedNum Number of collapsed loops.
+  /// \param Clauses List of clauses.
+  /// \param AssociatedStmt Statement, associated with the directive.
+  /// \param Exprs Helper expressions for CodeGen.
+  ///
+  static OMPParallelForSimdDirective *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+         unsigned CollapsedNum, ArrayRef Clauses,
+         Stmt *AssociatedStmt, const HelperExprs &Exprs);
+
+  /// \brief Creates an empty directive with the place
+  /// for \a NumClauses clauses.
+  ///
+  /// \param C AST context.
+  /// \param CollapsedNum Number of collapsed nested loops.
+  /// \param NumClauses Number of clauses.
+  ///
+  static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C,
+                                                  unsigned NumClauses,
+                                                  unsigned CollapsedNum,
+                                                  EmptyShell);
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPParallelForSimdDirectiveClass;
+  }
+};
+
 /// \brief This represents '#pragma omp parallel sections' directive.
 ///
 /// \code
@@ -1028,6 +1501,253 @@ public:
   }
 };
 
+/// \brief This represents '#pragma omp ordered' directive.
+///
+/// \code
+/// #pragma omp ordered
+/// \endcode
+///
+class OMPOrderedDirective : public OMPExecutableDirective {
+  friend class ASTStmtReader;
+  /// \brief Build directive with the given start and end location.
+  ///
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending location of the directive.
+  ///
+  OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+      : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
+                               StartLoc, EndLoc, 0, 1) {}
+
+  /// \brief Build an empty directive.
+  ///
+  explicit OMPOrderedDirective()
+      : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered,
+                               SourceLocation(), SourceLocation(), 0, 1) {}
+
+public:
+  /// \brief Creates directive.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending Location of the directive.
+  /// \param AssociatedStmt Statement, associated with the directive.
+  ///
+  static OMPOrderedDirective *Create(const ASTContext &C,
+                                     SourceLocation StartLoc,
+                                     SourceLocation EndLoc,
+                                     Stmt *AssociatedStmt);
+
+  /// \brief Creates an empty directive.
+  ///
+  /// \param C AST context.
+  ///
+  static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell);
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPOrderedDirectiveClass;
+  }
+};
+
+/// \brief This represents '#pragma omp atomic' directive.
+///
+/// \code
+/// #pragma omp atomic capture
+/// \endcode
+/// In this example directive '#pragma omp atomic' has clause 'capture'.
+///
+class OMPAtomicDirective : public OMPExecutableDirective {
+  friend class ASTStmtReader;
+  /// \brief Build directive with the given start and end location.
+  ///
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending location of the directive.
+  /// \param NumClauses Number of clauses.
+  ///
+  OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+                     unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
+                               StartLoc, EndLoc, NumClauses, 4) {}
+
+  /// \brief Build an empty directive.
+  ///
+  /// \param NumClauses Number of clauses.
+  ///
+  explicit OMPAtomicDirective(unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic,
+                               SourceLocation(), SourceLocation(), NumClauses,
+                               4) {}
+
+  /// \brief Set 'x' part of the associated expression/statement.
+  void setX(Expr *X) { *std::next(child_begin()) = X; }
+  /// \brief Set 'v' part of the associated expression/statement.
+  void setV(Expr *V) { *std::next(child_begin(), 2) = V; }
+  /// \brief Set 'expr' part of the associated expression/statement.
+  void setExpr(Expr *E) { *std::next(child_begin(), 3) = E; }
+
+public:
+  /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
+  /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
+  /// detailed description of 'x', 'v' and 'expr').
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending Location of the directive.
+  /// \param Clauses List of clauses.
+  /// \param AssociatedStmt Statement, associated with the directive.
+  /// \param X 'x' part of the associated expression/statement.
+  /// \param V 'v' part of the associated expression/statement.
+  /// \param E 'expr' part of the associated expression/statement.
+  ///
+  static OMPAtomicDirective *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+         ArrayRef Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
+         Expr *E);
+
+  /// \brief Creates an empty directive with the place for \a NumClauses
+  /// clauses.
+  ///
+  /// \param C AST context.
+  /// \param NumClauses Number of clauses.
+  ///
+  static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
+                                         unsigned NumClauses, EmptyShell);
+
+  /// \brief Get 'x' part of the associated expression/statement.
+  Expr *getX() { return cast_or_null(*std::next(child_begin())); }
+  const Expr *getX() const {
+    return cast_or_null(*std::next(child_begin()));
+  }
+  /// \brief Get 'v' part of the associated expression/statement.
+  Expr *getV() { return cast_or_null(*std::next(child_begin(), 2)); }
+  const Expr *getV() const {
+    return cast_or_null(*std::next(child_begin(), 2));
+  }
+  /// \brief Get 'expr' part of the associated expression/statement.
+  Expr *getExpr() { return cast_or_null(*std::next(child_begin(), 3)); }
+  const Expr *getExpr() const {
+    return cast_or_null(*std::next(child_begin(), 3));
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPAtomicDirectiveClass;
+  }
+};
+
+/// \brief This represents '#pragma omp target' directive.
+///
+/// \code
+/// #pragma omp target if(a)
+/// \endcode
+/// In this example directive '#pragma omp target' has clause 'if' with
+/// condition 'a'.
+///
+class OMPTargetDirective : public OMPExecutableDirective {
+  friend class ASTStmtReader;
+  /// \brief Build directive with the given start and end location.
+  ///
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending location of the directive.
+  /// \param NumClauses Number of clauses.
+  ///
+  OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+                     unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target,
+                               StartLoc, EndLoc, NumClauses, 1) {}
+
+  /// \brief Build an empty directive.
+  ///
+  /// \param NumClauses Number of clauses.
+  ///
+  explicit OMPTargetDirective(unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target,
+                               SourceLocation(), SourceLocation(), NumClauses,
+                               1) {}
+
+public:
+  /// \brief Creates directive with a list of \a Clauses.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending Location of the directive.
+  /// \param Clauses List of clauses.
+  /// \param AssociatedStmt Statement, associated with the directive.
+  ///
+  static OMPTargetDirective *
+  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+         ArrayRef Clauses, Stmt *AssociatedStmt);
+
+  /// \brief Creates an empty directive with the place for \a NumClauses
+  /// clauses.
+  ///
+  /// \param C AST context.
+  /// \param NumClauses Number of clauses.
+  ///
+  static OMPTargetDirective *CreateEmpty(const ASTContext &C,
+                                         unsigned NumClauses, EmptyShell);
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPTargetDirectiveClass;
+  }
+};
+
+/// \brief This represents '#pragma omp teams' directive.
+///
+/// \code
+/// #pragma omp teams if(a)
+/// \endcode
+/// In this example directive '#pragma omp teams' has clause 'if' with
+/// condition 'a'.
+///
+class OMPTeamsDirective : public OMPExecutableDirective {
+  friend class ASTStmtReader;
+  /// \brief Build directive with the given start and end location.
+  ///
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending location of the directive.
+  /// \param NumClauses Number of clauses.
+  ///
+  OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+                    unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams,
+                               StartLoc, EndLoc, NumClauses, 1) {}
+
+  /// \brief Build an empty directive.
+  ///
+  /// \param NumClauses Number of clauses.
+  ///
+  explicit OMPTeamsDirective(unsigned NumClauses)
+      : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams,
+                               SourceLocation(), SourceLocation(), NumClauses,
+                               1) {}
+
+public:
+  /// \brief Creates directive with a list of \a Clauses.
+  ///
+  /// \param C AST context.
+  /// \param StartLoc Starting location of the directive kind.
+  /// \param EndLoc Ending Location of the directive.
+  /// \param Clauses List of clauses.
+  /// \param AssociatedStmt Statement, associated with the directive.
+  ///
+  static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc,
+                                   SourceLocation EndLoc,
+                                   ArrayRef Clauses,
+                                   Stmt *AssociatedStmt);
+
+  /// \brief Creates an empty directive with the place for \a NumClauses
+  /// clauses.
+  ///
+  /// \param C AST context.
+  /// \param NumClauses Number of clauses.
+  ///
+  static OMPTeamsDirective *CreateEmpty(const ASTContext &C,
+                                        unsigned NumClauses, EmptyShell);
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == OMPTeamsDirectiveClass;
+  }
+};
+
 } // end namespace clang
 
 #endif
diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h
index 1026a78..80b68bc 100644
--- a/include/clang/AST/TemplateBase.h
+++ b/include/clang/AST/TemplateBase.h
@@ -18,8 +18,8 @@
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
 #include "llvm/ADT/APSInt.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 
@@ -76,7 +76,7 @@ private:
 
   struct DA {
     unsigned Kind;
-    bool ForRefParam;
+    void *QT;
     ValueDecl *D;
   };
   struct I {
@@ -132,11 +132,11 @@ public:
   /// \brief Construct a template argument that refers to a
   /// declaration, which is either an external declaration or a
   /// template declaration.
-  TemplateArgument(ValueDecl *D, bool ForRefParam) {
+  TemplateArgument(ValueDecl *D, QualType QT) {
     assert(D && "Expected decl");
     DeclArg.Kind = Declaration;
+    DeclArg.QT = QT.getAsOpaquePtr();
     DeclArg.D = D;
-    DeclArg.ForRefParam = ForRefParam;
   }
 
   /// \brief Construct an integral constant template argument. The memory to
@@ -249,11 +249,9 @@ public:
     return DeclArg.D;
   }
 
-  /// \brief Retrieve whether a declaration is binding to a
-  /// reference parameter in a declaration non-type template argument.
-  bool isDeclForReferenceParam() const {
+  QualType getParamTypeForDecl() const {
     assert(getKind() == Declaration && "Unexpected kind");
-    return DeclArg.ForRefParam;
+    return QualType::getFromOpaquePtr(DeclArg.QT);
   }
 
   /// \brief Retrieve the type for null non-type template argument.
@@ -344,7 +342,7 @@ public:
   /// \brief Return the array of arguments in this template argument pack.
   ArrayRef getPackAsArray() const {
     assert(getKind() == Pack);
-    return ArrayRef(Args.Args, Args.NumArgs);
+    return llvm::makeArrayRef(Args.Args, Args.NumArgs);
   }
 
   /// \brief Determines whether two template arguments are superficially the
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 09862e4..1bda01f 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -16,6 +16,7 @@
 
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/TemplateName.h"
+#include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
 #include "clang/Basic/LLVM.h"
@@ -25,11 +26,11 @@
 #include "clang/Basic/Visibility.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/ErrorHandling.h"
 
 namespace clang {
@@ -400,21 +401,36 @@ public:
     Mask |= qs.Mask;
   }
 
+  /// \brief Returns true if this address space is a superset of the other one.
+  /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of
+  /// overlapping address spaces.
+  /// CL1.1 or CL1.2:
+  ///   every address space is a superset of itself.
+  /// CL2.0 adds:
+  ///   __generic is a superset of any address space except for __constant.
+  bool isAddressSpaceSupersetOf(Qualifiers other) const {
+    return
+        // Address spaces must match exactly.
+        getAddressSpace() == other.getAddressSpace() ||
+        // Otherwise in OpenCLC v2.0 s6.5.5: every address space except
+        // for __constant can be used as __generic.
+        (getAddressSpace() == LangAS::opencl_generic &&
+         other.getAddressSpace() != LangAS::opencl_constant);
+  }
+
   /// \brief Determines if these qualifiers compatibly include another set.
   /// Generally this answers the question of whether an object with the other
   /// qualifiers can be safely used as an object with these qualifiers.
   bool compatiblyIncludes(Qualifiers other) const {
-    return
-      // Address spaces must match exactly.
-      getAddressSpace() == other.getAddressSpace() &&
-      // ObjC GC qualifiers can match, be added, or be removed, but can't be
-      // changed.
-      (getObjCGCAttr() == other.getObjCGCAttr() ||
-       !hasObjCGCAttr() || !other.hasObjCGCAttr()) &&
-      // ObjC lifetime qualifiers must match exactly.
-      getObjCLifetime() == other.getObjCLifetime() &&
-      // CVR qualifiers may subset.
-      (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
+    return isAddressSpaceSupersetOf(other) &&
+           // ObjC GC qualifiers can match, be added, or be removed, but can't
+           // be changed.
+           (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() ||
+            !other.hasObjCGCAttr()) &&
+           // ObjC lifetime qualifiers must match exactly.
+           getObjCLifetime() == other.getObjCLifetime() &&
+           // CVR qualifiers may subset.
+           (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask));
   }
 
   /// \brief Determines if these qualifiers compatibly include another set of
@@ -1245,6 +1261,7 @@ protected:
 
   class FunctionTypeBitfields {
     friend class FunctionType;
+    friend class FunctionProtoType;
 
     unsigned : NumTypeBits;
 
@@ -1259,6 +1276,11 @@ protected:
     /// C++ 8.3.5p4: The return type, the parameter type list and the
     /// cv-qualifier-seq, [...], are part of the function type.
     unsigned TypeQuals : 3;
+
+    /// \brief The ref-qualifier associated with a \c FunctionProtoType.
+    ///
+    /// This is a value of type \c RefQualifierKind.
+    unsigned RefQualifier : 2;
   };
 
   class ObjCObjectTypeBitfields {
@@ -1685,6 +1707,11 @@ public:
   /// type of a class template or class template partial specialization.
   CXXRecordDecl *getAsCXXRecordDecl() const;
 
+  /// \brief Retrieves the TagDecl that this type refers to, either
+  /// because the type is a TagType or because it is the injected-class-name
+  /// type of a class template or class template partial specialization.
+  TagDecl *getAsTagDecl() const;
+
   /// If this is a pointer or reference to a RecordType, return the
   /// CXXRecordDecl that that type refers to.
   ///
@@ -1982,6 +2009,22 @@ public:
 
   QualType getPointeeType() const { return PointeeType; }
 
+  /// \brief Returns true if address spaces of pointers overlap.
+  /// OpenCL v2.0 defines conversion rules for pointers to different
+  /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping
+  /// address spaces.
+  /// CL1.1 or CL1.2:
+  ///   address spaces overlap iff they are they same.
+  /// CL2.0 adds:
+  ///   __generic overlaps with any address space except for __constant.
+  bool isAddressSpaceOverlapping(const PointerType &other) const {
+    Qualifiers thisQuals = PointeeType.getQualifiers();
+    Qualifiers otherQuals = other.getPointeeType().getQualifiers();
+    // Address spaces overlap if at least one of them is a superset of another
+    return thisQuals.isAddressSpaceSupersetOf(otherQuals) ||
+           otherQuals.isAddressSpaceSupersetOf(thisQuals);
+  }
+
   bool isSugared() const { return false; }
   QualType desugar() const { return QualType(this, 0); }
 
@@ -2765,7 +2808,7 @@ class FunctionType : public Type {
 
 protected:
   FunctionType(TypeClass tc, QualType res,
-               unsigned typeQuals, QualType Canonical, bool Dependent,
+               QualType Canonical, bool Dependent,
                bool InstantiationDependent,
                bool VariablyModified, bool ContainsUnexpandedParameterPack,
                ExtInfo Info)
@@ -2773,7 +2816,6 @@ protected:
            ContainsUnexpandedParameterPack),
       ResultType(res) {
     FunctionTypeBits.ExtInfo = Info.Bits;
-    FunctionTypeBits.TypeQuals = typeQuals;
   }
   unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; }
 
@@ -2810,7 +2852,7 @@ public:
 /// no information available about its arguments.
 class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
   FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info)
-    : FunctionType(FunctionNoProto, Result, 0, Canonical,
+    : FunctionType(FunctionNoProto, Result, Canonical,
                    /*Dependent=*/false, /*InstantiationDependent=*/false,
                    Result->isVariablyModifiedType(),
                    /*ContainsUnexpandedParameterPack=*/false, Info) {}
@@ -2844,33 +2886,51 @@ public:
 /// type.
 class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
 public:
+  struct ExceptionSpecInfo {
+    ExceptionSpecInfo()
+        : Type(EST_None), NoexceptExpr(nullptr),
+          SourceDecl(nullptr), SourceTemplate(nullptr) {}
+
+    ExceptionSpecInfo(ExceptionSpecificationType EST)
+        : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr),
+          SourceTemplate(nullptr) {}
+
+    /// The kind of exception specification this is.
+    ExceptionSpecificationType Type;
+    /// Explicitly-specified list of exception types.
+    ArrayRef Exceptions;
+    /// Noexcept expression, if this is EST_ComputedNoexcept.
+    Expr *NoexceptExpr;
+    /// The function whose exception specification this is, for
+    /// EST_Unevaluated and EST_Uninstantiated.
+    FunctionDecl *SourceDecl;
+    /// The function template whose exception specification this is instantiated
+    /// from, for EST_Uninstantiated.
+    FunctionDecl *SourceTemplate;
+  };
+
   /// ExtProtoInfo - Extra information about a function prototype.
   struct ExtProtoInfo {
     ExtProtoInfo()
         : Variadic(false), HasTrailingReturn(false), TypeQuals(0),
-          ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0),
-          Exceptions(nullptr), NoexceptExpr(nullptr),
-          ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr),
-          ConsumedParameters(nullptr) {}
+          RefQualifier(RQ_None), ConsumedParameters(nullptr) {}
 
     ExtProtoInfo(CallingConv CC)
         : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0),
-          ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0),
-          Exceptions(nullptr), NoexceptExpr(nullptr),
-          ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr),
-          ConsumedParameters(nullptr) {}
+          RefQualifier(RQ_None), ConsumedParameters(nullptr) {}
+
+    ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) {
+      ExtProtoInfo Result(*this);
+      Result.ExceptionSpec = O;
+      return Result;
+    }
 
     FunctionType::ExtInfo ExtInfo;
     bool Variadic : 1;
     bool HasTrailingReturn : 1;
     unsigned char TypeQuals;
-    ExceptionSpecificationType ExceptionSpecType;
     RefQualifierKind RefQualifier;
-    unsigned NumExceptions;
-    const QualType *Exceptions;
-    Expr *NoexceptExpr;
-    FunctionDecl *ExceptionSpecDecl;
-    FunctionDecl *ExceptionSpecTemplate;
+    ExceptionSpecInfo ExceptionSpec;
     const bool *ConsumedParameters;
   };
 
@@ -2896,7 +2956,7 @@ private:
   unsigned NumExceptions : 9;
 
   /// ExceptionSpecType - The type of exception specification this function has.
-  unsigned ExceptionSpecType : 3;
+  unsigned ExceptionSpecType : 4;
 
   /// HasAnyConsumedParams - Whether this function has any consumed parameters.
   unsigned HasAnyConsumedParams : 1;
@@ -2907,11 +2967,6 @@ private:
   /// HasTrailingReturn - Whether this function has a trailing return type.
   unsigned HasTrailingReturn : 1;
 
-  /// \brief The ref-qualifier associated with a \c FunctionProtoType.
-  ///
-  /// This is a value of type \c RefQualifierKind.
-  unsigned RefQualifier : 2;
-
   // ParamInfo - There is an variable size array after the class in memory that
   // holds the parameter types.
 
@@ -2952,7 +3007,7 @@ public:
     return param_type_begin()[i];
   }
   ArrayRef getParamTypes() const {
-    return ArrayRef(param_type_begin(), param_type_end());
+    return llvm::makeArrayRef(param_type_begin(), param_type_end());
   }
 
   ExtProtoInfo getExtProtoInfo() const {
@@ -2960,19 +3015,18 @@ public:
     EPI.ExtInfo = getExtInfo();
     EPI.Variadic = isVariadic();
     EPI.HasTrailingReturn = hasTrailingReturn();
-    EPI.ExceptionSpecType = getExceptionSpecType();
+    EPI.ExceptionSpec.Type = getExceptionSpecType();
     EPI.TypeQuals = static_cast(getTypeQuals());
     EPI.RefQualifier = getRefQualifier();
-    if (EPI.ExceptionSpecType == EST_Dynamic) {
-      EPI.NumExceptions = NumExceptions;
-      EPI.Exceptions = exception_begin();
-    } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) {
-      EPI.NoexceptExpr = getNoexceptExpr();
-    } else if (EPI.ExceptionSpecType == EST_Uninstantiated) {
-      EPI.ExceptionSpecDecl = getExceptionSpecDecl();
-      EPI.ExceptionSpecTemplate = getExceptionSpecTemplate();
-    } else if (EPI.ExceptionSpecType == EST_Unevaluated) {
-      EPI.ExceptionSpecDecl = getExceptionSpecDecl();
+    if (EPI.ExceptionSpec.Type == EST_Dynamic) {
+      EPI.ExceptionSpec.Exceptions = exceptions();
+    } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) {
+      EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr();
+    } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) {
+      EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
+      EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate();
+    } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) {
+      EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl();
     }
     if (hasAnyConsumedParams())
       EPI.ConsumedParameters = getConsumedParamsBuffer();
@@ -2995,6 +3049,8 @@ public:
   bool hasNoexceptExceptionSpec() const {
     return isNoexceptExceptionSpec(getExceptionSpecType());
   }
+  /// \brief Return whether this function has a dependent exception spec.
+  bool hasDependentExceptionSpec() const;
   /// \brief Result type of getNoexceptSpec().
   enum NoexceptResult {
     NR_NoNoexcept,  ///< There is no noexcept specifier.
@@ -3057,7 +3113,7 @@ public:
 
   /// \brief Retrieve the ref-qualifier associated with this function type.
   RefQualifierKind getRefQualifier() const {
-    return static_cast(RefQualifier);
+    return static_cast(FunctionTypeBits.RefQualifier);
   }
 
   typedef const QualType *param_type_iterator;
@@ -3074,10 +3130,9 @@ public:
   }
 
   typedef const QualType *exception_iterator;
-  typedef llvm::iterator_range exception_range;
 
-  exception_range exceptions() const {
-    return exception_range(exception_begin(), exception_end());
+  ArrayRef exceptions() const {
+    return llvm::makeArrayRef(exception_begin(), exception_end());
   }
   exception_iterator exception_begin() const {
     // exceptions begin where arguments end
@@ -3416,6 +3471,7 @@ public:
     attr_stdcall,
     attr_thiscall,
     attr_pascal,
+    attr_vectorcall,
     attr_pnaclcall,
     attr_inteloclbicc,
     attr_ms_abi,
@@ -5231,8 +5287,8 @@ template  const T *Type::castAs() const {
   ArrayType_cannot_be_used_with_getAs at;
   (void) at;
 
-  assert(isa(CanonicalType));
   if (const T *ty = dyn_cast(this)) return ty;
+  assert(isa(CanonicalType));
   return cast(getUnqualifiedDesugaredType());
 }
 
diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h
index 3648d2a..4f3c811 100644
--- a/include/clang/AST/TypeLoc.h
+++ b/include/clang/AST/TypeLoc.h
@@ -1208,7 +1208,7 @@ public:
   }
 
   ArrayRef getParams() const {
-    return ArrayRef(getParmArray(), getNumParams());
+    return llvm::makeArrayRef(getParmArray(), getNumParams());
   }
 
   // ParmVarDecls* are stored after Info, one for each parameter.
@@ -1567,6 +1567,8 @@ public:
   void setUnderlyingTInfo(TypeSourceInfo* TI) const {
     this->getLocalData()->UnderlyingTInfo = TI;
   }
+
+  void initializeLocal(ASTContext &Context, SourceLocation Loc);
 };
 
 // FIXME: location of the 'decltype' and parens.
diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h
index 9c9f15e..392e544 100644
--- a/include/clang/AST/TypeOrdering.h
+++ b/include/clang/AST/TypeOrdering.h
@@ -16,8 +16,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_TYPE_ORDERING_H
-#define LLVM_CLANG_TYPE_ORDERING_H
+#ifndef LLVM_CLANG_AST_TYPEORDERING_H
+#define LLVM_CLANG_AST_TYPEORDERING_H
 
 #include "clang/AST/CanonicalType.h"
 #include "clang/AST/Type.h"
diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h
index 2ef5800..a11f22d 100644
--- a/include/clang/AST/UnresolvedSet.h
+++ b/include/clang/AST/UnresolvedSet.h
@@ -98,7 +98,7 @@ class UnresolvedSetImpl {
 private:
   template  friend class UnresolvedSet;
   UnresolvedSetImpl() {}
-  UnresolvedSetImpl(const UnresolvedSetImpl &) LLVM_DELETED_FUNCTION;
+  UnresolvedSetImpl(const UnresolvedSetImpl &) {}
 
 public:
   // We don't currently support assignment through this iterator, so we might
diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h
index 8af0546..ce2674e 100644
--- a/include/clang/ASTMatchers/ASTMatchFinder.h
+++ b/include/clang/ASTMatchers/ASTMatchFinder.h
@@ -38,10 +38,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H
 
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Timer.h"
 
 namespace clang {
 
@@ -102,6 +104,12 @@ public:
     ///
     /// Optionally override to do per translation unit tasks.
     virtual void onEndOfTranslationUnit() {}
+
+    /// \brief An id used to group the matchers.
+    ///
+    /// This id is used, for example, for the profiling output.
+    /// It defaults to "".
+    virtual StringRef getID() const;
   };
 
   /// \brief Called when parsing is finished. Intended for testing only.
@@ -111,7 +119,22 @@ public:
     virtual void run() = 0;
   };
 
-  MatchFinder();
+  struct MatchFinderOptions {
+    struct Profiling {
+      Profiling(llvm::StringMap &Records)
+          : Records(Records) {}
+
+      /// \brief Per bucket timing information.
+      llvm::StringMap &Records;
+    };
+
+    /// \brief Enables per-check timers.
+    ///
+    /// It prints a report after match.
+    llvm::Optional CheckProfiling;
+  };
+
+  MatchFinder(MatchFinderOptions Options = MatchFinderOptions());
   ~MatchFinder();
 
   /// \brief Adds a matcher to execute when running over the AST.
@@ -148,7 +171,7 @@ public:
                          MatchCallback *Action);
 
   /// \brief Creates a clang ASTConsumer that finds all matches.
-  clang::ASTConsumer *newASTConsumer();
+  std::unique_ptr newASTConsumer();
 
   /// \brief Calls the registered callbacks on all matches on the given \p Node.
   ///
@@ -173,11 +196,25 @@ public:
   /// Each call to FindAll(...) will call the closure once.
   void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone);
 
-private:
-  /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called
+  /// \brief For each \c Matcher<> a \c MatchCallback that will be called
   /// when it matches.
-  std::vector >
-    MatcherCallbackPairs;
+  struct MatchersByType {
+    std::vector>
+        DeclOrStmt;
+    std::vector> Type;
+    std::vector>
+        NestedNameSpecifier;
+    std::vector>
+        NestedNameSpecifierLoc;
+    std::vector> TypeLoc;
+    /// \brief All the callbacks in one container to simplify iteration.
+    std::vector AllCallbacks;
+  };
+
+private:
+  MatchersByType Matchers;
+
+  MatchFinderOptions Options;
 
   /// \brief Called when parsing is done.
   ParsingDoneTestCallback *ParsingDone;
@@ -210,16 +247,14 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
 ///
 /// This is useful in combanation with \c match():
 /// \code
-///   Decl *D = selectFirst("id", match(Matcher.bind("id"),
-///                                           Node, Context));
+///   const Decl *D = selectFirst("id", match(Matcher.bind("id"),
+///                                                 Node, Context));
 /// \endcode
 template 
-NodeT *
+const NodeT *
 selectFirst(StringRef BoundTo, const SmallVectorImpl &Results) {
-  for (SmallVectorImpl::const_iterator I = Results.begin(),
-                                                   E = Results.end();
-       I != E; ++I) {
-    if (NodeT *Node = I->getNodeAs(BoundTo))
+  for (const BoundNodes &N : Results) {
+    if (const NodeT *Node = N.getNodeAs(BoundTo))
       return Node;
   }
   return nullptr;
@@ -243,7 +278,7 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node,
   MatchFinder Finder;
   Finder.addMatcher(Matcher, &Callback);
   Finder.match(Node, Context);
-  return Callback.Nodes;
+  return std::move(Callback.Nodes);
 }
 
 template 
@@ -255,4 +290,4 @@ match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) {
 } // end namespace ast_matchers
 } // end namespace clang
 
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 1ff4ab3..f002cb9 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -42,9 +42,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H
 
+#include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclFriend.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/ASTMatchers/ASTMatchersInternal.h"
@@ -140,9 +141,97 @@ typedef internal::Matcher NestedNameSpecifierLocMatcher;
 /// \endcode
 ///
 /// Usable as: Any Matcher
-inline internal::PolymorphicMatcherWithParam0
-anything() {
-  return internal::PolymorphicMatcherWithParam0();
+inline internal::TrueMatcher anything() { return internal::TrueMatcher(); }
+
+/// \brief Matches typedef declarations.
+///
+/// Given
+/// \code
+///   typedef int X;
+/// \endcode
+/// typedefDecl()
+///   matches "typedef int X"
+const internal::VariadicDynCastAllOfMatcher typedefDecl;
+
+/// \brief Matches AST nodes that were expanded within the main-file.
+///
+/// Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile())
+/// \code
+///   #include 
+///   class X {};
+/// \endcode
+/// Y.h:
+/// \code
+///   class Y {};
+/// \endcode
+///
+/// Usable as: Matcher, Matcher, Matcher
+AST_POLYMORPHIC_MATCHER(isExpansionInMainFile,
+                        AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+                                                          TypeLoc)) {
+  auto &SourceManager = Finder->getASTContext().getSourceManager();
+  return SourceManager.isInMainFile(
+      SourceManager.getExpansionLoc(Node.getLocStart()));
+}
+
+/// \brief Matches AST nodes that were expanded within system-header-files.
+///
+/// Example matches Y but not X
+///     (matcher = recordDecl(isExpansionInSystemHeader())
+/// \code
+///   #include 
+///   class X {};
+/// \endcode
+/// SystemHeader.h:
+/// \code
+///   class Y {};
+/// \endcode
+///
+/// Usable as: Matcher, Matcher, Matcher
+AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader,
+                        AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+                                                          TypeLoc)) {
+  auto &SourceManager = Finder->getASTContext().getSourceManager();
+  auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+  if (ExpansionLoc.isInvalid()) {
+    return false;
+  }
+  return SourceManager.isInSystemHeader(ExpansionLoc);
+}
+
+/// \brief Matches AST nodes that were expanded within files whose name is
+/// partially matching a given regex.
+///
+/// Example matches Y but not X
+///     (matcher = recordDecl(isExpansionInFileMatching("AST.*"))
+/// \code
+///   #include "ASTMatcher.h"
+///   class X {};
+/// \endcode
+/// ASTMatcher.h:
+/// \code
+///   class Y {};
+/// \endcode
+///
+/// Usable as: Matcher, Matcher, Matcher
+AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching,
+                          AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt,
+                                                            TypeLoc),
+                          std::string, RegExp) {
+  auto &SourceManager = Finder->getASTContext().getSourceManager();
+  auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart());
+  if (ExpansionLoc.isInvalid()) {
+    return false;
+  }
+  auto FileEntry =
+      SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc));
+  if (!FileEntry) {
+    return false;
+  }
+
+  auto Filename = FileEntry->getName();
+  llvm::Regex RE(RegExp);
+  return RE.match(Filename);
 }
 
 /// \brief Matches declarations.
@@ -156,6 +245,17 @@ anything() {
 /// \endcode
 const internal::VariadicAllOfMatcher decl;
 
+/// \brief Matches a declaration of a linkage specification.
+///
+/// Given
+/// \code
+///   extern "C" {}
+/// \endcode
+/// linkageSpecDecl()
+///   matches "extern "C" {}"
+const internal::VariadicDynCastAllOfMatcher
+    linkageSpecDecl;
+
 /// \brief Matches a declaration of anything that could have a name.
 ///
 /// Example matches \c X, \c S, the anonymous union type, \c i, and \c U;
@@ -263,6 +363,17 @@ const internal::VariadicDynCastAllOfMatcher<
 /// \endcode
 const internal::VariadicAllOfMatcher ctorInitializer;
 
+/// \brief Matches template arguments.
+///
+/// Given
+/// \code
+///   template  struct C {};
+///   C c;
+/// \endcode
+/// templateArgument()
+///   matches 'int' in C.
+const internal::VariadicAllOfMatcher templateArgument;
+
 /// \brief Matches public C++ declarations.
 ///
 /// Given
@@ -441,6 +552,23 @@ AST_POLYMORPHIC_MATCHER_P2(
   return InnerMatcher.matches(List[N], Finder, Builder);
 }
 
+/// \brief Matches if the number of template arguments equals \p N.
+///
+/// Given
+/// \code
+///   template struct C {};
+///   C c;
+/// \endcode
+/// classTemplateSpecializationDecl(templateArgumentCountIs(1))
+///   matches C.
+AST_POLYMORPHIC_MATCHER_P(
+    templateArgumentCountIs,
+    AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl,
+                                      TemplateSpecializationType),
+    unsigned, N) {
+  return internal::getTemplateSpecializationArgs(Node).size() == N;
+}
+
 /// \brief Matches a TemplateArgument that refers to a certain type.
 ///
 /// Given
@@ -497,6 +625,68 @@ AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher, InnerMatcher) {
   return false;
 }
 
+/// \brief Matches a TemplateArgument that is an integral value.
+///
+/// Given
+/// \code
+///   template struct A {};
+///   C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+///   hasAnyTemplateArgument(isIntegral()))
+///   matches the implicit instantiation of C in C<42>
+///   with isIntegral() matching 42.
+AST_MATCHER(TemplateArgument, isIntegral) {
+  return Node.getKind() == TemplateArgument::Integral;
+}
+
+/// \brief Matches a TemplateArgument that referes to an integral type.
+///
+/// Given
+/// \code
+///   template struct A {};
+///   C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+///   hasAnyTemplateArgument(refersToIntegralType(asString("int"))))
+///   matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, refersToIntegralType,
+              internal::Matcher, InnerMatcher) {
+  if (Node.getKind() != TemplateArgument::Integral)
+    return false;
+  return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder);
+}
+
+/// \brief Matches a TemplateArgument of integral type with a given value.
+///
+/// Note that 'Value' is a string as the template argument's value is
+/// an arbitrary precision integer. 'Value' must be euqal to the canonical
+/// representation of that integral value in base 10.
+///
+/// Given
+/// \code
+///   template struct A {};
+///   C<42> c;
+/// \endcode
+/// classTemplateSpecializationDecl(
+///   hasAnyTemplateArgument(equalsIntegralValue("42")))
+///   matches the implicit instantiation of C in C<42>.
+AST_MATCHER_P(TemplateArgument, equalsIntegralValue,
+              std::string, Value) {
+  if (Node.getKind() != TemplateArgument::Integral)
+    return false;
+  return Node.getAsIntegral().toString(10) == Value;
+}
+
+/// \brief Matches any value declaration.
+///
+/// Example matches A, B, C and F
+/// \code
+///   enum X { A, B, C };
+///   void F();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher valueDecl;
+
 /// \brief Matches C++ constructor declarations.
 ///
 /// Example matches Foo::Foo() and Foo::Foo(int)
@@ -1414,21 +1604,21 @@ const internal::VariadicAllOfMatcher typeLoc;
 ///
 /// Usable as: Any Matcher
 const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = {
-  internal::EachOfVariadicOperator
+  internal::DynTypedMatcher::VO_EachOf
 };
 
 /// \brief Matches if any of the given matchers matches.
 ///
 /// Usable as: Any Matcher
 const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = {
-  internal::AnyOfVariadicOperator
+  internal::DynTypedMatcher::VO_AnyOf
 };
 
 /// \brief Matches if all given matchers match.
 ///
 /// Usable as: Any Matcher
 const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = {
-  internal::AllOfVariadicOperator
+  internal::DynTypedMatcher::VO_AllOf
 };
 
 /// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL)
@@ -1502,16 +1692,8 @@ inline internal::Matcher sizeOfExpr(
 /// \code
 ///   namespace a { namespace b { class X; } }
 /// \endcode
-AST_MATCHER_P(NamedDecl, hasName, std::string, Name) {
-  assert(!Name.empty());
-  const std::string FullNameString = "::" + Node.getQualifiedNameAsString();
-  const StringRef FullName = FullNameString;
-  const StringRef Pattern = Name;
-  if (Pattern.startswith("::")) {
-    return FullName == Pattern;
-  } else {
-    return FullName.endswith(("::" + Pattern).str());
-  }
+inline internal::Matcher hasName(const std::string &Name) {
+  return internal::Matcher(new internal::HasNameMatcher(Name));
 }
 
 /// \brief Matches NamedDecl nodes whose fully qualified names contain
@@ -1558,7 +1740,7 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) {
 inline internal::PolymorphicMatcherWithParam1<
     internal::HasOverloadedOperatorNameMatcher, StringRef,
     AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>
-hasOverloadedOperatorName(const StringRef Name) {
+hasOverloadedOperatorName(StringRef Name) {
   return internal::PolymorphicMatcherWithParam1<
       internal::HasOverloadedOperatorNameMatcher, StringRef,
       AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>(
@@ -1592,7 +1774,7 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom,
 }
 
 /// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, StringRef, BaseName, 1) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) {
   assert(!BaseName.empty());
   return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
 }
@@ -1607,8 +1789,8 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom,
 
 /// \brief Overloaded method as shortcut for
 /// \c isSameOrDerivedFrom(hasName(...)).
-AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, StringRef, BaseName,
-                       1) {
+AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string,
+                       BaseName, 1) {
   assert(!BaseName.empty());
   return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder);
 }
@@ -1768,7 +1950,7 @@ const internal::ArgumentAdaptingMatcherFunc<
 ///
 /// Usable as: Any Matcher
 const internal::VariadicOperatorMatcherFunc<1, 1> unless = {
-  internal::NotUnaryOperator
+  internal::DynTypedMatcher::VO_UnaryNot
 };
 
 /// \brief Matches a node if the declaration associated with that node
@@ -1844,7 +2026,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher,
 /// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x")))))
 /// \code
 ///   class Y { public: void x(); };
-///   void z() { Y y; y.x();
+///   void z() { Y y; y.x(); }
 /// \endcode
 AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher, InnerMatcher,
                        1) {
@@ -1952,6 +2134,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher,
 ///     void a(X b) {
 ///       X &x = b;
 ///       const X &y = b;
+///     }
 ///   };
 /// \endcode
 AST_MATCHER_P(QualType, references, internal::Matcher,
@@ -2280,11 +2463,10 @@ AST_MATCHER(CXXCtorInitializer, isWritten) {
 AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2(
                                               CallExpr, CXXConstructExpr),
                           internal::Matcher, InnerMatcher) {
-  for (unsigned I = 0; I < Node.getNumArgs(); ++I) {
+  for (const Expr *Arg : Node.arguments()) {
     BoundNodesTreeBuilder Result(*Builder);
-    if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder,
-                             &Result)) {
-      *Builder = Result;
+    if (InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, &Result)) {
+      *Builder = std::move(Result);
       return true;
     }
   }
@@ -2372,6 +2554,19 @@ AST_MATCHER(FunctionDecl, isExternC) {
   return Node.isExternC();
 }
 
+/// \brief Matches deleted function declarations.
+///
+/// Given:
+/// \code
+///   void Func();
+///   void DeletedFunc() = delete;
+/// \endcode
+/// functionDecl(isDeleted())
+///   matches the declaration of DeletedFunc, but not Func.
+AST_MATCHER(FunctionDecl, isDeleted) {
+  return Node.isDeleted();
+}
+
 /// \brief Matches the condition expression of an if statement, for loop,
 /// or conditional operator.
 ///
@@ -2953,6 +3148,43 @@ AST_POLYMORPHIC_MATCHER(
           TSK_ExplicitInstantiationDefinition);
 }
 
+/// \brief Matches declarations that are template instantiations or are inside
+/// template instantiations.
+///
+/// Given
+/// \code
+///   template void A(T t) { T i; }
+///   A(0);
+///   A(0U);
+/// \endcode
+/// functionDecl(isInstantiated())
+///   matches 'A(int) {...};' and 'A(unsigned) {...}'.
+AST_MATCHER_FUNCTION(internal::Matcher, isInstantiated) {
+  auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()),
+                                    functionDecl(isTemplateInstantiation())));
+  return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation)));
+}
+
+/// \brief Matches statements inside of a template instantiation.
+///
+/// Given
+/// \code
+///   int j;
+///   template void A(T t) { T i; j += 42;}
+///   A(0);
+///   A(0U);
+/// \endcode
+/// declStmt(isInTemplateInstantiation())
+///   matches 'int i;' and 'unsigned i'.
+/// unless(stmt(isInTemplateInstantiation()))
+///   will NOT match j += 42; as it's shared between the template definition and
+///   instantiation.
+AST_MATCHER_FUNCTION(internal::Matcher, isInTemplateInstantiation) {
+  return stmt(
+      hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()),
+                             functionDecl(isTemplateInstantiation())))));
+}
+
 /// \brief Matches explicit template specializations of function, class, or
 /// static member variable template instantiations.
 ///
@@ -2979,6 +3211,18 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher, loc,
       new internal::TypeLocTypeMatcher(InnerMatcher));
 }
 
+/// \brief Matches type \c void.
+///
+/// Given
+/// \code
+///  struct S { void func(); };
+/// \endcode
+/// functionDecl(returns(voidType()))
+///   matches "void func();"
+AST_MATCHER(Type, voidType) {
+  return Node.isVoidType();
+}
+
 /// \brief Matches builtin Types.
 ///
 /// Given
@@ -3094,6 +3338,7 @@ AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType);
 ///     int a[] = { 2, 3 }
 ///     int b[42];
 ///     int c[a[0]];
+///   }
 /// \endcode
 /// variableArrayType()
 ///   matches "int c[a[0]]"
@@ -3432,8 +3677,9 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher,
 /// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the
 /// declaration of \c class \c D.
 AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher, InnerMatcher) {
-  return InnerMatcher.matches(*Decl::castFromDeclContext(Node.getDeclContext()),
-                              Finder, Builder);
+  const DeclContext *DC = Node.getDeclContext();
+  if (!DC) return false;
+  return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder);
 }
 
 /// \brief Matches nested name specifiers.
@@ -3599,7 +3845,7 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher,
       Result.addMatch(CaseBuilder);
     }
   }
-  *Builder = Result;
+  *Builder = std::move(Result);
   return Matched;
 }
 
@@ -3622,7 +3868,7 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer,
       Result.addMatch(InitBuilder);
     }
   }
-  *Builder = Result;
+  *Builder = std::move(Result);
   return Matched;
 }
 
@@ -3643,7 +3889,32 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher,
   return InnerMatcher.matches(*Node.getLHS(), Finder, Builder);
 }
 
+/// \brief Matches declaration that has a given attribute.
+///
+/// Given
+/// \code
+///   __attribute__((device)) void f() { ... }
+/// \endcode
+/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of
+/// f.
+AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) {
+  for (const auto *Attr : Node.attrs()) {
+    if (Attr->getKind() == AttrKind)
+      return true;
+  }
+  return false;
+}
+
+/// \brief Matches CUDA kernel call expression.
+///
+/// Example matches,
+/// \code
+///   kernel<<>>();
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher
+    CUDAKernelCallExpr;
+
 } // end namespace ast_matchers
 } // end namespace clang
 
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h
index 94435fd..ebe5cdd 100644
--- a/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -32,8 +32,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H
 
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Decl.h"
@@ -44,6 +44,7 @@
 #include "clang/AST/Type.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/VariadicFunction.h"
+#include "llvm/Support/ManagedStatic.h"
 #include 
 #include 
 #include 
@@ -61,9 +62,8 @@ public:
   /// \brief Adds \c Node to the map with key \c ID.
   ///
   /// The node's base type should be in NodeBaseType or it will be unaccessible.
-  template 
-  void addNode(StringRef ID, const T* Node) {
-    NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node);
+  void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) {
+    NodeMap[ID] = DynNode;
   }
 
   /// \brief Returns the AST node bound to \c ID.
@@ -103,6 +103,16 @@ public:
     return NodeMap;
   }
 
+  /// \brief Returns \c true if this \c BoundNodesMap can be compared, i.e. all
+  /// stored nodes have memoization data.
+  bool isComparable() const {
+    for (const auto &IDAndNode : NodeMap) {
+      if (!IDAndNode.second.getMemoizationData())
+        return false;
+    }
+    return true;
+  }
+
 private:
   IDToNodeMap NodeMap;
 };
@@ -126,11 +136,12 @@ public:
   };
 
   /// \brief Add a binding from an id to a node.
-  template  void setBinding(const std::string &Id, const T *Node) {
+  void setBinding(const std::string &Id,
+                  const ast_type_traits::DynTypedNode &DynNode) {
     if (Bindings.empty())
       Bindings.push_back(BoundNodesMap());
-    for (unsigned i = 0, e = Bindings.size(); i != e; ++i)
-      Bindings[i].addNode(Id, Node);
+    for (BoundNodesMap &Binding : Bindings)
+      Binding.addNode(Id, DynNode);
   }
 
   /// \brief Adds a branch in the tree.
@@ -153,12 +164,38 @@ public:
     return Bindings < Other.Bindings;
   }
 
+  /// \brief Returns \c true if this \c BoundNodesTreeBuilder can be compared,
+  /// i.e. all stored node maps have memoization data.
+  bool isComparable() const {
+    for (const BoundNodesMap &NodesMap : Bindings) {
+      if (!NodesMap.isComparable())
+        return false;
+    }
+    return true;
+  }
+
 private:
   SmallVector Bindings;
 };
 
 class ASTMatchFinder;
 
+/// \brief Generic interface for all matchers.
+///
+/// Used by the implementation of Matcher and DynTypedMatcher.
+/// In general, implement MatcherInterface or SingleNodeMatcherInterface
+/// instead.
+class DynMatcherInterface : public RefCountedBaseVPTR {
+public:
+  /// \brief Returns true if \p DynNode can be matched.
+  ///
+  /// May bind \p DynNode to an ID via \p Builder, or recurse into
+  /// the AST via \p Finder.
+  virtual bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
+                          ASTMatchFinder *Finder,
+                          BoundNodesTreeBuilder *Builder) const = 0;
+};
+
 /// \brief Generic interface for matchers on an AST node of type T.
 ///
 /// Implement this if your matcher may need to inspect the children or
@@ -167,7 +204,7 @@ class ASTMatchFinder;
 /// current node and doesn't care about its children or descendants,
 /// implement SingleNodeMatcherInterface instead.
 template 
-class MatcherInterface : public RefCountedBaseVPTR {
+class MatcherInterface : public DynMatcherInterface {
 public:
   virtual ~MatcherInterface() {}
 
@@ -178,6 +215,12 @@ public:
   virtual bool matches(const T &Node,
                        ASTMatchFinder *Finder,
                        BoundNodesTreeBuilder *Builder) const = 0;
+
+  bool dynMatches(const ast_type_traits::DynTypedNode &DynNode,
+                  ASTMatchFinder *Finder,
+                  BoundNodesTreeBuilder *Builder) const override {
+    return matches(DynNode.getUnchecked(), Finder, Builder);
+  }
 };
 
 /// \brief Interface for matchers that only evaluate properties on a single
@@ -199,6 +242,145 @@ private:
   }
 };
 
+template  class Matcher;
+
+/// \brief Matcher that works on a \c DynTypedNode.
+///
+/// It is constructed from a \c Matcher object and redirects most calls to
+/// underlying matcher.
+/// It checks whether the \c DynTypedNode is convertible into the type of the
+/// underlying matcher and then do the actual match on the actual node, or
+/// return false if it is not convertible.
+class DynTypedMatcher {
+public:
+  /// \brief Takes ownership of the provided implementation pointer.
+  template 
+  DynTypedMatcher(MatcherInterface *Implementation)
+      : AllowBind(false),
+        SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind()),
+        RestrictKind(SupportedKind), Implementation(Implementation) {}
+
+  /// \brief Construct from a variadic function.
+  enum VariadicOperator {
+    /// \brief Matches nodes for which all provided matchers match.
+    VO_AllOf,
+    /// \brief Matches nodes for which at least one of the provided matchers
+    /// matches.
+    VO_AnyOf,
+    /// \brief Matches nodes for which at least one of the provided matchers
+    /// matches, but doesn't stop at the first match.
+    VO_EachOf,
+    /// \brief Matches nodes that do not match the provided matcher.
+    ///
+    /// Uses the variadic matcher interface, but fails if
+    /// InnerMatchers.size() != 1.
+    VO_UnaryNot
+  };
+  static DynTypedMatcher
+  constructVariadic(VariadicOperator Op,
+                    std::vector InnerMatchers);
+
+  /// \brief Get a "true" matcher for \p NodeKind.
+  ///
+  /// It only checks that the node is of the right kind.
+  static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind);
+
+  void setAllowBind(bool AB) { AllowBind = AB; }
+
+  /// \brief Check whether this matcher could ever match a node of kind \p Kind.
+  /// \return \c false if this matcher will never match such a node. Otherwise,
+  /// return \c true.
+  bool canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const;
+
+  /// \brief Return a matcher that points to the same implementation, but
+  ///   restricts the node types for \p Kind.
+  DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const;
+
+  /// \brief Returns true if the matcher matches the given \c DynNode.
+  bool matches(const ast_type_traits::DynTypedNode &DynNode,
+               ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const;
+
+  /// \brief Same as matches(), but skips the kind check.
+  ///
+  /// It is faster, but the caller must ensure the node is valid for the
+  /// kind of this matcher.
+  bool matchesNoKindCheck(const ast_type_traits::DynTypedNode &DynNode,
+                          ASTMatchFinder *Finder,
+                          BoundNodesTreeBuilder *Builder) const;
+
+  /// \brief Bind the specified \p ID to the matcher.
+  /// \return A new matcher with the \p ID bound to it if this matcher supports
+  ///   binding. Otherwise, returns an empty \c Optional<>.
+  llvm::Optional tryBind(StringRef ID) const;
+
+  /// \brief Returns a unique \p ID for the matcher.
+  ///
+  /// Casting a Matcher to Matcher creates a matcher that has the
+  /// same \c Implementation pointer, but different \c RestrictKind. We need to
+  /// include both in the ID to make it unique.
+  ///
+  /// \c MatcherIDType supports operator< and provides strict weak ordering.
+  typedef std::pair MatcherIDType;
+  MatcherIDType getID() const {
+    /// FIXME: Document the requirements this imposes on matcher
+    /// implementations (no new() implementation_ during a Matches()).
+    return std::make_pair(RestrictKind,
+                          reinterpret_cast(Implementation.get()));
+  }
+
+  /// \brief Returns the type this matcher works on.
+  ///
+  /// \c matches() will always return false unless the node passed is of this
+  /// or a derived type.
+  ast_type_traits::ASTNodeKind getSupportedKind() const {
+    return SupportedKind;
+  }
+
+  /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
+  ///   to a \c Matcher.
+  ///
+  /// This method verifies that the underlying matcher in \c Other can process
+  /// nodes of types T.
+  template  bool canConvertTo() const {
+    return canConvertTo(ast_type_traits::ASTNodeKind::getFromNodeKind());
+  }
+  bool canConvertTo(ast_type_traits::ASTNodeKind To) const;
+
+  /// \brief Construct a \c Matcher interface around the dynamic matcher.
+  ///
+  /// This method asserts that \c canConvertTo() is \c true. Callers
+  /// should call \c canConvertTo() first to make sure that \c this is
+  /// compatible with T.
+  template  Matcher convertTo() const {
+    assert(canConvertTo());
+    return unconditionalConvertTo();
+  }
+
+  /// \brief Same as \c convertTo(), but does not check that the underlying
+  ///   matcher can handle a value of T.
+  ///
+  /// If it is not compatible, then this matcher will never match anything.
+  template  Matcher unconditionalConvertTo() const;
+
+private:
+ DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind,
+                 ast_type_traits::ASTNodeKind RestrictKind,
+                 IntrusiveRefCntPtr Implementation)
+     : AllowBind(false),
+       SupportedKind(SupportedKind),
+       RestrictKind(RestrictKind),
+       Implementation(std::move(Implementation)) {}
+
+  bool AllowBind;
+  ast_type_traits::ASTNodeKind SupportedKind;
+  /// \brief A potentially stricter node kind.
+  ///
+  /// It allows to perform implicit and dynamic cast of matchers without
+  /// needing to change \c Implementation.
+  ast_type_traits::ASTNodeKind RestrictKind;
+  IntrusiveRefCntPtr Implementation;
+};
+
 /// \brief Wrapper of a MatcherInterface *that allows copying.
 ///
 /// A Matcher can be used anywhere a Matcher is
@@ -221,7 +403,10 @@ public:
   Matcher(const Matcher &Other,
           typename std::enable_if::value &&
                                   !std::is_same::value>::type * = 0)
-      : Implementation(new ImplicitCastMatcher(Other)) {}
+      : Implementation(restrictMatcher(Other.Implementation)) {
+    assert(Implementation.getSupportedKind().isSame(
+        ast_type_traits::ASTNodeKind::getFromNodeKind()));
+  }
 
   /// \brief Implicitly converts \c Matcher to \c Matcher.
   ///
@@ -233,26 +418,34 @@ public:
             std::is_same::value>::type* = 0)
       : Implementation(new TypeToQualType(Other)) {}
 
+  /// \brief Convert \c this into a \c Matcher by applying dyn_cast<> to the
+  /// argument.
+  /// \c To must be a base class of \c T.
+  template 
+  Matcher dynCastTo() const {
+    static_assert(std::is_base_of::value, "Invalid dynCast call.");
+    return Matcher(Implementation);
+  }
+
   /// \brief Forwards the call to the underlying MatcherInterface pointer.
   bool matches(const T &Node,
                ASTMatchFinder *Finder,
                BoundNodesTreeBuilder *Builder) const {
-    if (Implementation->matches(Node, Finder, Builder))
-      return true;
-    // Delete all bindings when a matcher does not match.
-    // This prevents unexpected exposure of bound nodes in unmatches
-    // branches of the match tree.
-    *Builder = BoundNodesTreeBuilder();
-    return false;
+    return Implementation.matches(ast_type_traits::DynTypedNode::create(Node),
+                                  Finder, Builder);
   }
 
   /// \brief Returns an ID that uniquely identifies the matcher.
-  uint64_t getID() const {
-    /// FIXME: Document the requirements this imposes on matcher
-    /// implementations (no new() implementation_ during a Matches()).
-    return reinterpret_cast(Implementation.get());
+  DynTypedMatcher::MatcherIDType getID() const {
+    return Implementation.getID();
   }
 
+  /// \brief Extract the dynamic matcher.
+  ///
+  /// The returned matcher keeps the same restrictions as \c this and remembers
+  /// that it is meant to support nodes of type \c T.
+  operator DynTypedMatcher() const { return Implementation; }
+
   /// \brief Allows the conversion of a \c Matcher to a \c
   /// Matcher.
   ///
@@ -276,24 +469,22 @@ public:
   };
 
 private:
-  /// \brief Allows conversion from Matcher to Matcher if T
-  /// is derived from Base.
-  template 
-  class ImplicitCastMatcher : public MatcherInterface {
-  public:
-    explicit ImplicitCastMatcher(const Matcher &From)
-        : From(From) {}
+  // For Matcher <=> Matcher conversions.
+  template  friend class Matcher;
+  // For DynTypedMatcher::unconditionalConvertTo.
+  friend class DynTypedMatcher;
 
-    bool matches(const T &Node, ASTMatchFinder *Finder,
-                 BoundNodesTreeBuilder *Builder) const override {
-      return From.matches(Node, Finder, Builder);
-    }
+  static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) {
+    return Other.dynCastTo(ast_type_traits::ASTNodeKind::getFromNodeKind());
+  }
 
-  private:
-    const Matcher From;
-  };
+  explicit Matcher(const DynTypedMatcher &Implementation)
+      : Implementation(restrictMatcher(Implementation)) {
+    assert(this->Implementation.getSupportedKind()
+               .isSame(ast_type_traits::ASTNodeKind::getFromNodeKind()));
+  }
 
-  IntrusiveRefCntPtr< MatcherInterface > Implementation;
+  DynTypedMatcher Implementation;
 };  // class Matcher
 
 /// \brief A convenient helper for creating a Matcher without specifying
@@ -303,153 +494,10 @@ inline Matcher makeMatcher(MatcherInterface *Implementation) {
   return Matcher(Implementation);
 }
 
-template  class BindableMatcher;
-
-/// \brief Matcher that works on a \c DynTypedNode.
-///
-/// It is constructed from a \c Matcher object and redirects most calls to
-/// underlying matcher.
-/// It checks whether the \c DynTypedNode is convertible into the type of the
-/// underlying matcher and then do the actual match on the actual node, or
-/// return false if it is not convertible.
-class DynTypedMatcher {
-public:
-  /// \brief Construct from a \c Matcher. Copies the matcher.
-  template  inline DynTypedMatcher(const Matcher &M);
-
-  /// \brief Construct from a bindable \c Matcher. Copies the matcher.
-  ///
-  /// This version enables \c tryBind() on the \c DynTypedMatcher.
-  template  inline DynTypedMatcher(const BindableMatcher &M);
-
-  /// \brief Returns true if the matcher matches the given \c DynNode.
-  bool matches(const ast_type_traits::DynTypedNode DynNode,
-               ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const {
-    return Storage->matches(DynNode, Finder, Builder);
-  }
-
-  /// \brief Bind the specified \p ID to the matcher.
-  /// \return A new matcher with the \p ID bound to it if this matcher supports
-  ///   binding. Otherwise, returns an empty \c Optional<>.
-  llvm::Optional tryBind(StringRef ID) const {
-    return Storage->tryBind(ID);
-  }
-
-  /// \brief Returns a unique \p ID for the matcher.
-  uint64_t getID() const { return Storage->getID(); }
-
-  /// \brief Returns the type this matcher works on.
-  ///
-  /// \c matches() will always return false unless the node passed is of this
-  /// or a derived type.
-  ast_type_traits::ASTNodeKind getSupportedKind() const {
-    return Storage->getSupportedKind();
-  }
-
-  /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted
-  ///   to a \c Matcher.
-  ///
-  /// This method verifies that the underlying matcher in \c Other can process
-  /// nodes of types T.
-  template  bool canConvertTo() const {
-    return getSupportedKind().isBaseOf(
-        ast_type_traits::ASTNodeKind::getFromNodeKind());
-  }
-
-  /// \brief Construct a \c Matcher interface around the dynamic matcher.
-  ///
-  /// This method asserts that \c canConvertTo() is \c true. Callers
-  /// should call \c canConvertTo() first to make sure that \c this is
-  /// compatible with T.
-  template  Matcher convertTo() const {
-    assert(canConvertTo());
-    return unconditionalConvertTo();
-  }
-
-  /// \brief Same as \c convertTo(), but does not check that the underlying
-  ///   matcher can handle a value of T.
-  ///
-  /// If it is not compatible, then this matcher will never match anything.
-  template  Matcher unconditionalConvertTo() const;
-
-private:
-  class MatcherStorage : public RefCountedBaseVPTR {
-  public:
-    MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID)
-        : SupportedKind(SupportedKind), ID(ID) {}
-    virtual ~MatcherStorage();
-
-    virtual bool matches(const ast_type_traits::DynTypedNode DynNode,
-                         ASTMatchFinder *Finder,
-                         BoundNodesTreeBuilder *Builder) const = 0;
-
-    virtual llvm::Optional tryBind(StringRef ID) const = 0;
-
-    ast_type_traits::ASTNodeKind getSupportedKind() const {
-      return SupportedKind;
-    }
-
-    uint64_t getID() const { return ID; }
-
-  private:
-    const ast_type_traits::ASTNodeKind SupportedKind;
-    const uint64_t ID;
-  };
-
-  /// \brief Typed implementation of \c MatcherStorage.
-  template  class TypedMatcherStorage;
-
-  IntrusiveRefCntPtr Storage;
-};
-
-template 
-class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage {
-public:
-  TypedMatcherStorage(const Matcher &Other, bool AllowBind)
-      : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind(),
-                       Other.getID()),
-        InnerMatcher(Other), AllowBind(AllowBind) {}
-
-  bool matches(const ast_type_traits::DynTypedNode DynNode,
-               ASTMatchFinder *Finder,
-               BoundNodesTreeBuilder *Builder) const override {
-    if (const T *Node = DynNode.get()) {
-      return InnerMatcher.matches(*Node, Finder, Builder);
-    }
-    return false;
-  }
-
-  llvm::Optional tryBind(StringRef ID) const override {
-    if (!AllowBind)
-      return llvm::Optional();
-    return DynTypedMatcher(BindableMatcher(InnerMatcher).bind(ID));
-  }
-
-private:
-  const Matcher InnerMatcher;
-  const bool AllowBind;
-};
-
-template 
-inline DynTypedMatcher::DynTypedMatcher(const Matcher &M)
-    : Storage(new TypedMatcherStorage(M, false)) {}
-
-template 
-inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher &M)
-    : Storage(new TypedMatcherStorage(M, true)) {}
-
 /// \brief Specialization of the conversion functions for QualType.
 ///
-/// These specializations provide the Matcher->Matcher
+/// This specialization provides the Matcher->Matcher
 /// conversion that the static API does.
-template <> inline bool DynTypedMatcher::canConvertTo() const {
-  const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind();
-  return SourceKind.isSame(
-             ast_type_traits::ASTNodeKind::getFromNodeKind()) ||
-         SourceKind.isSame(
-             ast_type_traits::ASTNodeKind::getFromNodeKind());
-}
-
 template <>
 inline Matcher DynTypedMatcher::convertTo() const {
   assert(canConvertTo());
@@ -470,7 +518,7 @@ bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start,
   for (IteratorT I = Start; I != End; ++I) {
     BoundNodesTreeBuilder Result(*Builder);
     if (Matcher.matches(*I, Finder, &Result)) {
-      *Builder = Result;
+      *Builder = std::move(Result);
       return true;
     }
   }
@@ -486,7 +534,7 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start,
   for (IteratorT I = Start; I != End; ++I) {
     BoundNodesTreeBuilder Result(*Builder);
     if (Matcher.matches(**I, Finder, &Result)) {
-      *Builder = Result;
+      *Builder = std::move(Result);
       return true;
     }
   }
@@ -549,6 +597,33 @@ private:
   std::string Name;
 };
 
+/// \brief Matches named declarations with a specific name.
+///
+/// See \c hasName() in ASTMatchers.h for details.
+class HasNameMatcher : public SingleNodeMatcherInterface {
+ public:
+  explicit HasNameMatcher(StringRef Name);
+
+  bool matchesNode(const NamedDecl &Node) const override;
+
+ private:
+  /// \brief Unqualified match routine.
+  ///
+  /// It is much faster than the full match, but it only works for unqualified
+  /// matches.
+  bool matchesNodeUnqualified(const NamedDecl &Node) const;
+
+  /// \brief Full match routine
+  ///
+  /// It generates the fully qualified name of the declaration (which is
+  /// expensive) before trying to match.
+  /// It is slower but simple and works on all cases.
+  bool matchesNodeFull(const NamedDecl &Node) const;
+
+  const bool UseUnqualifiedMatch;
+  const std::string Name;
+};
+
 /// \brief Matches declarations for QualType and CallExpr.
 ///
 /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but
@@ -973,46 +1048,16 @@ private:
 ///
 /// This is useful when a matcher syntactically requires a child matcher,
 /// but the context doesn't care. See for example: anything().
-///
-/// FIXME: Alternatively we could also create a IsAMatcher or something
-/// that checks that a dyn_cast is possible. This is purely needed for the
-/// difference between calling for example:
-///   record()
-/// and
-///   record(SomeMatcher)
-/// In the second case we need the correct type we were dyn_cast'ed to in order
-/// to get the right type for the inner matcher. In the first case we don't need
-/// that, but we use the type conversion anyway and insert a TrueMatcher.
-template 
-class TrueMatcher : public SingleNodeMatcherInterface  {
-public:
-  bool matchesNode(const T &Node) const override {
-    return true;
-  }
-};
-
-/// \brief Matcher that wraps an inner Matcher and binds the matched node
-/// to an ID if the inner matcher matches on the node.
-template 
-class IdMatcher : public MatcherInterface {
-public:
-  /// \brief Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches
-  /// the node.
-  IdMatcher(StringRef ID, const Matcher &InnerMatcher)
-      : ID(ID), InnerMatcher(InnerMatcher) {}
+class TrueMatcher {
+ public:
+  typedef AllNodeBaseTypes ReturnTypes;
 
-  bool matches(const T &Node, ASTMatchFinder *Finder,
-               BoundNodesTreeBuilder *Builder) const override {
-    bool Result = InnerMatcher.matches(Node, Finder, Builder);
-    if (Result) {
-      Builder->setBinding(ID, &Node);
-    }
-    return Result;
+  template 
+  operator Matcher() const {
+    return DynTypedMatcher::trueMatcher(
+               ast_type_traits::ASTNodeKind::getFromNodeKind())
+        .template unconditionalConvertTo();
   }
-
-private:
-  const std::string ID;
-  const Matcher InnerMatcher;
 };
 
 /// \brief A Matcher that allows binding the node it matches to an id.
@@ -1031,7 +1076,17 @@ public:
   /// The returned matcher is equivalent to this matcher, but will
   /// bind the matched node on a match.
   Matcher bind(StringRef ID) const {
-    return Matcher(new IdMatcher(ID, *this));
+    return DynTypedMatcher(*this)
+        .tryBind(ID)
+        ->template unconditionalConvertTo();
+  }
+
+  /// \brief Same as Matcher's conversion operator, but enables binding on
+  /// the returned matcher.
+  operator DynTypedMatcher() const {
+    DynTypedMatcher Result = static_cast&>(*this);
+    Result.setAllowBind(true);
+    return Result;
   }
 };
 
@@ -1089,36 +1144,11 @@ private:
 /// \brief VariadicOperatorMatcher related types.
 /// @{
 
-/// \brief Function signature for any variadic operator. It takes the inner
-///   matchers as an array of DynTypedMatcher.
-typedef bool (*VariadicOperatorFunction)(
-    const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder,
-    BoundNodesTreeBuilder *Builder, ArrayRef InnerMatchers);
-
-/// \brief \c MatcherInterface implementation for an variadic operator.
-template 
-class VariadicOperatorMatcherInterface : public MatcherInterface {
-public:
-  VariadicOperatorMatcherInterface(VariadicOperatorFunction Func,
-                                   std::vector InnerMatchers)
-      : Func(Func), InnerMatchers(std::move(InnerMatchers)) {}
-
-  bool matches(const T &Node, ASTMatchFinder *Finder,
-               BoundNodesTreeBuilder *Builder) const override {
-    return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder,
-                InnerMatchers);
-  }
-
-private:
-  const VariadicOperatorFunction Func;
-  const std::vector InnerMatchers;
-};
-
 /// \brief "No argument" placeholder to use as template paratemers.
 struct VariadicOperatorNoArg {};
 
-/// \brief Polymorphic matcher object that uses a \c VariadicOperatorFunction
-///   operator.
+/// \brief Polymorphic matcher object that uses a \c
+/// DynTypedMatcher::VariadicOperator operator.
 ///
 /// Input matchers can have any type (including other polymorphic matcher
 /// types), and the actual Matcher is generated on demand with an implicit
@@ -1133,7 +1163,8 @@ template 
 class VariadicOperatorMatcher {
 public:
-  VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1,
+  VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
+                          const P1 &Param1,
                           const P2 &Param2 = VariadicOperatorNoArg(),
                           const P3 &Param3 = VariadicOperatorNoArg(),
                           const P4 &Param4 = VariadicOperatorNoArg(),
@@ -1142,7 +1173,7 @@ public:
                           const P7 &Param7 = VariadicOperatorNoArg(),
                           const P8 &Param8 = VariadicOperatorNoArg(),
                           const P9 &Param9 = VariadicOperatorNoArg())
-      : Func(Func), Param1(Param1), Param2(Param2), Param3(Param3),
+      : Op(Op), Param1(Param1), Param2(Param2), Param3(Param3),
         Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7),
         Param8(Param8), Param9(Param9) {}
 
@@ -1157,8 +1188,8 @@ public:
     addMatcher(Param7, Matchers);
     addMatcher(Param8, Matchers);
     addMatcher(Param9, Matchers);
-    return Matcher(
-        new VariadicOperatorMatcherInterface(Func, std::move(Matchers)));
+    return DynTypedMatcher::constructVariadic(Op, std::move(Matchers))
+        .template unconditionalConvertTo();
   }
 
 private:
@@ -1173,7 +1204,7 @@ private:
   static void addMatcher(VariadicOperatorNoArg,
                          std::vector &Matchers) {}
 
-  const VariadicOperatorFunction Func;
+  const DynTypedMatcher::VariadicOperator Op;
   const P1 Param1;
   const P2 Param2;
   const P3 Param3;
@@ -1191,7 +1222,7 @@ private:
 /// It supports 1-9 argument overloaded operator(). More can be added if needed.
 template 
 struct VariadicOperatorMatcherFunc {
-  VariadicOperatorFunction Func;
+  DynTypedMatcher::VariadicOperator Op;
 
   template 
   struct EnableIfValidArity
@@ -1200,30 +1231,29 @@ struct VariadicOperatorMatcherFunc {
   template 
   typename EnableIfValidArity<1, VariadicOperatorMatcher >::type
   operator()(const M1 &P1) const {
-    return VariadicOperatorMatcher(Func, P1);
+    return VariadicOperatorMatcher(Op, P1);
   }
   template 
   typename EnableIfValidArity<2, VariadicOperatorMatcher >::type
   operator()(const M1 &P1, const M2 &P2) const {
-    return VariadicOperatorMatcher(Func, P1, P2);
+    return VariadicOperatorMatcher(Op, P1, P2);
   }
   template 
   typename EnableIfValidArity<3, VariadicOperatorMatcher >::type
   operator()(const M1 &P1, const M2 &P2, const M3 &P3) const {
-    return VariadicOperatorMatcher(Func, P1, P2, P3);
+    return VariadicOperatorMatcher(Op, P1, P2, P3);
   }
   template 
   typename EnableIfValidArity<4, VariadicOperatorMatcher >::type
   operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const {
-    return VariadicOperatorMatcher(Func, P1, P2, P3, P4);
+    return VariadicOperatorMatcher(Op, P1, P2, P3, P4);
   }
   template 
   typename EnableIfValidArity<
       5, VariadicOperatorMatcher >::type
   operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
              const M5 &P5) const {
-    return VariadicOperatorMatcher(Func, P1, P2, P3, P4,
-                                                       P5);
+    return VariadicOperatorMatcher(Op, P1, P2, P3, P4, P5);
   }
   template 
@@ -1232,7 +1262,7 @@ struct VariadicOperatorMatcherFunc {
   operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
              const M5 &P5, const M6 &P6) const {
     return VariadicOperatorMatcher(
-        Func, P1, P2, P3, P4, P5, P6);
+        Op, P1, P2, P3, P4, P5, P6);
   }
   template 
@@ -1241,7 +1271,7 @@ struct VariadicOperatorMatcherFunc {
   operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
              const M5 &P5, const M6 &P6, const M7 &P7) const {
     return VariadicOperatorMatcher(
-        Func, P1, P2, P3, P4, P5, P6, P7);
+        Op, P1, P2, P3, P4, P5, P6, P7);
   }
   template 
@@ -1250,7 +1280,7 @@ struct VariadicOperatorMatcherFunc {
   operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4,
              const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8) const {
     return VariadicOperatorMatcher(
-        Func, P1, P2, P3, P4, P5, P6, P7, P8);
+        Op, P1, P2, P3, P4, P5, P6, P7, P8);
   }
   template 
@@ -1260,55 +1290,40 @@ struct VariadicOperatorMatcherFunc {
              const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8,
              const M9 &P9) const {
     return VariadicOperatorMatcher(
-        Func, P1, P2, P3, P4, P5, P6, P7, P8, P9);
+        Op, P1, P2, P3, P4, P5, P6, P7, P8, P9);
   }
 };
 
 /// @}
 
-/// \brief Matches nodes that do not match the provided matcher.
-///
-/// Uses the variadic matcher interface, but fails if InnerMatchers.size()!=1.
-bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode,
-                      ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder,
-                      ArrayRef InnerMatchers);
-
-/// \brief Matches nodes for which all provided matchers match.
-bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
-                           ASTMatchFinder *Finder,
-                           BoundNodesTreeBuilder *Builder,
-                           ArrayRef InnerMatchers);
-
-/// \brief Matches nodes for which at least one of the provided matchers
-/// matches, but doesn't stop at the first match.
-bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
-                            ASTMatchFinder *Finder,
-                            BoundNodesTreeBuilder *Builder,
-                            ArrayRef InnerMatchers);
-
-/// \brief Matches nodes for which at least one of the provided matchers
-/// matches.
-bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode,
-                           ASTMatchFinder *Finder,
-                           BoundNodesTreeBuilder *Builder,
-                           ArrayRef InnerMatchers);
-
 template 
 inline Matcher DynTypedMatcher::unconditionalConvertTo() const {
-  return Matcher(new VariadicOperatorMatcherInterface(
-      AllOfVariadicOperator, llvm::makeArrayRef(*this)));
+  return Matcher(*this);
 }
 
 /// \brief Creates a Matcher that matches if all inner matchers match.
 template
 BindableMatcher makeAllOfComposite(
     ArrayRef *> InnerMatchers) {
-  std::vector DynMatchers;
-  for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
-    DynMatchers.push_back(*InnerMatchers[i]);
+  // For the size() == 0 case, we return a "true" matcher.
+  if (InnerMatchers.size() == 0) {
+    return BindableMatcher(TrueMatcher());
+  }
+  // For the size() == 1 case, we simply return that one matcher.
+  // No need to wrap it in a variadic operation.
+  if (InnerMatchers.size() == 1) {
+    return BindableMatcher(*InnerMatchers[0]);
   }
-  return BindableMatcher(new VariadicOperatorMatcherInterface(
-      AllOfVariadicOperator, std::move(DynMatchers)));
+
+  std::vector DynMatchers;
+  DynMatchers.reserve(InnerMatchers.size());
+  for (const auto *InnerMatcher : InnerMatchers) {
+    DynMatchers.push_back(*InnerMatcher);
+  }
+  return BindableMatcher(
+      DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf,
+                                         std::move(DynMatchers))
+          .template unconditionalConvertTo());
 }
 
 /// \brief Creates a Matcher that matches if
@@ -1320,8 +1335,8 @@ BindableMatcher makeAllOfComposite(
 template
 BindableMatcher makeDynCastAllOfComposite(
     ArrayRef *> InnerMatchers) {
-  return BindableMatcher(DynTypedMatcher(makeAllOfComposite(InnerMatchers))
-                                .unconditionalConvertTo());
+  return BindableMatcher(
+      makeAllOfComposite(InnerMatchers).template dynCastTo());
 }
 
 /// \brief Matches nodes of type T that have at least one descendant node of
@@ -1606,6 +1621,23 @@ private:
   const Matcher InnerMatcher;
 };
 
+/// \brief A simple memoizer of T(*)() functions.
+///
+/// It will call the passed 'Func' template parameter at most once.
+/// Used to support AST_MATCHER_FUNCTION() macro.
+template  class MemoizedMatcher {
+  struct Wrapper {
+    Wrapper() : M(Func()) {}
+    Matcher M;
+  };
+
+public:
+  static const Matcher &getInstance() {
+    static llvm::ManagedStatic Instance;
+    return Instance->M;
+  }
+};
+
 // Define the create() method out of line to silence a GCC warning about
 // the struct "Func" having greater visibility than its base, which comes from
 // using the flag -fvisibility-inlines-hidden.
@@ -1627,7 +1659,7 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) {
 
 inline ArrayRef
 getTemplateSpecializationArgs(const TemplateSpecializationType &T) {
-  return ArrayRef(T.getArgs(), T.getNumArgs());
+  return llvm::makeArrayRef(T.getArgs(), T.getNumArgs());
 }
 
 struct NotEqualsBoundNodePredicate {
@@ -1642,4 +1674,4 @@ struct NotEqualsBoundNodePredicate {
 } // end namespace ast_matchers
 } // end namespace clang
 
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H
+#endif
diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h
index 563372a..b7888be 100644
--- a/include/clang/ASTMatchers/ASTMatchersMacros.h
+++ b/include/clang/ASTMatchers/ASTMatchersMacros.h
@@ -34,8 +34,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
-#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H
+
+/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) {
+/// defines a zero parameter function named DefineMatcher() that returns a
+/// ReturnType object.
+#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher)                        \
+  inline ReturnType DefineMatcher##_getInstance();                             \
+  inline ReturnType DefineMatcher() {                                          \
+    return internal::MemoizedMatcher<                                          \
+        ReturnType, DefineMatcher##_getInstance>::getInstance();               \
+  }                                                                            \
+  inline ReturnType DefineMatcher##_getInstance()
 
 /// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) {
 /// defines a single-parameter function named DefineMatcher() that returns a
@@ -352,4 +363,4 @@
       internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc;  \
   AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF)
 
-#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H
+#endif
diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
index 82a14f1..ef93ac5 100644
--- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h
+++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h
@@ -12,8 +12,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H
 
 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
 #include "clang/Basic/LLVM.h"
diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h
index 4045f57..bd006b6 100644
--- a/include/clang/ASTMatchers/Dynamic/Parser.h
+++ b/include/clang/ASTMatchers/Dynamic/Parser.h
@@ -31,8 +31,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H
 
 #include "clang/ASTMatchers/Dynamic/Diagnostics.h"
 #include "clang/ASTMatchers/Dynamic/Registry.h"
@@ -63,17 +63,6 @@ public:
   public:
     virtual ~Sema();
 
-    /// \brief Lookup a value by name.
-    ///
-    /// This can be used in the Sema layer to declare known constants or to
-    /// allow to split an expression in pieces.
-    ///
-    /// \param Name The name of the value to lookup.
-    ///
-    /// \return The named value. It could be any type that VariantValue
-    ///   supports. An empty value means that the name is not recognized.
-    virtual VariantValue getNamedValue(StringRef Name);
-
     /// \brief Process a matcher expression.
     ///
     /// All the arguments passed here have already been processed.
@@ -105,6 +94,29 @@ public:
     /// found.
     virtual llvm::Optional
     lookupMatcherCtor(StringRef MatcherName) = 0;
+
+    /// \brief Compute the list of completion types for \p Context.
+    ///
+    /// Each element of \p Context represents a matcher invocation, going from
+    /// outermost to innermost. Elements are pairs consisting of a reference to
+    /// the matcher constructor and the index of the next element in the
+    /// argument list of that matcher (or for the last element, the index of
+    /// the completion point in the argument list). An empty list requests
+    /// completion for the root matcher.
+    virtual std::vector getAcceptedCompletionTypes(
+        llvm::ArrayRef> Context);
+
+    /// \brief Compute the list of completions that match any of
+    /// \p AcceptedTypes.
+    ///
+    /// \param AcceptedTypes All types accepted for this completion.
+    ///
+    /// \return All completions for the specified types.
+    /// Completions should be valid when used in \c lookupMatcherCtor().
+    /// The matcher constructed from the return of \c lookupMatcherCtor()
+    /// should be convertible to some type in \p AcceptedTypes.
+    virtual std::vector
+    getMatcherCompletions(llvm::ArrayRef AcceptedTypes);
   };
 
   /// \brief Sema implementation that uses the matcher registry to process the
@@ -121,58 +133,91 @@ public:
                                           StringRef BindID,
                                           ArrayRef Args,
                                           Diagnostics *Error) override;
+
+    std::vector getAcceptedCompletionTypes(
+        llvm::ArrayRef> Context) override;
+
+    std::vector
+    getMatcherCompletions(llvm::ArrayRef AcceptedTypes) override;
   };
 
-  /// \brief Parse a matcher expression, creating matchers from the registry.
-  ///
-  /// This overload creates matchers calling directly into the registry. If the
-  /// caller needs more control over how the matchers are created, then it can
-  /// use the overload below that takes a Sema.
-  ///
-  /// \param MatcherCode The matcher expression to parse.
-  ///
-  /// \return The matcher object constructed, or an empty Optional if an error
-  ///   occurred.
-  ///   In that case, \c Error will contain a description of the error.
-  ///   The caller takes ownership of the DynTypedMatcher object returned.
-  static llvm::Optional
-  parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error);
+  typedef llvm::StringMap NamedValueMap;
 
   /// \brief Parse a matcher expression.
   ///
   /// \param MatcherCode The matcher expression to parse.
   ///
   /// \param S The Sema instance that will help the parser
-  ///   construct the matchers.
+  ///   construct the matchers. If null, it uses the default registry.
+  ///
+  /// \param NamedValues A map of precomputed named values.  This provides
+  ///   the dictionary for the  rule of the grammar.
+  ///   If null, it is ignored.
+  ///
   /// \return The matcher object constructed by the processor, or an empty
   ///   Optional if an error occurred. In that case, \c Error will contain a
   ///   description of the error.
   ///   The caller takes ownership of the DynTypedMatcher object returned.
   static llvm::Optional
-  parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error);
-
-  /// \brief Parse an expression, creating matchers from the registry.
-  ///
-  /// Parses any expression supported by this parser. In general, the
-  /// \c parseMatcherExpression function is a better approach to get a matcher
-  /// object.
-  static bool parseExpression(StringRef Code, VariantValue *Value,
-                              Diagnostics *Error);
+  parseMatcherExpression(StringRef MatcherCode, Sema *S,
+                         const NamedValueMap *NamedValues,
+                         Diagnostics *Error);
+  static llvm::Optional
+  parseMatcherExpression(StringRef MatcherCode, Sema *S,
+                         Diagnostics *Error) {
+    return parseMatcherExpression(MatcherCode, S, nullptr, Error);
+  }
+  static llvm::Optional
+  parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) {
+    return parseMatcherExpression(MatcherCode, nullptr, Error);
+  }
 
   /// \brief Parse an expression.
   ///
   /// Parses any expression supported by this parser. In general, the
   /// \c parseMatcherExpression function is a better approach to get a matcher
   /// object.
+  ///
+  /// \param S The Sema instance that will help the parser
+  ///   construct the matchers. If null, it uses the default registry.
+  ///
+  /// \param NamedValues A map of precomputed named values.  This provides
+  ///   the dictionary for the  rule of the grammar.
+  ///   If null, it is ignored.
   static bool parseExpression(StringRef Code, Sema *S,
+                              const NamedValueMap *NamedValues,
                               VariantValue *Value, Diagnostics *Error);
+  static bool parseExpression(StringRef Code, Sema *S,
+                              VariantValue *Value, Diagnostics *Error) {
+    return parseExpression(Code, S, nullptr, Value, Error);
+  }
+  static bool parseExpression(StringRef Code, VariantValue *Value,
+                              Diagnostics *Error) {
+    return parseExpression(Code, nullptr, Value, Error);
+  }
 
   /// \brief Complete an expression at the given offset.
   ///
+  /// \param S The Sema instance that will help the parser
+  ///   construct the matchers. If null, it uses the default registry.
+  ///
+  /// \param NamedValues A map of precomputed named values.  This provides
+  ///   the dictionary for the  rule of the grammar.
+  ///   If null, it is ignored.
+  ///
   /// \return The list of completions, which may be empty if there are no
   /// available completions or if an error occurred.
   static std::vector
-  completeExpression(StringRef Code, unsigned CompletionOffset);
+  completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S,
+                     const NamedValueMap *NamedValues);
+  static std::vector
+  completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) {
+    return completeExpression(Code, CompletionOffset, S, nullptr);
+  }
+  static std::vector
+  completeExpression(StringRef Code, unsigned CompletionOffset) {
+    return completeExpression(Code, CompletionOffset, nullptr);
+  }
 
 private:
   class CodeTokenizer;
@@ -180,6 +225,7 @@ private:
   struct TokenInfo;
 
   Parser(CodeTokenizer *Tokenizer, Sema *S,
+         const NamedValueMap *NamedValues,
          Diagnostics *Error);
 
   bool parseExpressionImpl(VariantValue *Value);
@@ -187,12 +233,16 @@ private:
                                   VariantValue *Value);
   bool parseIdentifierPrefixImpl(VariantValue *Value);
 
-  void addCompletion(const TokenInfo &CompToken, StringRef TypedText,
-                     StringRef Decl);
+  void addCompletion(const TokenInfo &CompToken,
+                     const MatcherCompletion &Completion);
   void addExpressionCompletions();
 
+  std::vector
+  getNamedValueCompletions(ArrayRef AcceptedTypes);
+
   CodeTokenizer *const Tokenizer;
   Sema *const S;
+  const NamedValueMap *const NamedValues;
   Diagnostics *const Error;
 
   typedef std::vector > ContextStackTy;
diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h
index faa9254..ad24a8d 100644
--- a/include/clang/ASTMatchers/Dynamic/Registry.h
+++ b/include/clang/ASTMatchers/Dynamic/Registry.h
@@ -14,8 +14,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H
 
 #include "clang/ASTMatchers/Dynamic/Diagnostics.h"
 #include "clang/ASTMatchers/Dynamic/VariantValue.h"
@@ -36,8 +36,10 @@ typedef const internal::MatcherDescriptor *MatcherCtor;
 
 struct MatcherCompletion {
   MatcherCompletion() {}
-  MatcherCompletion(StringRef TypedText, StringRef MatcherDecl)
-      : TypedText(TypedText), MatcherDecl(MatcherDecl) {}
+  MatcherCompletion(StringRef TypedText, StringRef MatcherDecl,
+                    unsigned Specificity)
+      : TypedText(TypedText), MatcherDecl(MatcherDecl),
+        Specificity(Specificity) {}
 
   /// \brief The text to type to select this matcher.
   std::string TypedText;
@@ -45,6 +47,13 @@ struct MatcherCompletion {
   /// \brief The "declaration" of the matcher, with type information.
   std::string MatcherDecl;
 
+  /// \brief Value corresponding to the "specificity" of the converted matcher.
+  ///
+  /// Zero specificity indicates that this conversion would produce a trivial
+  /// matcher that will either always or never match.
+  /// Such matchers are excluded from code completion results.
+  unsigned Specificity;
+
   bool operator==(const MatcherCompletion &Other) const {
     return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl;
   }
@@ -58,28 +67,28 @@ public:
   /// constructor, or Optional() if not found.
   static llvm::Optional lookupMatcherCtor(StringRef MatcherName);
 
-  /// \brief Compute the list of completions for \p Context.
+  /// \brief Compute the list of completion types for \p Context.
   ///
   /// Each element of \p Context represents a matcher invocation, going from
-  /// outermost to innermost. Elements are pairs consisting of a reference to the
-  /// matcher constructor and the index of the next element in the argument list
-  /// of that matcher (or for the last element, the index of the completion
-  /// point in the argument list). An empty list requests completion for the
-  /// root matcher.
+  /// outermost to innermost. Elements are pairs consisting of a reference to
+  /// the matcher constructor and the index of the next element in the
+  /// argument list of that matcher (or for the last element, the index of
+  /// the completion point in the argument list). An empty list requests
+  /// completion for the root matcher.
+  static std::vector getAcceptedCompletionTypes(
+      llvm::ArrayRef> Context);
+
+  /// \brief Compute the list of completions that match any of
+  /// \p AcceptedTypes.
   ///
-  /// The completions are ordered first by decreasing relevance, then
-  /// alphabetically.  Relevance is determined by how closely the matcher's
-  /// type matches that of the context. For example, if the innermost matcher
-  /// takes a FunctionDecl matcher, the FunctionDecl matchers are returned
-  /// first, followed by the ValueDecl matchers, then NamedDecl, then Decl, then
-  /// polymorphic matchers.
+  /// \param AcceptedTypes All types accepted for this completion.
   ///
-  /// Matchers which are technically convertible to the innermost context but
-  /// which would match either all or no nodes are excluded. For example,
-  /// namedDecl and varDecl are excluded in a FunctionDecl context, because
-  /// those matchers would match respectively all or no nodes in such a context.
+  /// \return All completions for the specified types.
+  /// Completions should be valid when used in \c lookupMatcherCtor().
+  /// The matcher constructed from the return of \c lookupMatcherCtor()
+  /// should be convertible to some type in \p AcceptedTypes.
   static std::vector
-  getCompletions(ArrayRef > Context);
+  getMatcherCompletions(ArrayRef AcceptedTypes);
 
   /// \brief Construct a matcher from the registry.
   ///
diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h
index b25267b..a9bd3d5 100644
--- a/include/clang/ASTMatchers/Dynamic/VariantValue.h
+++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h
@@ -14,8 +14,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
-#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H
+#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
+#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H
 
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/ASTMatchers/ASTMatchersInternal.h"
@@ -29,6 +29,51 @@ namespace clang {
 namespace ast_matchers {
 namespace dynamic {
 
+/// \brief Kind identifier.
+///
+/// It supports all types that VariantValue can contain.
+class ArgKind {
+ public:
+  enum Kind {
+    AK_Matcher,
+    AK_Unsigned,
+    AK_String
+  };
+  /// \brief Constructor for non-matcher types.
+  ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); }
+
+  /// \brief Constructor for matcher types.
+  ArgKind(ast_type_traits::ASTNodeKind MatcherKind)
+      : K(AK_Matcher), MatcherKind(MatcherKind) {}
+
+  Kind getArgKind() const { return K; }
+  ast_type_traits::ASTNodeKind getMatcherKind() const {
+    assert(K == AK_Matcher);
+    return MatcherKind;
+  }
+
+  /// \brief Determines if this type can be converted to \p To.
+  ///
+  /// \param To the requested destination type.
+  ///
+  /// \param Specificity value corresponding to the "specificity" of the
+  ///   convertion.
+  bool isConvertibleTo(ArgKind To, unsigned *Specificity) const;
+
+  bool operator<(const ArgKind &Other) const {
+    if (K == AK_Matcher && Other.K == AK_Matcher)
+      return MatcherKind < Other.MatcherKind;
+    return K < Other.K;
+  }
+
+  /// \brief String representation of the type.
+  std::string asString() const;
+
+private:
+  Kind K;
+  ast_type_traits::ASTNodeKind MatcherKind;
+};
+
 using ast_matchers::internal::DynTypedMatcher;
 
 /// \brief A variant matcher object.
@@ -48,13 +93,28 @@ class VariantMatcher {
   /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher.
   class MatcherOps {
   public:
-    virtual ~MatcherOps();
-    virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
-                                  bool &IsExactMatch) const = 0;
-    virtual void constructFrom(const DynTypedMatcher &Matcher) = 0;
-    virtual void constructVariadicOperator(
-        ast_matchers::internal::VariadicOperatorFunction Func,
-        ArrayRef InnerMatchers) = 0;
+    MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {}
+
+    bool canConstructFrom(const DynTypedMatcher &Matcher,
+                          bool &IsExactMatch) const;
+
+    /// \brief Convert \p Matcher the destination type and return it as a new
+    /// DynTypedMatcher.
+    virtual DynTypedMatcher
+    convertMatcher(const DynTypedMatcher &Matcher) const = 0;
+
+    /// \brief Constructs a variadic typed matcher from \p InnerMatchers.
+    /// Will try to convert each inner matcher to the destination type and
+    /// return llvm::None if it fails to do so.
+    llvm::Optional
+    constructVariadicOperator(DynTypedMatcher::VariadicOperator Op,
+                              ArrayRef InnerMatchers) const;
+
+  protected:
+    ~MatcherOps() {}
+
+  private:
+    ast_type_traits::ASTNodeKind NodeKind;
   };
 
   /// \brief Payload interface to be specialized by each matcher type.
@@ -65,7 +125,10 @@ class VariantMatcher {
     virtual ~Payload();
     virtual llvm::Optional getSingleMatcher() const = 0;
     virtual std::string getTypeAsString() const = 0;
-    virtual void makeTypedMatcher(MatcherOps &Ops) const = 0;
+    virtual llvm::Optional
+    getTypedMatcher(const MatcherOps &Ops) const = 0;
+    virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+                                 unsigned *Specificity) const = 0;
   };
 
 public:
@@ -84,9 +147,9 @@ public:
   /// \brief Creates a 'variadic' operator matcher.
   ///
   /// It will bind to the appropriate type on getTypedMatcher().
-  static VariantMatcher VariadicOperatorMatcher(
-      ast_matchers::internal::VariadicOperatorFunction Func,
-      std::vector Args);
+  static VariantMatcher
+  VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op,
+                          std::vector Args);
 
   /// \brief Makes the matcher the "null" matcher.
   void reset();
@@ -111,9 +174,21 @@ public:
   /// that can, the result would be ambiguous and false is returned.
   template 
   bool hasTypedMatcher() const {
-    TypedMatcherOps Ops;
-    if (Value) Value->makeTypedMatcher(Ops);
-    return Ops.hasMatcher();
+    if (!Value) return false;
+    return Value->getTypedMatcher(TypedMatcherOps()).hasValue();
+  }
+
+  /// \brief Determines if the contained matcher can be converted to \p Kind.
+  ///
+  /// \param Kind the requested destination type.
+  ///
+  /// \param Specificity value corresponding to the "specificity" of the
+  ///   convertion.
+  bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind,
+                       unsigned *Specificity) const {
+    if (Value)
+      return Value->isConvertibleTo(Kind, Specificity);
+    return false;
   }
 
   /// \brief Return this matcher as a \c Matcher.
@@ -122,10 +197,9 @@ public:
   /// Asserts that \c hasTypedMatcher() is true.
   template 
   ast_matchers::internal::Matcher getTypedMatcher() const {
-    TypedMatcherOps Ops;
-    Value->makeTypedMatcher(Ops);
-    assert(Ops.hasMatcher() && "hasTypedMatcher() == false");
-    return Ops.matcher();
+    assert(hasTypedMatcher() && "hasTypedMatcher() == false");
+    return Value->getTypedMatcher(TypedMatcherOps())
+        ->template convertTo();
   }
 
   /// \brief String representation of the type of the value.
@@ -137,51 +211,25 @@ public:
 private:
   explicit VariantMatcher(Payload *Value) : Value(Value) {}
 
+  template  struct TypedMatcherOps;
+
   class SinglePayload;
   class PolymorphicPayload;
   class VariadicOpPayload;
 
-  template 
-  class TypedMatcherOps : public MatcherOps {
-  public:
-    typedef ast_matchers::internal::Matcher MatcherT;
-
-    virtual bool canConstructFrom(const DynTypedMatcher &Matcher,
-                                  bool &IsExactMatch) const {
-      IsExactMatch = Matcher.getSupportedKind().isSame(
-          ast_type_traits::ASTNodeKind::getFromNodeKind());
-      return Matcher.canConvertTo();
-    }
-
-    virtual void constructFrom(const DynTypedMatcher& Matcher) {
-      Out.reset(new MatcherT(Matcher.convertTo()));
-    }
-
-    virtual void constructVariadicOperator(
-        ast_matchers::internal::VariadicOperatorFunction Func,
-        ArrayRef InnerMatchers) {
-      std::vector DynMatchers;
-      for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) {
-        // Abort if any of the inner matchers can't be converted to
-        // Matcher.
-        if (!InnerMatchers[i].hasTypedMatcher()) {
-          return;
-        }
-        DynMatchers.push_back(InnerMatchers[i].getTypedMatcher());
-      }
-      Out.reset(new MatcherT(
-          new ast_matchers::internal::VariadicOperatorMatcherInterface(
-              Func, DynMatchers)));
-    }
-
-    bool hasMatcher() const { return Out.get() != nullptr; }
-    const MatcherT &matcher() const { return *Out; }
+  IntrusiveRefCntPtr Value;
+};
 
-  private:
-    std::unique_ptr Out;
-  };
+template 
+struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps {
+  TypedMatcherOps()
+      : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind()) {}
+  typedef ast_matchers::internal::Matcher MatcherT;
 
-  IntrusiveRefCntPtr Value;
+  DynTypedMatcher
+  convertMatcher(const DynTypedMatcher &Matcher) const override {
+    return DynTypedMatcher(Matcher.convertTo());
+  }
 };
 
 /// \brief Variant value class.
@@ -228,6 +276,24 @@ public:
   const VariantMatcher &getMatcher() const;
   void setMatcher(const VariantMatcher &Matcher);
 
+  /// \brief Determines if the contained value can be converted to \p Kind.
+  ///
+  /// \param Kind the requested destination type.
+  ///
+  /// \param Specificity value corresponding to the "specificity" of the
+  ///   convertion.
+  bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const;
+
+  /// \brief Determines if the contained value can be converted to any kind
+  /// in \p Kinds.
+  ///
+  /// \param Kinds the requested destination types.
+  ///
+  /// \param Specificity value corresponding to the "specificity" of the
+  ///   convertion. It is the maximum specificity of all the possible
+  ///   conversions.
+  bool isConvertibleTo(ArrayRef Kinds, unsigned *Specificity) const;
+
   /// \brief String representation of the type of the value.
   std::string getTypeAsString() const;
 
diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
index a61d9e4..cc14c7b 100644
--- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
+++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h
@@ -13,8 +13,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef CLANG_ANALYSIS_CFG_REACHABILITY
-#define CLANG_ANALYSIS_CFG_REACHABILITY
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H
 
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h
index 36e07c2..a710923 100644
--- a/include/clang/Analysis/Analyses/Consumed.h
+++ b/include/clang/Analysis/Analyses/Consumed.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_CONSUMED_H
-#define LLVM_CLANG_CONSUMED_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
 
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ExprCXX.h"
diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h
index 6c6d923..fcef0fc 100644
--- a/include/clang/Analysis/Analyses/Dominators.h
+++ b/include/clang/Analysis/Analyses/Dominators.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_DOMINATORS_H
-#define LLVM_CLANG_DOMINATORS_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H
 
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/CFG.h"
diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h
index 76fe9dd..174cce4 100644
--- a/include/clang/Analysis/Analyses/FormatString.h
+++ b/include/clang/Analysis/Analyses/FormatString.h
@@ -16,8 +16,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_FORMAT_H
-#define LLVM_CLANG_FORMAT_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H
 
 #include "clang/AST/CanonicalType.h"
 
@@ -79,6 +79,7 @@ public:
     AsLongDouble, // 'L'
     AsAllocate,   // for '%as', GNU extension to C90 scanf
     AsMAllocate,  // for '%ms', GNU extension to scanf
+    AsWide,       // 'w' (MSVCRT, like l but only for c, C, s, S, or Z
     AsWideChar = AsLong // for '%ls', only makes sense for printf
   };
 
@@ -154,6 +155,8 @@ public:
 
     // ** Printf-specific **
 
+    ZArg, // MS extension
+
     // Objective-C specific specifiers.
     ObjCObjArg,  // '@'
     ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
@@ -644,6 +647,9 @@ public:
 bool ParsePrintfString(FormatStringHandler &H,
                        const char *beg, const char *end, const LangOptions &LO,
                        const TargetInfo &Target);
+  
+bool ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO,
+                              const TargetInfo &Target);
 
 bool ParseScanfString(FormatStringHandler &H,
                       const char *beg, const char *end, const LangOptions &LO,
diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h
index 7842271..c29dd40 100644
--- a/include/clang/Analysis/Analyses/LiveVariables.h
+++ b/include/clang/Analysis/Analyses/LiveVariables.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_LIVEVARIABLES_H
-#define LLVM_CLANG_LIVEVARIABLES_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H
 
 #include "clang/AST/Decl.h"
 #include "clang/Analysis/AnalysisContext.h"
diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h
index 91bf51c..a1c6504 100644
--- a/include/clang/Analysis/Analyses/PostOrderCFGView.h
+++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_POSTORDER_CFGVIEW
-#define LLVM_CLANG_POSTORDER_CFGVIEW
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H
 
 #include 
 //#include 
@@ -47,17 +47,17 @@ public:
 
     /// \brief Set the bit associated with a particular CFGBlock.
     /// This is the important method for the SetType template parameter.
-    bool insert(const CFGBlock *Block) {
+    std::pair insert(const CFGBlock *Block) {
       // Note that insert() is called by po_iterator, which doesn't check to
       // make sure that Block is non-null.  Moreover, the CFGBlock iterator will
       // occasionally hand out null pointers for pruned edges, so we catch those
       // here.
       if (!Block)
-        return false;  // if an edge is trivially false.
+        return std::make_pair(None, false); // if an edge is trivially false.
       if (VisitedBlockIDs.test(Block->getBlockID()))
-        return false;
+        return std::make_pair(None, false);
       VisitedBlockIDs.set(Block->getBlockID());
-      return true;
+      return std::make_pair(None, true);
     }
 
     /// \brief Check if the bit for a CFGBlock has been already set.
diff --git a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
index cb73850..c4ec2f2 100644
--- a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
+++ b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h
@@ -13,8 +13,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
-#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H
 
 #include "clang/AST/Stmt.h"
 
diff --git a/include/clang/Analysis/Analyses/ReachableCode.h b/include/clang/Analysis/Analyses/ReachableCode.h
index 90a6d01..4c523bf 100644
--- a/include/clang/Analysis/Analyses/ReachableCode.h
+++ b/include/clang/Analysis/Analyses/ReachableCode.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_REACHABLECODE_H
-#define LLVM_CLANG_REACHABLECODE_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H
 
 #include "clang/Basic/SourceLocation.h"
 
diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h
index b533c1d..458bb57 100644
--- a/include/clang/Analysis/Analyses/ThreadSafety.h
+++ b/include/clang/Analysis/Analyses/ThreadSafety.h
@@ -16,31 +16,33 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_THREADSAFETY_H
-#define LLVM_CLANG_THREADSAFETY_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H
 
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/StringRef.h"
 
 namespace clang {
-namespace thread_safety {
+namespace threadSafety {
 
 /// This enum distinguishes between different kinds of operations that may
 /// need to be protected by locks. We use this enum in error handling.
 enum ProtectedOperationKind {
   POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;)
   POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;)
-  POK_FunctionCall ///< Making a function call (e.g. fool())
+  POK_FunctionCall, ///< Making a function call (e.g. fool())
+  POK_PassByRef, ///< Passing a guarded variable by reference.
+  POK_PtPassByRef,  ///< Passing a pt-guarded variable by reference.
 };
 
 /// This enum distinguishes between different kinds of lock actions. For
 /// example, it is an error to write a variable protected by shared version of a
 /// mutex.
 enum LockKind {
-  LK_Shared, ///< Shared/reader lock of a mutex.
+  LK_Shared,    ///< Shared/reader lock of a mutex.
   LK_Exclusive, ///< Exclusive/writer lock of a mutex.
-  LK_Generic  ///<  Can be either Shared or Exclusive
+  LK_Generic    ///< Can be either Shared or Exclusive
 };
 
 /// This enum distinguishes between different ways to access (read or write) a
@@ -161,6 +163,16 @@ public:
                                   LockKind LK, SourceLocation Loc,
                                   Name *PossibleMatch = nullptr) {}
 
+  /// Warn when acquiring a lock that the negative capability is not held.
+  /// \param Kind -- the capability's name parameter (role, mutex, etc).
+  /// \param LockName -- The name for the lock expression, to be printed in the
+  /// diagnostic.
+  /// \param Neg -- The name of the negative capability to be printed in the
+  /// diagnostic.
+  /// \param Loc -- The location of the protected operation.
+  virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg,
+                                     SourceLocation Loc) {}
+
   /// Warn when a function is called while an excluded mutex is locked. For
   /// example, the mutex may be locked inside the function.
   /// \param Kind -- the capability's name parameter (role, mutex, etc).
@@ -171,6 +183,13 @@ public:
   virtual void handleFunExcludesLock(StringRef Kind, Name FunName,
                                      Name LockName, SourceLocation Loc) {}
 
+  /// Called by the analysis when starting analysis of a function.
+  /// Used to issue suggestions for changes to annotations.
+  virtual void enterFunction(const FunctionDecl *FD) {}
+
+  /// Called by the analysis when finishing analysis of a function.
+  virtual void leaveFunction(const FunctionDecl *FD) {}
+
   bool issueBetaWarnings() { return IssueBetaWarnings; }
   void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; }
 
@@ -190,5 +209,5 @@ void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
 /// of access.
 LockKind getLockKindFromAccessKind(AccessKind AK);
 
-}} // end namespace clang::thread_safety
+}} // end namespace clang::threadSafety
 #endif
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
index 09c614c..be81121 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -19,21 +19,63 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_THREAD_SAFETY_COMMON_H
-#define LLVM_CLANG_THREAD_SAFETY_COMMON_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H
 
 #include "clang/Analysis/Analyses/PostOrderCFGView.h"
 #include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
+#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Basic/OperatorKinds.h"
-
 #include 
+#include 
+#include 
 #include 
 
 
 namespace clang {
 namespace threadSafety {
 
+
+// Various helper functions on til::SExpr
+namespace sx {
+
+inline bool equals(const til::SExpr *E1, const til::SExpr *E2) {
+  return til::EqualsComparator::compareExprs(E1, E2);
+}
+
+inline bool matches(const til::SExpr *E1, const til::SExpr *E2) {
+  // We treat a top-level wildcard as the "univsersal" lock.
+  // It matches everything for the purpose of checking locks, but not
+  // for unlocking them.
+  if (isa(E1))
+    return isa(E2);
+  if (isa(E2))
+    return isa(E1);
+
+  return til::MatchComparator::compareExprs(E1, E2);
+}
+
+inline bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2) {
+  const auto *PE1 = dyn_cast_or_null(E1);
+  if (!PE1)
+    return false;
+  const auto *PE2 = dyn_cast_or_null(E2);
+  if (!PE2)
+    return false;
+  return PE1->clangDecl() == PE2->clangDecl();
+}
+
+inline std::string toString(const til::SExpr *E) {
+  std::stringstream ss;
+  til::StdPrinter::print(E, ss);
+  return ss.str();
+}
+
+}  // end namespace sx
+
+
+
 // This class defines the interface of a clang CFG Visitor.
 // CFGWalker will invoke the following methods.
 // Note that methods are not virtual; the visitor is templatized.
@@ -206,6 +248,59 @@ private:
 };
 
 
+
+
+class CapabilityExpr {
+  // TODO: move this back into ThreadSafety.cpp
+  // This is specific to thread safety.  It is here because
+  // translateAttrExpr needs it, but that should be moved too.
+
+private:
+  const til::SExpr* CapExpr;   ///< The capability expression.
+  bool Negated;                ///< True if this is a negative capability
+
+public:
+  CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {}
+
+  const til::SExpr* sexpr()    const { return CapExpr; }
+  bool              negative() const { return Negated; }
+
+  CapabilityExpr operator!() const {
+    return CapabilityExpr(CapExpr, !Negated);
+  }
+
+  bool equals(const CapabilityExpr &other) const {
+    return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr);
+  }
+
+  bool matches(const CapabilityExpr &other) const {
+    return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr);
+  }
+
+  bool matchesUniv(const CapabilityExpr &CapE) const {
+    return isUniversal() || matches(CapE);
+  }
+
+  bool partiallyMatches(const CapabilityExpr &other) const {
+    return (Negated == other.Negated) &&
+            sx::partiallyMatches(CapExpr, other.CapExpr);
+  }
+
+  std::string toString() const {
+    if (Negated)
+      return "!" + sx::toString(CapExpr);
+    return sx::toString(CapExpr);
+  }
+
+  bool shouldIgnore() const { return CapExpr == nullptr; }
+
+  bool isInvalid() const { return sexpr() && isa(sexpr()); }
+
+  bool isUniversal() const { return sexpr() && isa(sexpr()); }
+};
+
+
+
 // Translate clang::Expr to til::SExpr.
 class SExprBuilder {
 public:
@@ -219,18 +314,16 @@ public:
   /// should be evaluated; multiple calling contexts can be chained together
   /// by the lock_returned attribute.
   struct CallingContext {
+    CallingContext  *Prev;      // The previous context; or 0 if none.
     const NamedDecl *AttrDecl;  // The decl to which the attr is attached.
     const Expr *SelfArg;        // Implicit object argument -- e.g. 'this'
     unsigned NumArgs;           // Number of funArgs
     const Expr *const *FunArgs; // Function arguments
-    CallingContext *Prev;       // The previous context; or 0 if none.
     bool SelfArrow;             // is Self referred to with -> or .?
 
-    CallingContext(const NamedDecl *D = nullptr, const Expr *S = nullptr,
-                   unsigned N = 0, const Expr *const *A = nullptr,
-                   CallingContext *P = nullptr)
-        : AttrDecl(D), SelfArg(S), NumArgs(N), FunArgs(A), Prev(P),
-          SelfArrow(false)
+    CallingContext(CallingContext *P, const NamedDecl *D = nullptr)
+        : Prev(P), AttrDecl(D), SelfArg(nullptr),
+          NumArgs(0), FunArgs(nullptr), SelfArrow(false)
     {}
   };
 
@@ -242,6 +335,13 @@ public:
     SelfVar->setKind(til::Variable::VK_SFun);
   }
 
+  // Translate a clang expression in an attribute to a til::SExpr.
+  // Constructs the context from D, DeclExp, and SelfDecl.
+  CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D,
+                                   const Expr *DeclExp, VarDecl *SelfD=nullptr);
+
+  CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx);
+
   // Translate a clang statement or expression to a TIL expression.
   // Also performs substitution of variables; Ctx provides the context.
   // Dispatches on the type of S.
@@ -262,7 +362,8 @@ private:
                                    CallingContext *Ctx) ;
   til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx);
   til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx);
-  til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx);
+  til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx,
+                                const Expr *SelfE = nullptr);
   til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME,
                                          CallingContext *Ctx);
   til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE,
@@ -280,10 +381,8 @@ private:
   til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx);
   til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E,
                                           CallingContext *Ctx);
-  til::SExpr *translateConditionalOperator(const ConditionalOperator *C,
-                                           CallingContext *Ctx);
-  til::SExpr *translateBinaryConditionalOperator(
-      const BinaryConditionalOperator *C, CallingContext *Ctx);
+  til::SExpr *translateAbstractConditionalOperator(
+      const AbstractConditionalOperator *C, CallingContext *Ctx);
 
   til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx);
 
@@ -362,21 +461,24 @@ private:
   void mergePhiNodesBackEdge(const CFGBlock *Blk);
 
 private:
+  // Set to true when parsing capability expressions, which get translated
+  // inaccurately in order to hack around smart pointers etc.
+  static const bool CapabilityExprMode = true;
+
   til::MemRegionRef Arena;
   til::Variable *SelfVar;       // Variable to use for 'this'.  May be null.
-  til::SCFG *Scfg;
 
+  til::SCFG *Scfg;
   StatementMap SMap;                       // Map from Stmt to TIL Variables
   LVarIndexMap LVarIdxMap;                 // Indices of clang local vars.
   std::vector BlockMap; // Map from clang to til BBs.
   std::vector BBInfo;           // Extra information per BB.
                                            // Indexed by clang BlockID.
-  std::unique_ptr CallCtx; // Root calling context
 
   LVarDefinitionMap CurrentLVarMap;
-  std::vector CurrentArguments;
-  std::vector CurrentInstructions;
-  std::vector IncompleteArgs;
+  std::vector   CurrentArguments;
+  std::vector CurrentInstructions;
+  std::vector   IncompleteArgs;
   til::BasicBlock *CurrentBB;
   BlockInfo *CurrentBlockInfo;
 };
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
index c4f4b21..bc78021 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h
@@ -10,8 +10,8 @@
 // that are used as part of fact-checking capability expressions.
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_THREAD_SAFETY_LOGICAL_H
-#define LLVM_CLANG_THREAD_SAFETY_LOGICAL_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H
 
 #include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
 
@@ -41,13 +41,13 @@ private:
 };
 
 class Terminal : public LExpr {
-  til::SExprRef Expr;
+  til::SExpr *Expr;
 
 public:
   Terminal(til::SExpr *Expr) : LExpr(LExpr::Terminal), Expr(Expr) {}
 
-  const til::SExpr *expr() const { return Expr.get(); }
-  til::SExpr *expr() { return Expr.get(); }
+  const til::SExpr *expr() const { return Expr; }
+  til::SExpr *expr() { return Expr; }
 
   static bool classof(const LExpr *E) { return E->kind() == LExpr::Terminal; }
 };
@@ -104,5 +104,5 @@ bool LExpr::implies(const LExpr *RHS) const {
 }
 }
 
-#endif // LLVM_CLANG_THREAD_SAFETY_LOGICAL_H
+#endif
 
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyOps.def b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
index 6ebc95d..0d2458b 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyOps.def
+++ b/include/clang/Analysis/Analyses/ThreadSafetyOps.def
@@ -44,8 +44,11 @@ TIL_OPCODE_DEF(Cast)
 TIL_OPCODE_DEF(SCFG)
 TIL_OPCODE_DEF(BasicBlock)
 TIL_OPCODE_DEF(Phi)
+
+// Terminator instructions
 TIL_OPCODE_DEF(Goto)
 TIL_OPCODE_DEF(Branch)
+TIL_OPCODE_DEF(Return)
 
 // pseudo-terms
 TIL_OPCODE_DEF(Identifier)
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
index 8e4299e..2cd8c6d 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h
@@ -44,17 +44,16 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_THREAD_SAFETY_TIL_H
-#define LLVM_CLANG_THREAD_SAFETY_TIL_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H
 
 // All clang include dependencies for this file must be put in
 // ThreadSafetyUtil.h.
 #include "ThreadSafetyUtil.h"
-
-#include 
 #include 
 #include 
 #include 
+#include 
 #include 
 
 
@@ -63,24 +62,27 @@ namespace threadSafety {
 namespace til {
 
 
+/// Enum for the different distinct classes of SExpr
 enum TIL_Opcode {
 #define TIL_OPCODE_DEF(X) COP_##X,
 #include "ThreadSafetyOps.def"
 #undef TIL_OPCODE_DEF
 };
 
+/// Opcode for unary arithmetic operations.
 enum TIL_UnaryOpcode : unsigned char {
   UOP_Minus,        //  -
   UOP_BitNot,       //  ~
   UOP_LogicNot      //  !
 };
 
+/// Opcode for binary arithmetic operations.
 enum TIL_BinaryOpcode : unsigned char {
+  BOP_Add,          //  +
+  BOP_Sub,          //  -
   BOP_Mul,          //  *
   BOP_Div,          //  /
   BOP_Rem,          //  %
-  BOP_Add,          //  +
-  BOP_Sub,          //  -
   BOP_Shl,          //  <<
   BOP_Shr,          //  >>
   BOP_BitAnd,       //  &
@@ -90,37 +92,42 @@ enum TIL_BinaryOpcode : unsigned char {
   BOP_Neq,          //  !=
   BOP_Lt,           //  <
   BOP_Leq,          //  <=
-  BOP_LogicAnd,     //  &&
-  BOP_LogicOr       //  ||
+  BOP_LogicAnd,     //  &&  (no short-circuit)
+  BOP_LogicOr       //  ||  (no short-circuit)
 };
 
+/// Opcode for cast operations.
 enum TIL_CastOpcode : unsigned char {
   CAST_none = 0,
   CAST_extendNum,   // extend precision of numeric type
   CAST_truncNum,    // truncate precision of numeric type
   CAST_toFloat,     // convert to floating point type
   CAST_toInt,       // convert to integer type
+  CAST_objToPtr     // convert smart pointer to pointer  (C++ only)
 };
 
 const TIL_Opcode       COP_Min  = COP_Future;
 const TIL_Opcode       COP_Max  = COP_Branch;
 const TIL_UnaryOpcode  UOP_Min  = UOP_Minus;
 const TIL_UnaryOpcode  UOP_Max  = UOP_LogicNot;
-const TIL_BinaryOpcode BOP_Min  = BOP_Mul;
+const TIL_BinaryOpcode BOP_Min  = BOP_Add;
 const TIL_BinaryOpcode BOP_Max  = BOP_LogicOr;
 const TIL_CastOpcode   CAST_Min = CAST_none;
 const TIL_CastOpcode   CAST_Max = CAST_toInt;
 
+/// Return the name of a unary opcode.
 StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op);
+
+/// Return the name of a binary opcode.
 StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op);
 
 
-// ValueTypes are data types that can actually be held in registers.
-// All variables and expressions must have a vBNF_Nonealue type.
-// Pointer types are further subdivided into the various heap-allocated
-// types, such as functions, records, etc.
-// Structured types that are passed by value (e.g. complex numbers)
-// require special handling; they use BT_ValueRef, and size ST_0.
+/// ValueTypes are data types that can actually be held in registers.
+/// All variables and expressions must have a value type.
+/// Pointer types are further subdivided into the various heap-allocated
+/// types, such as functions, records, etc.
+/// Structured types that are passed by value (e.g. complex numbers)
+/// require special handling; they use BT_ValueRef, and size ST_0.
 struct ValueType {
   enum BaseType : unsigned char {
     BT_Void = 0,
@@ -246,8 +253,10 @@ inline ValueType ValueType::getValueType() {
 }
 
 
+class BasicBlock;
+
 
-// Base class for AST nodes in the typed intermediate language.
+/// Base class for AST nodes in the typed intermediate language.
 class SExpr {
 public:
   TIL_Opcode opcode() const { return static_cast(Opcode); }
@@ -266,71 +275,47 @@ public:
   // template  typename C::CType compare(CType* E, C& Cmp) {
   //   compare all subexpressions, following the comparator interface
   // }
-
   void *operator new(size_t S, MemRegionRef &R) {
     return ::operator new(S, R);
   }
 
-  // SExpr objects cannot be deleted.
+  /// SExpr objects cannot be deleted.
   // This declaration is public to workaround a gcc bug that breaks building
   // with REQUIRES_EH=1.
   void operator delete(void *) LLVM_DELETED_FUNCTION;
 
+  /// Returns the instruction ID for this expression.
+  /// All basic block instructions have a unique ID (i.e. virtual register).
+  unsigned id() const { return SExprID; }
+
+  /// Returns the block, if this is an instruction in a basic block,
+  /// otherwise returns null.
+  BasicBlock* block() const { return Block; }
+
+  /// Set the basic block and instruction ID for this expression.
+  void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; }
+
 protected:
-  SExpr(TIL_Opcode Op) : Opcode(Op), Reserved(0), Flags(0) {}
-  SExpr(const SExpr &E) : Opcode(E.Opcode), Reserved(0), Flags(E.Flags) {}
+  SExpr(TIL_Opcode Op)
+    : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {}
+  SExpr(const SExpr &E)
+    : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0),
+      Block(nullptr) {}
 
   const unsigned char Opcode;
   unsigned char Reserved;
   unsigned short Flags;
+  unsigned SExprID;
+  BasicBlock* Block;
 
 private:
   SExpr() LLVM_DELETED_FUNCTION;
 
-  // SExpr objects must be created in an arena.
+  /// SExpr objects must be created in an arena.
   void *operator new(size_t) LLVM_DELETED_FUNCTION;
 };
 
 
-// Class for owning references to SExprs.
-// Includes attach/detach logic for counting variable references and lazy
-// rewriting strategies.
-class SExprRef {
-public:
-  SExprRef() : Ptr(nullptr) { }
-  SExprRef(std::nullptr_t P) : Ptr(nullptr) { }
-  SExprRef(SExprRef &&R) : Ptr(R.Ptr) { R.Ptr = nullptr; }
-
-  // Defined after Variable and Future, below.
-  inline SExprRef(SExpr *P);
-  inline ~SExprRef();
-
-  SExpr       *get()       { return Ptr; }
-  const SExpr *get() const { return Ptr; }
-
-  SExpr       *operator->()       { return get(); }
-  const SExpr *operator->() const { return get(); }
-
-  SExpr       &operator*()        { return *Ptr; }
-  const SExpr &operator*() const  { return *Ptr; }
-
-  bool operator==(const SExprRef &R) const { return Ptr == R.Ptr; }
-  bool operator!=(const SExprRef &R) const { return !operator==(R); }
-  bool operator==(const SExpr *P)    const { return Ptr == P; }
-  bool operator!=(const SExpr *P)    const { return !operator==(P); }
-  bool operator==(std::nullptr_t)    const { return Ptr == nullptr; }
-  bool operator!=(std::nullptr_t)    const { return Ptr != nullptr; }
-
-  inline void reset(SExpr *E);
-
-private:
-  inline void attach();
-  inline void detach();
-
-  SExpr *Ptr;
-};
-
-
 // Contains various helper functions for SExprs.
 namespace ThreadSafetyTIL {
   inline bool isTrivial(const SExpr *E) {
@@ -342,62 +327,64 @@ namespace ThreadSafetyTIL {
 // Nodes which declare variables
 class Function;
 class SFunction;
-class BasicBlock;
 class Let;
 
 
-// A named variable, e.g. "x".
-//
-// There are two distinct places in which a Variable can appear in the AST.
-// A variable declaration introduces a new variable, and can occur in 3 places:
-//   Let-expressions:           (Let (x = t) u)
-//   Functions:                 (Function (x : t) u)
-//   Self-applicable functions  (SFunction (x) t)
-//
-// If a variable occurs in any other location, it is a reference to an existing
-// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
-// allocate a separate AST node for variable references; a reference is just a
-// pointer to the original declaration.
+/// A named variable, e.g. "x".
+///
+/// There are two distinct places in which a Variable can appear in the AST.
+/// A variable declaration introduces a new variable, and can occur in 3 places:
+///   Let-expressions:           (Let (x = t) u)
+///   Functions:                 (Function (x : t) u)
+///   Self-applicable functions  (SFunction (x) t)
+///
+/// If a variable occurs in any other location, it is a reference to an existing
+/// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't
+/// allocate a separate AST node for variable references; a reference is just a
+/// pointer to the original declaration.
 class Variable : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; }
 
-  // Let-variable, function parameter, or self-variable
   enum VariableKind {
-    VK_Let,
-    VK_LetBB,
-    VK_Fun,
-    VK_SFun
+    VK_Let,  ///< Let-variable
+    VK_Fun,  ///< Function parameter
+    VK_SFun  ///< SFunction (self) parameter
   };
 
-  // These are defined after SExprRef contructor, below
-  inline Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr);
-  inline Variable(StringRef s, SExpr *D = nullptr);
-  inline Variable(const Variable &Vd, SExpr *D);
+  Variable(StringRef s, SExpr *D = nullptr)
+      : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) {
+    Flags = VK_Let;
+  }
+  Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr)
+      : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
+        Definition(D), Cvdecl(Cvd) {
+    Flags = VK_Let;
+  }
+  Variable(const Variable &Vd, SExpr *D)  // rewrite constructor
+      : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) {
+    Flags = Vd.kind();
+  }
 
+  /// Return the kind of variable (let, function param, or self)
   VariableKind kind() const { return static_cast(Flags); }
 
-  const StringRef name() const { return Name; }
-  const clang::ValueDecl *clangDecl() const { return Cvdecl; }
-
-  // Returns the definition (for let vars) or type (for parameter & self vars)
-  SExpr *definition() { return Definition.get(); }
-  const SExpr *definition() const { return Definition.get(); }
+  /// Return the name of the variable, if any.
+  StringRef name() const { return Name; }
 
-  void attachVar() const { ++NumUses; }
-  void detachVar() const { assert(NumUses > 0); --NumUses; }
+  /// Return the clang declaration for this variable, if any.
+  const clang::ValueDecl *clangDecl() const { return Cvdecl; }
 
-  unsigned getID() const { return Id; }
-  unsigned getBlockID() const { return BlockID; }
+  /// Return the definition of the variable.
+  /// For let-vars, this is the setting expression.
+  /// For function and self parameters, it is the type of the variable.
+  SExpr *definition() { return Definition; }
+  const SExpr *definition() const { return Definition; }
 
-  void setName(StringRef S) { Name = S; }
-  void setID(unsigned Bid, unsigned I) {
-    BlockID = static_cast(Bid);
-    Id = static_cast(I);
-  }
-  void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
-  void setDefinition(SExpr *E);
+  void setName(StringRef S)    { Name = S;  }
   void setKind(VariableKind K) { Flags = K; }
+  void setDefinition(SExpr *E) { Definition = E; }
+  void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -405,7 +392,8 @@ public:
     return Vs.reduceVariableRef(this);
   }
 
-  template  typename C::CType compare(Variable* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Variable* E, C& Cmp) const {
     return Cmp.compareVariableRefs(this, E);
   }
 
@@ -416,17 +404,13 @@ private:
   friend class Let;
 
   StringRef Name;                  // The name of the variable.
-  SExprRef  Definition;            // The TIL type or definition
+  SExpr*    Definition;            // The TIL type or definition
   const clang::ValueDecl *Cvdecl;  // The clang declaration for this variable.
-
-  unsigned short BlockID;
-  unsigned short Id;
-  mutable unsigned NumUses;
 };
 
 
-// Placeholder for an expression that has not yet been created.
-// Used to implement lazy copy and rewriting strategies.
+/// Placeholder for an expression that has not yet been created.
+/// Used to implement lazy copy and rewriting strategies.
 class Future : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Future; }
@@ -437,25 +421,17 @@ public:
     FS_done
   };
 
-  Future() :
-    SExpr(COP_Future), Status(FS_pending), Result(nullptr), Location(nullptr)
-  {}
+  Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {}
+
 private:
   virtual ~Future() LLVM_DELETED_FUNCTION;
-public:
-
-  // Registers the location in the AST where this future is stored.
-  // Forcing the future will automatically update the AST.
-  static inline void registerLocation(SExprRef *Member) {
-    if (Future *F = dyn_cast_or_null(Member->get()))
-      F->Location = Member;
-  }
 
+public:
   // A lazy rewriting strategy should subclass Future and override this method.
-  virtual SExpr *create() { return nullptr; }
+  virtual SExpr *compute() { return nullptr; }
 
   // Return the result of this future if it exists, otherwise return null.
-  SExpr *maybeGetResult() {
+  SExpr *maybeGetResult() const {
     return Result;
   }
 
@@ -463,8 +439,7 @@ public:
   SExpr *result() {
     switch (Status) {
     case FS_pending:
-      force();
-      return Result;
+      return force();
     case FS_evaluating:
       return nullptr; // infinite loop; illegal recursion.
     case FS_done:
@@ -478,88 +453,22 @@ public:
     return Vs.traverse(Result, Ctx);
   }
 
-  template  typename C::CType compare(Future* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Future* E, C& Cmp) const {
     if (!Result || !E->Result)
       return Cmp.comparePointers(this, E);
     return Cmp.compare(Result, E->Result);
   }
 
 private:
-  // Force the future.
-  inline void force();
+  SExpr* force();
 
   FutureStatus Status;
   SExpr *Result;
-  SExprRef *Location;
 };
 
 
-inline void SExprRef::attach() {
-  if (!Ptr)
-    return;
-
-  TIL_Opcode Op = Ptr->opcode();
-  if (Op == COP_Variable) {
-    cast(Ptr)->attachVar();
-  } else if (Op == COP_Future) {
-    cast(Ptr)->registerLocation(this);
-  }
-}
-
-inline void SExprRef::detach() {
-  if (Ptr && Ptr->opcode() == COP_Variable) {
-    cast(Ptr)->detachVar();
-  }
-}
-
-inline SExprRef::SExprRef(SExpr *P) : Ptr(P) {
-  attach();
-}
-
-inline SExprRef::~SExprRef() {
-  detach();
-}
-
-inline void SExprRef::reset(SExpr *P) {
-  detach();
-  Ptr = P;
-  attach();
-}
-
-
-inline Variable::Variable(StringRef s, SExpr *D)
-    : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr),
-      BlockID(0), Id(0), NumUses(0) {
-  Flags = VK_Let;
-}
-
-inline Variable::Variable(SExpr *D, const clang::ValueDecl *Cvd)
-    : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"),
-      Definition(D), Cvdecl(Cvd), BlockID(0), Id(0), NumUses(0) {
-  Flags = VK_Let;
-}
-
-inline Variable::Variable(const Variable &Vd, SExpr *D) // rewrite constructor
-    : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl),
-      BlockID(0), Id(0), NumUses(0) {
-  Flags = Vd.kind();
-}
-
-inline void Variable::setDefinition(SExpr *E) {
-  Definition.reset(E);
-}
-
-void Future::force() {
-  Status = FS_evaluating;
-  SExpr *R = create();
-  Result = R;
-  if (Location)
-    Location->reset(R);
-  Status = FS_done;
-}
-
-
-// Placeholder for C++ expressions that cannot be represented in the TIL.
+/// Placeholder for expressions that cannot be represented in the TIL.
 class Undefined : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; }
@@ -572,8 +481,9 @@ public:
     return Vs.reduceUndefined(*this);
   }
 
-  template  typename C::CType compare(Undefined* E, C& Cmp) {
-    return Cmp.comparePointers(Cstmt, E->Cstmt);
+  template 
+  typename C::CType compare(const Undefined* E, C& Cmp) const {
+    return Cmp.trueResult();
   }
 
 private:
@@ -581,7 +491,7 @@ private:
 };
 
 
-// Placeholder for a wildcard that matches any other expression.
+/// Placeholder for a wildcard that matches any other expression.
 class Wildcard : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; }
@@ -593,7 +503,8 @@ public:
     return Vs.reduceWildcard(*this);
   }
 
-  template  typename C::CType compare(Wildcard* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Wildcard* E, C& Cmp) const {
     return Cmp.trueResult();
   }
 };
@@ -626,9 +537,10 @@ public:
 
   template  typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx);
 
-  template  typename C::CType compare(Literal* E, C& Cmp) {
-    // TODO -- use value, not pointer equality
-    return Cmp.comparePointers(Cexpr, E->Cexpr);
+  template 
+  typename C::CType compare(const Literal* E, C& Cmp) const {
+    // TODO: defer actual comparison to LiteralT
+    return Cmp.trueResult();
   }
 
 private:
@@ -710,8 +622,8 @@ typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) {
 }
 
 
-// Literal pointer to an object allocated in memory.
-// At compile time, pointer literals are represented by symbolic names.
+/// A Literal pointer to an object allocated in memory.
+/// At compile time, pointer literals are represented by symbolic names.
 class LiteralPtr : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; }
@@ -727,7 +639,8 @@ public:
     return Vs.reduceLiteralPtr(*this);
   }
 
-  template  typename C::CType compare(LiteralPtr* E, C& Cmp) {
+  template 
+  typename C::CType compare(const LiteralPtr* E, C& Cmp) const {
     return Cmp.comparePointers(Cvdecl, E->Cvdecl);
   }
 
@@ -736,9 +649,9 @@ private:
 };
 
 
-// A function -- a.k.a. lambda abstraction.
-// Functions with multiple arguments are created by currying,
-// e.g. (function (x: Int) (function (y: Int) (add x y)))
+/// A function -- a.k.a. lambda abstraction.
+/// Functions with multiple arguments are created by currying,
+/// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y })))
 class Function : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Function; }
@@ -755,8 +668,8 @@ public:
   Variable *variableDecl()  { return VarDecl; }
   const Variable *variableDecl() const { return VarDecl; }
 
-  SExpr *body() { return Body.get(); }
-  const SExpr *body() const { return Body.get(); }
+  SExpr *body() { return Body; }
+  const SExpr *body() const { return Body; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -769,7 +682,8 @@ public:
     return Vs.reduceFunction(*this, Nvd, E1);
   }
 
-  template  typename C::CType compare(Function* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Function* E, C& Cmp) const {
     typename C::CType Ct =
       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
     if (Cmp.notTrue(Ct))
@@ -782,13 +696,13 @@ public:
 
 private:
   Variable *VarDecl;
-  SExprRef Body;
+  SExpr* Body;
 };
 
 
-// A self-applicable function.
-// A self-applicable function can be applied to itself.  It's useful for
-// implementing objects and late binding
+/// A self-applicable function.
+/// A self-applicable function can be applied to itself.  It's useful for
+/// implementing objects and late binding.
 class SFunction : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; }
@@ -797,20 +711,20 @@ public:
       : SExpr(COP_SFunction), VarDecl(Vd), Body(B) {
     assert(Vd->Definition == nullptr);
     Vd->setKind(Variable::VK_SFun);
-    Vd->Definition.reset(this);
+    Vd->Definition = this;
   }
   SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor
       : SExpr(F), VarDecl(Vd), Body(B) {
     assert(Vd->Definition == nullptr);
     Vd->setKind(Variable::VK_SFun);
-    Vd->Definition.reset(this);
+    Vd->Definition = this;
   }
 
   Variable *variableDecl() { return VarDecl; }
   const Variable *variableDecl() const { return VarDecl; }
 
-  SExpr *body() { return Body.get(); }
-  const SExpr *body() const { return Body.get(); }
+  SExpr *body() { return Body; }
+  const SExpr *body() const { return Body; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -824,7 +738,8 @@ public:
     return Vs.reduceSFunction(*this, Nvd, E1);
   }
 
-  template  typename C::CType compare(SFunction* E, C& Cmp) {
+  template 
+  typename C::CType compare(const SFunction* E, C& Cmp) const {
     Cmp.enterScope(variableDecl(), E->variableDecl());
     typename C::CType Ct = Cmp.compare(body(), E->body());
     Cmp.leaveScope();
@@ -833,11 +748,11 @@ public:
 
 private:
   Variable *VarDecl;
-  SExprRef Body;
+  SExpr* Body;
 };
 
 
-// A block of code -- e.g. the body of a function.
+/// A block of code -- e.g. the body of a function.
 class Code : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Code; }
@@ -846,11 +761,11 @@ public:
   Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor
       : SExpr(C), ReturnType(T), Body(B) {}
 
-  SExpr *returnType() { return ReturnType.get(); }
-  const SExpr *returnType() const { return ReturnType.get(); }
+  SExpr *returnType() { return ReturnType; }
+  const SExpr *returnType() const { return ReturnType; }
 
-  SExpr *body() { return Body.get(); }
-  const SExpr *body() const { return Body.get(); }
+  SExpr *body() { return Body; }
+  const SExpr *body() const { return Body; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -859,7 +774,8 @@ public:
     return Vs.reduceCode(*this, Nt, Nb);
   }
 
-  template  typename C::CType compare(Code* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Code* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(returnType(), E->returnType());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -867,12 +783,12 @@ public:
   }
 
 private:
-  SExprRef ReturnType;
-  SExprRef Body;
+  SExpr* ReturnType;
+  SExpr* Body;
 };
 
 
-// A typed, writable location in memory
+/// A typed, writable location in memory
 class Field : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Field; }
@@ -881,11 +797,11 @@ public:
   Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor
       : SExpr(C), Range(R), Body(B) {}
 
-  SExpr *range() { return Range.get(); }
-  const SExpr *range() const { return Range.get(); }
+  SExpr *range() { return Range; }
+  const SExpr *range() const { return Range; }
 
-  SExpr *body() { return Body.get(); }
-  const SExpr *body() const { return Body.get(); }
+  SExpr *body() { return Body; }
+  const SExpr *body() const { return Body; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -894,7 +810,8 @@ public:
     return Vs.reduceField(*this, Nr, Nb);
   }
 
-  template  typename C::CType compare(Field* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Field* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(range(), E->range());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -902,12 +819,16 @@ public:
   }
 
 private:
-  SExprRef Range;
-  SExprRef Body;
+  SExpr* Range;
+  SExpr* Body;
 };
 
 
-// Apply an argument to a function
+/// Apply an argument to a function.
+/// Note that this does not actually call the function.  Functions are curried,
+/// so this returns a closure in which the first parameter has been applied.
+/// Once all parameters have been applied, Call can be used to invoke the
+/// function.
 class Apply : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; }
@@ -917,11 +838,11 @@ public:
       : SExpr(A), Fun(F), Arg(Ar)
   {}
 
-  SExpr *fun() { return Fun.get(); }
-  const SExpr *fun() const { return Fun.get(); }
+  SExpr *fun() { return Fun; }
+  const SExpr *fun() const { return Fun; }
 
-  SExpr *arg() { return Arg.get(); }
-  const SExpr *arg() const { return Arg.get(); }
+  SExpr *arg() { return Arg; }
+  const SExpr *arg() const { return Arg; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -930,7 +851,8 @@ public:
     return Vs.reduceApply(*this, Nf, Na);
   }
 
-  template  typename C::CType compare(Apply* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Apply* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(fun(), E->fun());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -938,12 +860,12 @@ public:
   }
 
 private:
-  SExprRef Fun;
-  SExprRef Arg;
+  SExpr* Fun;
+  SExpr* Arg;
 };
 
 
-// Apply a self-argument to a self-applicable function
+/// Apply a self-argument to a self-applicable function.
 class SApply : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; }
@@ -952,23 +874,24 @@ public:
   SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor
       : SExpr(A), Sfun(Sf), Arg(Ar) {}
 
-  SExpr *sfun() { return Sfun.get(); }
-  const SExpr *sfun() const { return Sfun.get(); }
+  SExpr *sfun() { return Sfun; }
+  const SExpr *sfun() const { return Sfun; }
 
-  SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); }
-  const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); }
+  SExpr *arg() { return Arg ? Arg : Sfun; }
+  const SExpr *arg() const { return Arg ? Arg : Sfun; }
 
-  bool isDelegation() const { return Arg == nullptr; }
+  bool isDelegation() const { return Arg != nullptr; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
     auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx));
-    typename V::R_SExpr Na = Arg.get() ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
+    typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx))
                                        : nullptr;
     return Vs.reduceSApply(*this, Nf, Na);
   }
 
-  template  typename C::CType compare(SApply* E, C& Cmp) {
+  template 
+  typename C::CType compare(const SApply* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(sfun(), E->sfun());
     if (Cmp.notTrue(Ct) || (!arg() && !E->arg()))
       return Ct;
@@ -976,12 +899,12 @@ public:
   }
 
 private:
-  SExprRef Sfun;
-  SExprRef Arg;
+  SExpr* Sfun;
+  SExpr* Arg;
 };
 
 
-// Project a named slot from a C++ struct or class.
+/// Project a named slot from a C++ struct or class.
 class Project : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Project; }
@@ -989,17 +912,23 @@ public:
   Project(SExpr *R, StringRef SName)
       : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr)
   { }
-  Project(SExpr *R, clang::ValueDecl *Cvd)
+  Project(SExpr *R, const clang::ValueDecl *Cvd)
       : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd)
   { }
   Project(const Project &P, SExpr *R)
       : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl)
   { }
 
-  SExpr *record() { return Rec.get(); }
-  const SExpr *record() const { return Rec.get(); }
+  SExpr *record() { return Rec; }
+  const SExpr *record() const { return Rec; }
+
+  const clang::ValueDecl *clangDecl() const { return Cvdecl; }
 
-  const clang::ValueDecl *clangValueDecl() const { return Cvdecl; }
+  bool isArrow() const { return (Flags & 0x01) != 0; }
+  void setArrow(bool b) {
+    if (b) Flags |= 0x01;
+    else Flags &= 0xFFFE;
+  }
 
   StringRef slotName() const {
     if (Cvdecl)
@@ -1014,7 +943,8 @@ public:
     return Vs.reduceProject(*this, Nr);
   }
 
-  template  typename C::CType compare(Project* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Project* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(record(), E->record());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -1022,13 +952,13 @@ public:
   }
 
 private:
-  SExprRef Rec;
+  SExpr* Rec;
   StringRef SlotName;
-  clang::ValueDecl *Cvdecl;
+  const clang::ValueDecl *Cvdecl;
 };
 
 
-// Call a function (after all arguments have been applied).
+/// Call a function (after all arguments have been applied).
 class Call : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
@@ -1037,8 +967,8 @@ public:
       : SExpr(COP_Call), Target(T), Cexpr(Ce) {}
   Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {}
 
-  SExpr *target() { return Target.get(); }
-  const SExpr *target() const { return Target.get(); }
+  SExpr *target() { return Target; }
+  const SExpr *target() const { return Target; }
 
   const clang::CallExpr *clangCallExpr() const { return Cexpr; }
 
@@ -1048,17 +978,18 @@ public:
     return Vs.reduceCall(*this, Nt);
   }
 
-  template  typename C::CType compare(Call* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Call* E, C& Cmp) const {
     return Cmp.compare(target(), E->target());
   }
 
 private:
-  SExprRef Target;
+  SExpr* Target;
   const clang::CallExpr *Cexpr;
 };
 
 
-// Allocate memory for a new value on the heap or stack.
+/// Allocate memory for a new value on the heap or stack.
 class Alloc : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Call; }
@@ -1073,8 +1004,8 @@ public:
 
   AllocKind kind() const { return static_cast(Flags); }
 
-  SExpr *dataType() { return Dtype.get(); }
-  const SExpr *dataType() const { return Dtype.get(); }
+  SExpr *dataType() { return Dtype; }
+  const SExpr *dataType() const { return Dtype; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1082,7 +1013,8 @@ public:
     return Vs.reduceAlloc(*this, Nd);
   }
 
-  template  typename C::CType compare(Alloc* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Alloc* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -1090,11 +1022,11 @@ public:
   }
 
 private:
-  SExprRef Dtype;
+  SExpr* Dtype;
 };
 
 
-// Load a value from memory.
+/// Load a value from memory.
 class Load : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Load; }
@@ -1102,8 +1034,8 @@ public:
   Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {}
   Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {}
 
-  SExpr *pointer() { return Ptr.get(); }
-  const SExpr *pointer() const { return Ptr.get(); }
+  SExpr *pointer() { return Ptr; }
+  const SExpr *pointer() const { return Ptr; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1111,17 +1043,18 @@ public:
     return Vs.reduceLoad(*this, Np);
   }
 
-  template  typename C::CType compare(Load* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Load* E, C& Cmp) const {
     return Cmp.compare(pointer(), E->pointer());
   }
 
 private:
-  SExprRef Ptr;
+  SExpr* Ptr;
 };
 
 
-// Store a value to memory.
-// Source is a pointer, destination is the value to store.
+/// Store a value to memory.
+/// The destination is a pointer to a field, the source is the value to store.
 class Store : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Store; }
@@ -1129,11 +1062,11 @@ public:
   Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {}
   Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {}
 
-  SExpr *destination() { return Dest.get(); }  // Address to store to
-  const SExpr *destination() const { return Dest.get(); }
+  SExpr *destination() { return Dest; }  // Address to store to
+  const SExpr *destination() const { return Dest; }
 
-  SExpr *source() { return Source.get(); }     // Value to store
-  const SExpr *source() const { return Source.get(); }
+  SExpr *source() { return Source; }     // Value to store
+  const SExpr *source() const { return Source; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1142,7 +1075,8 @@ public:
     return Vs.reduceStore(*this, Np, Nv);
   }
 
-  template  typename C::CType compare(Store* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Store* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(destination(), E->destination());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -1150,13 +1084,13 @@ public:
   }
 
 private:
-  SExprRef Dest;
-  SExprRef Source;
+  SExpr* Dest;
+  SExpr* Source;
 };
 
 
-// If p is a reference to an array, then first(p) is a reference to the first
-// element.  The usual array notation p[i]  becomes first(p + i).
+/// If p is a reference to an array, then p[i] is a reference to the i'th
+/// element of the array.
 class ArrayIndex : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; }
@@ -1165,11 +1099,11 @@ public:
   ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N)
     : SExpr(E), Array(A), Index(N) {}
 
-  SExpr *array() { return Array.get(); }
-  const SExpr *array() const { return Array.get(); }
+  SExpr *array() { return Array; }
+  const SExpr *array() const { return Array; }
 
-  SExpr *index() { return Index.get(); }
-  const SExpr *index() const { return Index.get(); }
+  SExpr *index() { return Index; }
+  const SExpr *index() const { return Index; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1178,7 +1112,8 @@ public:
     return Vs.reduceArrayIndex(*this, Na, Ni);
   }
 
-  template  typename C::CType compare(ArrayIndex* E, C& Cmp) {
+  template 
+  typename C::CType compare(const ArrayIndex* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(array(), E->array());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -1186,14 +1121,14 @@ public:
   }
 
 private:
-  SExprRef Array;
-  SExprRef Index;
+  SExpr* Array;
+  SExpr* Index;
 };
 
 
-// Pointer arithmetic, restricted to arrays only.
-// If p is a reference to an array, then p + n, where n is an integer, is
-// a reference to a subarray.
+/// Pointer arithmetic, restricted to arrays only.
+/// If p is a reference to an array, then p + n, where n is an integer, is
+/// a reference to a subarray.
 class ArrayAdd : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; }
@@ -1202,11 +1137,11 @@ public:
   ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N)
     : SExpr(E), Array(A), Index(N) {}
 
-  SExpr *array() { return Array.get(); }
-  const SExpr *array() const { return Array.get(); }
+  SExpr *array() { return Array; }
+  const SExpr *array() const { return Array; }
 
-  SExpr *index() { return Index.get(); }
-  const SExpr *index() const { return Index.get(); }
+  SExpr *index() { return Index; }
+  const SExpr *index() const { return Index; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1215,7 +1150,8 @@ public:
     return Vs.reduceArrayAdd(*this, Na, Ni);
   }
 
-  template  typename C::CType compare(ArrayAdd* E, C& Cmp) {
+  template 
+  typename C::CType compare(const ArrayAdd* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(array(), E->array());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -1223,12 +1159,13 @@ public:
   }
 
 private:
-  SExprRef Array;
-  SExprRef Index;
+  SExpr* Array;
+  SExpr* Index;
 };
 
 
-// Simple unary operation -- e.g. !, ~, etc.
+/// Simple arithmetic unary operations, e.g. negate and not.
+/// These operations have no side-effects.
 class UnaryOp : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; }
@@ -1242,8 +1179,8 @@ public:
     return static_cast(Flags);
   }
 
-  SExpr *expr() { return Expr0.get(); }
-  const SExpr *expr() const { return Expr0.get(); }
+  SExpr *expr() { return Expr0; }
+  const SExpr *expr() const { return Expr0; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1251,7 +1188,8 @@ public:
     return Vs.reduceUnaryOp(*this, Ne);
   }
 
-  template  typename C::CType compare(UnaryOp* E, C& Cmp) {
+  template 
+  typename C::CType compare(const UnaryOp* E, C& Cmp) const {
     typename C::CType Ct =
       Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode());
     if (Cmp.notTrue(Ct))
@@ -1260,11 +1198,12 @@ public:
   }
 
 private:
-  SExprRef Expr0;
+  SExpr* Expr0;
 };
 
 
-// Simple binary operation -- e.g. +, -, etc.
+/// Simple arithmetic binary operations, e.g. +, -, etc.
+/// These operations have no side effects.
 class BinaryOp : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; }
@@ -1282,11 +1221,11 @@ public:
     return static_cast(Flags);
   }
 
-  SExpr *expr0() { return Expr0.get(); }
-  const SExpr *expr0() const { return Expr0.get(); }
+  SExpr *expr0() { return Expr0; }
+  const SExpr *expr0() const { return Expr0; }
 
-  SExpr *expr1() { return Expr1.get(); }
-  const SExpr *expr1() const { return Expr1.get(); }
+  SExpr *expr1() { return Expr1; }
+  const SExpr *expr1() const { return Expr1; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1295,7 +1234,8 @@ public:
     return Vs.reduceBinaryOp(*this, Ne0, Ne1);
   }
 
-  template  typename C::CType compare(BinaryOp* E, C& Cmp) {
+  template 
+  typename C::CType compare(const BinaryOp* E, C& Cmp) const {
     typename C::CType Ct =
       Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode());
     if (Cmp.notTrue(Ct))
@@ -1307,12 +1247,14 @@ public:
   }
 
 private:
-  SExprRef Expr0;
-  SExprRef Expr1;
+  SExpr* Expr0;
+  SExpr* Expr1;
 };
 
 
-// Cast expression
+/// Cast expressions.
+/// Cast expressions are essentially unary operations, but we treat them
+/// as a distinct AST node because they only change the type of the result.
 class Cast : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; }
@@ -1324,8 +1266,8 @@ public:
     return static_cast(Flags);
   }
 
-  SExpr *expr() { return Expr0.get(); }
-  const SExpr *expr() const { return Expr0.get(); }
+  SExpr *expr() { return Expr0; }
+  const SExpr *expr() const { return Expr0; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1333,7 +1275,8 @@ public:
     return Vs.reduceCast(*this, Ne);
   }
 
-  template  typename C::CType compare(Cast* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Cast* E, C& Cmp) const {
     typename C::CType Ct =
       Cmp.compareIntegers(castOpcode(), E->castOpcode());
     if (Cmp.notTrue(Ct))
@@ -1342,16 +1285,18 @@ public:
   }
 
 private:
-  SExprRef Expr0;
+  SExpr* Expr0;
 };
 
 
 class SCFG;
 
 
+/// Phi Node, for code in SSA form.
+/// Each Phi node has an array of possible values that it can take,
+/// depending on where control flow comes from.
 class Phi : public SExpr {
 public:
-  // TODO: change to SExprRef
   typedef SimpleArray ValArray;
 
   // In minimal SSA form, all Phi nodes are MultiVal.
@@ -1365,9 +1310,12 @@ public:
 
   static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; }
 
-  Phi() : SExpr(COP_Phi) {}
-  Phi(MemRegionRef A, unsigned Nvals) : SExpr(COP_Phi), Values(A, Nvals) {}
-  Phi(const Phi &P, ValArray &&Vs)    : SExpr(P), Values(std::move(Vs)) {}
+  Phi()
+    : SExpr(COP_Phi), Cvdecl(nullptr) {}
+  Phi(MemRegionRef A, unsigned Nvals)
+    : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr)  {}
+  Phi(const Phi &P, ValArray &&Vs)
+    : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {}
 
   const ValArray &values() const { return Values; }
   ValArray &values() { return Values; }
@@ -1375,6 +1323,12 @@ public:
   Status status() const { return static_cast(Flags); }
   void setStatus(Status s) { Flags = s; }
 
+  /// Return the clang declaration of the variable for this Phi node, if any.
+  const clang::ValueDecl *clangDecl() const { return Cvdecl; }
+
+  /// Set the clang variable associated with this Phi node.
+  void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; }
+
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
     typename V::template Container
@@ -1386,72 +1340,268 @@ public:
     return Vs.reducePhi(*this, Nvs);
   }
 
-  template  typename C::CType compare(Phi *E, C &Cmp) {
+  template 
+  typename C::CType compare(const Phi *E, C &Cmp) const {
     // TODO: implement CFG comparisons
     return Cmp.comparePointers(this, E);
   }
 
 private:
   ValArray Values;
+  const clang::ValueDecl* Cvdecl;
+};
+
+
+/// Base class for basic block terminators:  Branch, Goto, and Return.
+class Terminator : public SExpr {
+public:
+  static bool classof(const SExpr *E) {
+    return E->opcode() >= COP_Goto && E->opcode() <= COP_Return;
+  }
+
+protected:
+  Terminator(TIL_Opcode Op)  : SExpr(Op) {}
+  Terminator(const SExpr &E) : SExpr(E)  {}
+
+public:
+  /// Return the list of basic blocks that this terminator can branch to.
+  ArrayRef successors();
+
+  ArrayRef successors() const {
+    return const_cast(this)->successors();
+  }
 };
 
 
-// A basic block is part of an SCFG, and can be treated as a function in
-// continuation passing style.  It consists of a sequence of phi nodes, which
-// are "arguments" to the function, followed by a sequence of instructions.
-// Both arguments and instructions define new variables.  It ends with a
-// branch or goto to another basic block in the same SCFG.
+/// Jump to another basic block.
+/// A goto instruction is essentially a tail-recursive call into another
+/// block.  In addition to the block pointer, it specifies an index into the
+/// phi nodes of that block.  The index can be used to retrieve the "arguments"
+/// of the call.
+class Goto : public Terminator {
+public:
+  static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
+
+  Goto(BasicBlock *B, unsigned I)
+      : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+  Goto(const Goto &G, BasicBlock *B, unsigned I)
+      : Terminator(COP_Goto), TargetBlock(B), Index(I) {}
+
+  const BasicBlock *targetBlock() const { return TargetBlock; }
+  BasicBlock *targetBlock() { return TargetBlock; }
+
+  /// Returns the index into the
+  unsigned index() const { return Index; }
+
+  /// Return the list of basic blocks that this terminator can branch to.
+  ArrayRef successors() {
+    return ArrayRef(&TargetBlock, 1);
+  }
+
+  template 
+  typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+    BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
+    return Vs.reduceGoto(*this, Ntb);
+  }
+
+  template 
+  typename C::CType compare(const Goto *E, C &Cmp) const {
+    // TODO: implement CFG comparisons
+    return Cmp.comparePointers(this, E);
+  }
+
+private:
+  BasicBlock *TargetBlock;
+  unsigned Index;
+};
+
+
+/// A conditional branch to two other blocks.
+/// Note that unlike Goto, Branch does not have an index.  The target blocks
+/// must be child-blocks, and cannot have Phi nodes.
+class Branch : public Terminator {
+public:
+  static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
+
+  Branch(SExpr *C, BasicBlock *T, BasicBlock *E)
+      : Terminator(COP_Branch), Condition(C) {
+    Branches[0] = T;
+    Branches[1] = E;
+  }
+  Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E)
+      : Terminator(Br), Condition(C) {
+    Branches[0] = T;
+    Branches[1] = E;
+  }
+
+  const SExpr *condition() const { return Condition; }
+  SExpr *condition() { return Condition; }
+
+  const BasicBlock *thenBlock() const { return Branches[0]; }
+  BasicBlock *thenBlock() { return Branches[0]; }
+
+  const BasicBlock *elseBlock() const { return Branches[1]; }
+  BasicBlock *elseBlock() { return Branches[1]; }
+
+  /// Return the list of basic blocks that this terminator can branch to.
+  ArrayRef successors() {
+    return ArrayRef(Branches, 2);
+  }
+
+  template 
+  typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+    auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
+    BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]);
+    BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]);
+    return Vs.reduceBranch(*this, Nc, Ntb, Nte);
+  }
+
+  template 
+  typename C::CType compare(const Branch *E, C &Cmp) const {
+    // TODO: implement CFG comparisons
+    return Cmp.comparePointers(this, E);
+  }
+
+private:
+  SExpr*     Condition;
+  BasicBlock *Branches[2];
+};
+
+
+/// Return from the enclosing function, passing the return value to the caller.
+/// Only the exit block should end with a return statement.
+class Return : public Terminator {
+public:
+  static bool classof(const SExpr *E) { return E->opcode() == COP_Return; }
+
+  Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {}
+  Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {}
+
+  /// Return an empty list.
+  ArrayRef successors() {
+    return ArrayRef();
+  }
+
+  SExpr *returnValue() { return Retval; }
+  const SExpr *returnValue() const { return Retval; }
+
+  template 
+  typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
+    auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx));
+    return Vs.reduceReturn(*this, Ne);
+  }
+
+  template 
+  typename C::CType compare(const Return *E, C &Cmp) const {
+    return Cmp.compare(Retval, E->Retval);
+  }
+
+private:
+  SExpr* Retval;
+};
+
+
+inline ArrayRef Terminator::successors() {
+  switch (opcode()) {
+    case COP_Goto:   return cast(this)->successors();
+    case COP_Branch: return cast(this)->successors();
+    case COP_Return: return cast(this)->successors();
+    default:
+      return ArrayRef();
+  }
+}
+
+
+/// A basic block is part of an SCFG.  It can be treated as a function in
+/// continuation passing style.  A block consists of a sequence of phi nodes,
+/// which are "arguments" to the function, followed by a sequence of
+/// instructions.  It ends with a Terminator, which is a Branch or Goto to
+/// another basic block in the same SCFG.
 class BasicBlock : public SExpr {
 public:
-  typedef SimpleArray   VarArray;
+  typedef SimpleArray      InstrArray;
   typedef SimpleArray BlockArray;
 
+  // TopologyNodes are used to overlay tree structures on top of the CFG,
+  // such as dominator and postdominator trees.  Each block is assigned an
+  // ID in the tree according to a depth-first search.  Tree traversals are
+  // always up, towards the parents.
+  struct TopologyNode {
+    TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {}
+
+    bool isParentOf(const TopologyNode& OtherNode) {
+      return OtherNode.NodeID > NodeID &&
+             OtherNode.NodeID < NodeID + SizeOfSubTree;
+    }
+
+    bool isParentOfOrEqual(const TopologyNode& OtherNode) {
+      return OtherNode.NodeID >= NodeID &&
+             OtherNode.NodeID < NodeID + SizeOfSubTree;
+    }
+
+    int NodeID;
+    int SizeOfSubTree;    // Includes this node, so must be > 1.
+    BasicBlock *Parent;   // Pointer to parent.
+  };
+
   static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; }
 
-  explicit BasicBlock(MemRegionRef A, BasicBlock* P = nullptr)
+  explicit BasicBlock(MemRegionRef A)
       : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),
-        Parent(P), Terminator(nullptr)
-  { }
-  BasicBlock(BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T)
-      : SExpr(COP_BasicBlock), Arena(B.Arena), CFGPtr(nullptr), BlockID(0),
-        Parent(nullptr), Args(std::move(As)), Instrs(std::move(Is)),
-        Terminator(T)
-  { }
+        Visited(0), TermInstr(nullptr) {}
+  BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is,
+             Terminator *T)
+      : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0),
+        Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {}
+
+  /// Returns the block ID.  Every block has a unique ID in the CFG.
+  int blockID() const { return BlockID; }
 
-  unsigned blockID() const { return BlockID; }
-  unsigned numPredecessors() const { return Predecessors.size(); }
+  /// Returns the number of predecessors.
+  size_t numPredecessors() const { return Predecessors.size(); }
+  size_t numSuccessors() const { return successors().size(); }
 
   const SCFG* cfg() const { return CFGPtr; }
   SCFG* cfg() { return CFGPtr; }
 
-  const BasicBlock *parent() const { return Parent; }
-  BasicBlock *parent() { return Parent; }
+  const BasicBlock *parent() const { return DominatorNode.Parent; }
+  BasicBlock *parent() { return DominatorNode.Parent; }
 
-  const VarArray &arguments() const { return Args; }
-  VarArray &arguments() { return Args; }
+  const InstrArray &arguments() const { return Args; }
+  InstrArray &arguments() { return Args; }
 
-  const VarArray &instructions() const { return Instrs; }
-  VarArray &instructions() { return Instrs; }
+  InstrArray &instructions() { return Instrs; }
+  const InstrArray &instructions() const { return Instrs; }
 
-  const BlockArray &predecessors() const { return Predecessors; }
+  /// Returns a list of predecessors.
+  /// The order of predecessors in the list is important; each phi node has
+  /// exactly one argument for each precessor, in the same order.
   BlockArray &predecessors() { return Predecessors; }
+  const BlockArray &predecessors() const { return Predecessors; }
+
+  ArrayRef successors() { return TermInstr->successors(); }
+  ArrayRef successors() const { return TermInstr->successors(); }
+
+  const Terminator *terminator() const { return TermInstr; }
+  Terminator *terminator() { return TermInstr; }
 
-  const SExpr *terminator() const { return Terminator.get(); }
-  SExpr *terminator() { return Terminator.get(); }
+  void setTerminator(Terminator *E) { TermInstr = E; }
 
-  void setBlockID(unsigned i)   { BlockID = i; }
-  void setParent(BasicBlock *P) { Parent = P;  }
-  void setTerminator(SExpr *E)  { Terminator.reset(E); }
+  bool Dominates(const BasicBlock &Other) {
+    return DominatorNode.isParentOfOrEqual(Other.DominatorNode);
+  }
+
+  bool PostDominates(const BasicBlock &Other) {
+    return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode);
+  }
 
-  // Add a new argument.  V must define a phi-node.
-  void addArgument(Variable *V) {
-    V->setKind(Variable::VK_LetBB);
+  /// Add a new argument.
+  void addArgument(Phi *V) {
     Args.reserveCheck(1, Arena);
     Args.push_back(V);
   }
-  // Add a new instruction.
-  void addInstruction(Variable *V) {
-    V->setKind(Variable::VK_LetBB);
+  /// Add a new instruction.
+  void addInstruction(SExpr *V) {
     Instrs.reserveCheck(1, Arena);
     Instrs.push_back(V);
   }
@@ -1468,34 +1618,29 @@ public:
   // Reserve space for NumPreds predecessors, including space in phi nodes.
   void reservePredecessors(unsigned NumPreds);
 
-  // Return the index of BB, or Predecessors.size if BB is not a predecessor.
+  /// Return the index of BB, or Predecessors.size if BB is not a predecessor.
   unsigned findPredecessorIndex(const BasicBlock *BB) const {
     auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB);
     return std::distance(Predecessors.cbegin(), I);
   }
 
-  // Set id numbers for variables.
-  void renumberVars();
-
   template 
   typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) {
-    typename V::template Container Nas(Vs, Args.size());
-    typename V::template Container Nis(Vs, Instrs.size());
+    typename V::template Container Nas(Vs, Args.size());
+    typename V::template Container Nis(Vs, Instrs.size());
 
     // Entering the basic block should do any scope initialization.
     Vs.enterBasicBlock(*this);
 
-    for (auto *A : Args) {
-      auto Ne = Vs.traverse(A->Definition, Vs.subExprCtx(Ctx));
-      Variable *Nvd = Vs.enterScope(*A, Ne);
-      Nas.push_back(Nvd);
+    for (auto *E : Args) {
+      auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
+      Nas.push_back(Ne);
     }
-    for (auto *I : Instrs) {
-      auto Ne = Vs.traverse(I->Definition, Vs.subExprCtx(Ctx));
-      Variable *Nvd = Vs.enterScope(*I, Ne);
-      Nis.push_back(Nvd);
+    for (auto *E : Instrs) {
+      auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx));
+      Nis.push_back(Ne);
     }
-    auto Nt = Vs.traverse(Terminator, Ctx);
+    auto Nt = Vs.traverse(TermInstr, Ctx);
 
     // Exiting the basic block should handle any scope cleanup.
     Vs.exitBasicBlock(*this);
@@ -1503,7 +1648,8 @@ public:
     return Vs.reduceBasicBlock(*this, Nas, Nis, Nt);
   }
 
-  template  typename C::CType compare(BasicBlock *E, C &Cmp) {
+  template 
+  typename C::CType compare(const BasicBlock *E, C &Cmp) const {
     // TODO: implement CFG comparisons
     return Cmp.comparePointers(this, E);
   }
@@ -1511,22 +1657,32 @@ public:
 private:
   friend class SCFG;
 
-  MemRegionRef Arena;
+  int  renumberInstrs(int id);  // assign unique ids to all instructions
+  int  topologicalSort(SimpleArray& Blocks, int ID);
+  int  topologicalFinalSort(SimpleArray& Blocks, int ID);
+  void computeDominator();
+  void computePostDominator();
 
-  SCFG       *CFGPtr;       // The CFG that contains this block.
-  unsigned   BlockID;       // unique id for this BB in the containing CFG
-  BasicBlock *Parent;       // The parent block is the enclosing lexical scope.
-                            // The parent dominates this block.
-  BlockArray Predecessors;  // Predecessor blocks in the CFG.
-  VarArray   Args;          // Phi nodes.  One argument per predecessor.
-  VarArray   Instrs;        // Instructions.
-  SExprRef   Terminator;    // Branch or Goto
+private:
+  MemRegionRef Arena;        // The arena used to allocate this block.
+  SCFG         *CFGPtr;      // The CFG that contains this block.
+  int          BlockID : 31; // unique id for this BB in the containing CFG.
+                             // IDs are in topological order.
+  bool         Visited : 1;  // Bit to determine if a block has been visited
+                             // during a traversal.
+  BlockArray  Predecessors;  // Predecessor blocks in the CFG.
+  InstrArray  Args;          // Phi nodes.  One argument per predecessor.
+  InstrArray  Instrs;        // Instructions.
+  Terminator* TermInstr;     // Terminating instruction
+
+  TopologyNode DominatorNode;       // The dominator tree
+  TopologyNode PostDominatorNode;   // The post-dominator tree
 };
 
 
-// An SCFG is a control-flow graph.  It consists of a set of basic blocks, each
-// of which terminates in a branch to another basic block.  There is one
-// entry point, and one exit point.
+/// An SCFG is a control-flow graph.  It consists of a set of basic blocks,
+/// each of which terminates in a branch to another basic block.  There is one
+/// entry point, and one exit point.
 class SCFG : public SExpr {
 public:
   typedef SimpleArray BlockArray;
@@ -1537,20 +1693,29 @@ public:
 
   SCFG(MemRegionRef A, unsigned Nblocks)
     : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks),
-      Entry(nullptr), Exit(nullptr) {
-    Entry = new (A) BasicBlock(A, nullptr);
-    Exit  = new (A) BasicBlock(A, Entry);
-    auto *V = new (A) Variable(new (A) Phi());
+      Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
+    Entry = new (A) BasicBlock(A);
+    Exit  = new (A) BasicBlock(A);
+    auto *V = new (A) Phi();
     Exit->addArgument(V);
+    Exit->setTerminator(new (A) Return(V));
     add(Entry);
     add(Exit);
   }
   SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba
       : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)),
-        Entry(nullptr), Exit(nullptr) {
+        Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) {
     // TODO: set entry and exit!
   }
 
+  /// Return true if this CFG is valid.
+  bool valid() const { return Entry && Exit && Blocks.size() > 0; }
+
+  /// Return true if this CFG has been normalized.
+  /// After normalization, blocks are in topological order, and block and
+  /// instruction IDs have been assigned.
+  bool normal() const { return Normal; }
+
   iterator begin() { return Blocks.begin(); }
   iterator end() { return Blocks.end(); }
 
@@ -1565,9 +1730,17 @@ public:
   const BasicBlock *exit() const { return Exit; }
   BasicBlock *exit() { return Exit; }
 
+  /// Return the number of blocks in the CFG.
+  /// Block::blockID() will return a number less than numBlocks();
+  size_t numBlocks() const { return Blocks.size(); }
+
+  /// Return the total number of instructions in the CFG.
+  /// This is useful for building instruction side-tables;
+  /// A call to SExpr::id() will return a number less than numInstructions().
+  unsigned numInstructions() { return NumInstructions; }
+
   inline void add(BasicBlock *BB) {
-    assert(BB->CFGPtr == nullptr || BB->CFGPtr == this);
-    BB->setBlockID(Blocks.size());
+    assert(BB->CFGPtr == nullptr);
     BB->CFGPtr = this;
     Blocks.reserveCheck(1, Arena);
     Blocks.push_back(BB);
@@ -1576,13 +1749,13 @@ public:
   void setEntry(BasicBlock *BB) { Entry = BB; }
   void setExit(BasicBlock *BB)  { Exit = BB;  }
 
-  // Set varable ids in all blocks.
-  void renumberVars();
+  void computeNormalForm();
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
     Vs.enterCFG(*this);
     typename V::template Container Bbs(Vs, Blocks.size());
+
     for (auto *B : Blocks) {
       Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) );
     }
@@ -1590,100 +1763,28 @@ public:
     return Vs.reduceSCFG(*this, Bbs);
   }
 
-  template  typename C::CType compare(SCFG *E, C &Cmp) {
-    // TODO -- implement CFG comparisons
+  template 
+  typename C::CType compare(const SCFG *E, C &Cmp) const {
+    // TODO: implement CFG comparisons
     return Cmp.comparePointers(this, E);
   }
 
 private:
+  void renumberInstrs();       // assign unique ids to all instructions
+
+private:
   MemRegionRef Arena;
   BlockArray   Blocks;
   BasicBlock   *Entry;
   BasicBlock   *Exit;
+  unsigned     NumInstructions;
+  bool         Normal;
 };
 
 
-class Goto : public SExpr {
-public:
-  static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; }
-
-  Goto(BasicBlock *B, unsigned I)
-      : SExpr(COP_Goto), TargetBlock(B), Index(I) {}
-  Goto(const Goto &G, BasicBlock *B, unsigned I)
-      : SExpr(COP_Goto), TargetBlock(B), Index(I) {}
 
-  const BasicBlock *targetBlock() const { return TargetBlock; }
-  BasicBlock *targetBlock() { return TargetBlock; }
-
-  unsigned index() const { return Index; }
-
-  template 
-  typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
-    BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock);
-    return Vs.reduceGoto(*this, Ntb);
-  }
-
-  template  typename C::CType compare(Goto *E, C &Cmp) {
-    // TODO -- implement CFG comparisons
-    return Cmp.comparePointers(this, E);
-  }
-
-private:
-  BasicBlock *TargetBlock;
-  unsigned Index;   // Index into Phi nodes of target block.
-};
-
-
-class Branch : public SExpr {
-public:
-  static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; }
-
-  Branch(SExpr *C, BasicBlock *T, BasicBlock *E, unsigned TI, unsigned EI)
-      : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E),
-        ThenIndex(TI), ElseIndex(EI)
-  {}
-  Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E,
-         unsigned TI, unsigned EI)
-      : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E),
-        ThenIndex(TI), ElseIndex(EI)
-  {}
-
-  const SExpr *condition() const { return Condition; }
-  SExpr *condition() { return Condition; }
-
-  const BasicBlock *thenBlock() const { return ThenBlock; }
-  BasicBlock *thenBlock() { return ThenBlock; }
-
-  const BasicBlock *elseBlock() const { return ElseBlock; }
-  BasicBlock *elseBlock() { return ElseBlock; }
-
-  unsigned thenIndex() const { return ThenIndex; }
-  unsigned elseIndex() const { return ElseIndex; }
-
-  template 
-  typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
-    auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx));
-    BasicBlock *Ntb = Vs.reduceBasicBlockRef(ThenBlock);
-    BasicBlock *Nte = Vs.reduceBasicBlockRef(ElseBlock);
-    return Vs.reduceBranch(*this, Nc, Ntb, Nte);
-  }
-
-  template  typename C::CType compare(Branch *E, C &Cmp) {
-    // TODO -- implement CFG comparisons
-    return Cmp.comparePointers(this, E);
-  }
-
-private:
-  SExpr *Condition;
-  BasicBlock *ThenBlock;
-  BasicBlock *ElseBlock;
-  unsigned ThenIndex;
-  unsigned ElseIndex;
-};
-
-
-// An identifier, e.g. 'foo' or 'x'.
-// This is a pseduo-term; it will be lowered to a variable or projection.
+/// An identifier, e.g. 'foo' or 'x'.
+/// This is a pseduo-term; it will be lowered to a variable or projection.
 class Identifier : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; }
@@ -1698,7 +1799,8 @@ public:
     return Vs.reduceIdentifier(*this);
   }
 
-  template  typename C::CType compare(Identifier* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Identifier* E, C& Cmp) const {
     return Cmp.compareStrings(name(), E->name());
   }
 
@@ -1707,8 +1809,8 @@ private:
 };
 
 
-// An if-then-else expression.
-// This is a pseduo-term; it will be lowered to a branch in a CFG.
+/// An if-then-else expression.
+/// This is a pseduo-term; it will be lowered to a branch in a CFG.
 class IfThenElse : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; }
@@ -1720,14 +1822,14 @@ public:
     : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E)
   { }
 
-  SExpr *condition() { return Condition.get(); }   // Address to store to
-  const SExpr *condition() const { return Condition.get(); }
+  SExpr *condition() { return Condition; }   // Address to store to
+  const SExpr *condition() const { return Condition; }
 
-  SExpr *thenExpr() { return ThenExpr.get(); }     // Value to store
-  const SExpr *thenExpr() const { return ThenExpr.get(); }
+  SExpr *thenExpr() { return ThenExpr; }     // Value to store
+  const SExpr *thenExpr() const { return ThenExpr; }
 
-  SExpr *elseExpr() { return ElseExpr.get(); }     // Value to store
-  const SExpr *elseExpr() const { return ElseExpr.get(); }
+  SExpr *elseExpr() { return ElseExpr; }     // Value to store
+  const SExpr *elseExpr() const { return ElseExpr; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1737,7 +1839,8 @@ public:
     return Vs.reduceIfThenElse(*this, Nc, Nt, Ne);
   }
 
-  template  typename C::CType compare(IfThenElse* E, C& Cmp) {
+  template 
+  typename C::CType compare(const IfThenElse* E, C& Cmp) const {
     typename C::CType Ct = Cmp.compare(condition(), E->condition());
     if (Cmp.notTrue(Ct))
       return Ct;
@@ -1748,14 +1851,14 @@ public:
   }
 
 private:
-  SExprRef Condition;
-  SExprRef ThenExpr;
-  SExprRef ElseExpr;
+  SExpr* Condition;
+  SExpr* ThenExpr;
+  SExpr* ElseExpr;
 };
 
 
-// A let-expression,  e.g.  let x=t; u.
-// This is a pseduo-term; it will be lowered to instructions in a CFG.
+/// A let-expression,  e.g.  let x=t; u.
+/// This is a pseduo-term; it will be lowered to instructions in a CFG.
 class Let : public SExpr {
 public:
   static bool classof(const SExpr *E) { return E->opcode() == COP_Let; }
@@ -1770,8 +1873,8 @@ public:
   Variable *variableDecl()  { return VarDecl; }
   const Variable *variableDecl() const { return VarDecl; }
 
-  SExpr *body() { return Body.get(); }
-  const SExpr *body() const { return Body.get(); }
+  SExpr *body() { return Body; }
+  const SExpr *body() const { return Body; }
 
   template 
   typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) {
@@ -1784,7 +1887,8 @@ public:
     return Vs.reduceLet(*this, Nvd, E1);
   }
 
-  template  typename C::CType compare(Let* E, C& Cmp) {
+  template 
+  typename C::CType compare(const Let* E, C& Cmp) const {
     typename C::CType Ct =
       Cmp.compare(VarDecl->definition(), E->VarDecl->definition());
     if (Cmp.notTrue(Ct))
@@ -1797,17 +1901,18 @@ public:
 
 private:
   Variable *VarDecl;
-  SExprRef Body;
+  SExpr* Body;
 };
 
 
 
-SExpr *getCanonicalVal(SExpr *E);
-void simplifyIncompleteArg(Variable *V, til::Phi *Ph);
+const SExpr *getCanonicalVal(const SExpr *E);
+SExpr* simplifyToCanonicalVal(SExpr *E);
+void simplifyIncompleteArg(til::Phi *Ph);
 
 
 } // end namespace til
 } // end namespace threadSafety
 } // end namespace clang
 
-#endif // LLVM_CLANG_THREAD_SAFETY_TIL_H
+#endif
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
index bc1490b..705fe91 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h
@@ -14,10 +14,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
-#define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H
 
 #include "ThreadSafetyTIL.h"
+#include 
 
 namespace clang {
 namespace threadSafety {
@@ -56,11 +57,16 @@ public:
   // Traverse an expression -- returning a result of type R_SExpr.
   // Override this method to do something for every expression, regardless
   // of which kind it is.
-  typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) {
-    return traverse(E.get(), Ctx);
+  // E is a reference, so this can be use for in-place updates.
+  // The type T must be a subclass of SExpr.
+  template 
+  typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) {
+    return traverseSExpr(E, Ctx);
   }
 
-  typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) {
+  // Override this method to do something for every expression.
+  // Does not allow in-place updates.
+  typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) {
     return traverseByCase(E, Ctx);
   }
 
@@ -73,6 +79,7 @@ public:
 #include "ThreadSafetyOps.def"
 #undef TIL_OPCODE_DEF
     }
+    return self()->reduceNull();
   }
 
 // Traverse e, by static dispatch on the type "X" of e.
@@ -90,10 +97,10 @@ public:
 class SimpleReducerBase {
 public:
   enum TraversalKind {
-    TRV_Normal,
-    TRV_Decl,
-    TRV_Lazy,
-    TRV_Type
+    TRV_Normal,   // ordinary subexpressions
+    TRV_Decl,     // declarations (e.g. function bodies)
+    TRV_Lazy,     // expressions that require lazy evaluation
+    TRV_Type      // type expressions
   };
 
   // R_Ctx defines a "context" for the traversal, which encodes information
@@ -145,153 +152,6 @@ protected:
 };
 
 
-// Implements a traversal that makes a deep copy of an SExpr.
-// The default behavior of reduce##X(...) is to create a copy of the original.
-// Subclasses can override reduce##X to implement non-destructive rewriting
-// passes.
-template
-class CopyReducer : public Traversal,
-                    public CopyReducerBase {
-public:
-  CopyReducer(MemRegionRef A) : CopyReducerBase(A) {}
-
-public:
-  R_SExpr reduceNull() {
-    return nullptr;
-  }
-  // R_SExpr reduceFuture(...)  is never used.
-
-  R_SExpr reduceUndefined(Undefined &Orig) {
-    return new (Arena) Undefined(Orig);
-  }
-  R_SExpr reduceWildcard(Wildcard &Orig) {
-    return new (Arena) Wildcard(Orig);
-  }
-
-  R_SExpr reduceLiteral(Literal &Orig) {
-    return new (Arena) Literal(Orig);
-  }
-  template
-  R_SExpr reduceLiteralT(LiteralT &Orig) {
-    return new (Arena) LiteralT(Orig);
-  }
-  R_SExpr reduceLiteralPtr(LiteralPtr &Orig) {
-    return new (Arena) LiteralPtr(Orig);
-  }
-
-  R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) {
-    return new (Arena) Function(Orig, Nvd, E0);
-  }
-  R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) {
-    return new (Arena) SFunction(Orig, Nvd, E0);
-  }
-  R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) Code(Orig, E0, E1);
-  }
-  R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) Field(Orig, E0, E1);
-  }
-
-  R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) Apply(Orig, E0, E1);
-  }
-  R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) SApply(Orig, E0, E1);
-  }
-  R_SExpr reduceProject(Project &Orig, R_SExpr E0) {
-    return new (Arena) Project(Orig, E0);
-  }
-  R_SExpr reduceCall(Call &Orig, R_SExpr E0) {
-    return new (Arena) Call(Orig, E0);
-  }
-
-  R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) {
-    return new (Arena) Alloc(Orig, E0);
-  }
-  R_SExpr reduceLoad(Load &Orig, R_SExpr E0) {
-    return new (Arena) Load(Orig, E0);
-  }
-  R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) Store(Orig, E0, E1);
-  }
-  R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) ArrayIndex(Orig, E0, E1);
-  }
-  R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) ArrayAdd(Orig, E0, E1);
-  }
-  R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) {
-    return new (Arena) UnaryOp(Orig, E0);
-  }
-  R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) {
-    return new (Arena) BinaryOp(Orig, E0, E1);
-  }
-  R_SExpr reduceCast(Cast &Orig, R_SExpr E0) {
-    return new (Arena) Cast(Orig, E0);
-  }
-
-  R_SExpr reduceSCFG(SCFG &Orig, Container &Bbs) {
-    return nullptr;  // FIXME: implement CFG rewriting
-  }
-  R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container &As,
-                                Container &Is, R_SExpr T) {
-    return nullptr;  // FIXME: implement CFG rewriting
-  }
-  R_SExpr reducePhi(Phi &Orig, Container &As) {
-    return new (Arena) Phi(Orig, std::move(As.Elems));
-  }
-  R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) {
-    return new (Arena) Goto(Orig, B, 0);  // FIXME: set index
-  }
-  R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
-    return new (Arena) Branch(O, C, B0, B1, 0, 0);  // FIXME: set indices
-  }
-
-  R_SExpr reduceIdentifier(Identifier &Orig) {
-    return new (Arena) Identifier(Orig);
-  }
-  R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) {
-    return new (Arena) IfThenElse(Orig, C, T, E);
-  }
-  R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) {
-    return new (Arena) Let(Orig, Nvd, B);
-  }
-
-  // Create a new variable from orig, and push it onto the lexical scope.
-  Variable *enterScope(Variable &Orig, R_SExpr E0) {
-    return new (Arena) Variable(Orig, E0);
-  }
-  // Exit the lexical scope of orig.
-  void exitScope(const Variable &Orig) {}
-
-  void enterCFG(SCFG &Cfg) {}
-  void exitCFG(SCFG &Cfg) {}
-  void enterBasicBlock(BasicBlock &BB) {}
-  void exitBasicBlock(BasicBlock &BB) {}
-
-  // Map Variable references to their rewritten definitions.
-  Variable *reduceVariableRef(Variable *Ovd) { return Ovd; }
-
-  // Map BasicBlock references to their rewritten definitions.
-  BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; }
-};
-
-
-class SExprCopier : public CopyReducer {
-public:
-  typedef SExpr *R_SExpr;
-
-  SExprCopier(MemRegionRef A) : CopyReducer(A) { }
-
-  // Create a copy of e in region a.
-  static SExpr *copy(SExpr *E, MemRegionRef A) {
-    SExprCopier Copier(A);
-    return Copier.traverse(E, TRV_Normal);
-  }
-};
-
-
-
 // Base class for visit traversals.
 class VisitReducerBase : public SimpleReducerBase {
 public:
@@ -366,8 +226,8 @@ public:
   R_SExpr reduceSCFG(SCFG &Orig, Container Bbs) {
     return Bbs.Success;
   }
-  R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container &As,
-                                Container &Is, R_SExpr T) {
+  R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container &As,
+                                Container &Is, R_SExpr T) {
     return (As.Success && Is.Success && T);
   }
   R_SExpr reducePhi(Phi &Orig, Container &As) {
@@ -379,6 +239,9 @@ public:
   R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) {
     return C;
   }
+  R_SExpr reduceReturn(Return &O, R_SExpr E) {
+    return E;
+  }
 
   R_SExpr reduceIdentifier(Identifier &Orig) {
     return true;
@@ -423,7 +286,7 @@ protected:
   Self *self() { return reinterpret_cast(this); }
 
 public:
-  bool compareByCase(SExpr *E1, SExpr* E2) {
+  bool compareByCase(const SExpr *E1, const SExpr* E2) {
     switch (E1->opcode()) {
 #define TIL_OPCODE_DEF(X)                                                     \
     case COP_##X:                                                             \
@@ -431,6 +294,7 @@ public:
 #include "ThreadSafetyOps.def"
 #undef TIL_OPCODE_DEF
     }
+    return false;
   }
 };
 
@@ -449,38 +313,86 @@ public:
   bool compareStrings (StringRef s, StringRef r)     { return s == r; }
   bool comparePointers(const void* P, const void* Q) { return P == Q; }
 
-  bool compare(SExpr *E1, SExpr* E2) {
+  bool compare(const SExpr *E1, const SExpr* E2) {
     if (E1->opcode() != E2->opcode())
       return false;
     return compareByCase(E1, E2);
   }
 
   // TODO -- handle alpha-renaming of variables
-  void enterScope(Variable* V1, Variable* V2) { }
+  void enterScope(const Variable* V1, const Variable* V2) { }
   void leaveScope() { }
 
-  bool compareVariableRefs(Variable* V1, Variable* V2) {
+  bool compareVariableRefs(const Variable* V1, const Variable* V2) {
     return V1 == V2;
   }
 
-  static bool compareExprs(SExpr *E1, SExpr* E2) {
+  static bool compareExprs(const SExpr *E1, const SExpr* E2) {
     EqualsComparator Eq;
     return Eq.compare(E1, E2);
   }
 };
 
 
+
+class MatchComparator : public Comparator {
+public:
+  // Result type for the comparison, e.g. bool for simple equality,
+  // or int for lexigraphic comparison (-1, 0, 1).  Must have one value which
+  // denotes "true".
+  typedef bool CType;
+
+  CType trueResult() { return true; }
+  bool notTrue(CType ct) { return !ct; }
+
+  bool compareIntegers(unsigned i, unsigned j)       { return i == j; }
+  bool compareStrings (StringRef s, StringRef r)     { return s == r; }
+  bool comparePointers(const void* P, const void* Q) { return P == Q; }
+
+  bool compare(const SExpr *E1, const SExpr* E2) {
+    // Wildcards match anything.
+    if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard)
+      return true;
+    // otherwise normal equality.
+    if (E1->opcode() != E2->opcode())
+      return false;
+    return compareByCase(E1, E2);
+  }
+
+  // TODO -- handle alpha-renaming of variables
+  void enterScope(const Variable* V1, const Variable* V2) { }
+  void leaveScope() { }
+
+  bool compareVariableRefs(const Variable* V1, const Variable* V2) {
+    return V1 == V2;
+  }
+
+  static bool compareExprs(const SExpr *E1, const SExpr* E2) {
+    MatchComparator Matcher;
+    return Matcher.compare(E1, E2);
+  }
+};
+
+
+
+// inline std::ostream& operator<<(std::ostream& SS, StringRef R) {
+//   return SS.write(R.data(), R.size());
+// }
+
 // Pretty printer for TIL expressions
 template 
 class PrettyPrinter {
 private:
   bool Verbose;  // Print out additional information
   bool Cleanup;  // Omit redundant decls.
+  bool CStyle;   // Print exprs in C-like syntax.
 
 public:
-  PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { }
+  PrettyPrinter(bool V = false, bool C = true, bool CS = true)
+     : Verbose(V), Cleanup(C), CStyle(CS)
+  {}
 
-  static void print(SExpr *E, StreamType &SS) {
+  static void print(const SExpr *E, StreamType &SS) {
     Self printer;
     printer.printSExpr(E, SS, Prec_MAX);
   }
@@ -502,7 +414,7 @@ protected:
   static const unsigned Prec_MAX = 6;
 
   // Return the precedence of a given node, for use in pretty printing.
-  unsigned precedence(SExpr *E) {
+  unsigned precedence(const SExpr *E) {
     switch (E->opcode()) {
       case COP_Future:     return Prec_Atom;
       case COP_Undefined:  return Prec_Atom;
@@ -529,13 +441,14 @@ protected:
 
       case COP_UnaryOp:    return Prec_Unary;
       case COP_BinaryOp:   return Prec_Binary;
-      case COP_Cast:       return Prec_Unary;
+      case COP_Cast:       return Prec_Atom;
 
       case COP_SCFG:       return Prec_Decl;
       case COP_BasicBlock: return Prec_MAX;
       case COP_Phi:        return Prec_Atom;
       case COP_Goto:       return Prec_Atom;
       case COP_Branch:     return Prec_Atom;
+      case COP_Return:     return Prec_Other;
 
       case COP_Identifier: return Prec_Atom;
       case COP_IfThenElse: return Prec_Other;
@@ -544,22 +457,29 @@ protected:
     return Prec_MAX;
   }
 
-  void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) {
+  void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) {
     if (!BB) {
       SS << "BB_null";
       return;
     }
     SS << "BB_";
     SS << BB->blockID();
-    SS << ":";
-    SS << index;
+    if (index >= 0) {
+      SS << ":";
+      SS << index;
+    }
   }
 
-  void printSExpr(SExpr *E, StreamType &SS, unsigned P) {
+
+  void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) {
     if (!E) {
       self()->printNull(SS);
       return;
     }
+    if (Sub && E->block() && E->opcode() != COP_Variable) {
+      SS << "_x" << E->id();
+      return;
+    }
     if (self()->precedence(E) > P) {
       // Wrap expr in () if necessary.
       SS << "(";
@@ -582,28 +502,28 @@ protected:
     SS << "#null";
   }
 
-  void printFuture(Future *E, StreamType &SS) {
+  void printFuture(const Future *E, StreamType &SS) {
     self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom);
   }
 
-  void printUndefined(Undefined *E, StreamType &SS) {
+  void printUndefined(const Undefined *E, StreamType &SS) {
     SS << "#undefined";
   }
 
-  void printWildcard(Wildcard *E, StreamType &SS) {
-    SS << "_";
+  void printWildcard(const Wildcard *E, StreamType &SS) {
+    SS << "*";
   }
 
   template
-  void printLiteralT(LiteralT *E, StreamType &SS) {
+  void printLiteralT(const LiteralT *E, StreamType &SS) {
     SS << E->value();
   }
 
-  void printLiteralT(LiteralT *E, StreamType &SS) {
+  void printLiteralT(const LiteralT *E, StreamType &SS) {
     SS << "'" << E->value() << "'";
   }
 
-  void printLiteral(Literal *E, StreamType &SS) {
+  void printLiteral(const Literal *E, StreamType &SS) {
     if (E->clangExpr()) {
       SS << getSourceLiteralString(E->clangExpr());
       return;
@@ -685,25 +605,18 @@ protected:
     SS << "#lit";
   }
 
-  void printLiteralPtr(LiteralPtr *E, StreamType &SS) {
+  void printLiteralPtr(const LiteralPtr *E, StreamType &SS) {
     SS << E->clangDecl()->getNameAsString();
   }
 
-  void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) {
-    if (!IsVarDecl && Cleanup) {
-      SExpr* E = getCanonicalVal(V);
-      if (E != V) {
-        printSExpr(E, SS, Prec_Atom);
-        return;
-      }
-    }
-    if (V->kind() == Variable::VK_LetBB)
-      SS << V->name() << V->getBlockID() << "_" << V->getID();
+  void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) {
+    if (CStyle && V->kind() == Variable::VK_SFun)
+      SS << "this";
     else
-      SS << V->name() << V->getID();
+      SS << V->name() << V->id();
   }
 
-  void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) {
+  void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) {
     switch (sugared) {
       default:
         SS << "\\(";   // Lambda
@@ -719,7 +632,7 @@ protected:
     SS << ": ";
     self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX);
 
-    SExpr *B = E->body();
+    const SExpr *B = E->body();
     if (B && B->opcode() == COP_Function)
       self()->printFunction(cast(B), SS, 2);
     else {
@@ -728,29 +641,29 @@ protected:
     }
   }
 
-  void printSFunction(SFunction *E, StreamType &SS) {
+  void printSFunction(const SFunction *E, StreamType &SS) {
     SS << "@";
     self()->printVariable(E->variableDecl(), SS, true);
     SS << " ";
     self()->printSExpr(E->body(), SS, Prec_Decl);
   }
 
-  void printCode(Code *E, StreamType &SS) {
+  void printCode(const Code *E, StreamType &SS) {
     SS << ": ";
     self()->printSExpr(E->returnType(), SS, Prec_Decl-1);
     SS << " -> ";
     self()->printSExpr(E->body(), SS, Prec_Decl);
   }
 
-  void printField(Field *E, StreamType &SS) {
+  void printField(const Field *E, StreamType &SS) {
     SS << ": ";
     self()->printSExpr(E->range(), SS, Prec_Decl-1);
     SS << " = ";
     self()->printSExpr(E->body(), SS, Prec_Decl);
   }
 
-  void printApply(Apply *E, StreamType &SS, bool sugared = false) {
-    SExpr *F = E->fun();
+  void printApply(const Apply *E, StreamType &SS, bool sugared = false) {
+    const SExpr *F = E->fun();
     if (F->opcode() == COP_Apply) {
       printApply(cast(F), SS, true);
       SS << ", ";
@@ -763,7 +676,7 @@ protected:
       SS << ")$";
   }
 
-  void printSApply(SApply *E, StreamType &SS) {
+  void printSApply(const SApply *E, StreamType &SS) {
     self()->printSExpr(E->sfun(), SS, Prec_Postfix);
     if (E->isDelegation()) {
       SS << "@(";
@@ -772,14 +685,36 @@ protected:
     }
   }
 
-  void printProject(Project *E, StreamType &SS) {
+  void printProject(const Project *E, StreamType &SS) {
+    if (CStyle) {
+      // Omit the  this->
+      if (const SApply *SAP = dyn_cast(E->record())) {
+        if (const Variable *V = dyn_cast(SAP->sfun())) {
+          if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) {
+            SS << E->slotName();
+            return;
+          }
+        }
+      }
+      if (isa(E->record())) {
+        // handle existentials
+        SS << "&";
+        SS << E->clangDecl()->getQualifiedNameAsString();
+        return;
+      }
+    }
     self()->printSExpr(E->record(), SS, Prec_Postfix);
-    SS << ".";
+    if (CStyle && E->isArrow()) {
+      SS << "->";
+    }
+    else {
+      SS << ".";
+    }
     SS << E->slotName();
   }
 
-  void printCall(Call *E, StreamType &SS) {
-    SExpr *T = E->target();
+  void printCall(const Call *E, StreamType &SS) {
+    const SExpr *T = E->target();
     if (T->opcode() == COP_Apply) {
       self()->printApply(cast(T), SS, true);
       SS << ")";
@@ -790,52 +725,60 @@ protected:
     }
   }
 
-  void printAlloc(Alloc *E, StreamType &SS) {
+  void printAlloc(const Alloc *E, StreamType &SS) {
     SS << "new ";
     self()->printSExpr(E->dataType(), SS, Prec_Other-1);
   }
 
-  void printLoad(Load *E, StreamType &SS) {
+  void printLoad(const Load *E, StreamType &SS) {
     self()->printSExpr(E->pointer(), SS, Prec_Postfix);
-    SS << "^";
+    if (!CStyle)
+      SS << "^";
   }
 
-  void printStore(Store *E, StreamType &SS) {
+  void printStore(const Store *E, StreamType &SS) {
     self()->printSExpr(E->destination(), SS, Prec_Other-1);
     SS << " := ";
     self()->printSExpr(E->source(), SS, Prec_Other-1);
   }
 
-  void printArrayIndex(ArrayIndex *E, StreamType &SS) {
+  void printArrayIndex(const ArrayIndex *E, StreamType &SS) {
     self()->printSExpr(E->array(), SS, Prec_Postfix);
     SS << "[";
     self()->printSExpr(E->index(), SS, Prec_MAX);
     SS << "]";
   }
 
-  void printArrayAdd(ArrayAdd *E, StreamType &SS) {
+  void printArrayAdd(const ArrayAdd *E, StreamType &SS) {
     self()->printSExpr(E->array(), SS, Prec_Postfix);
     SS << " + ";
     self()->printSExpr(E->index(), SS, Prec_Atom);
   }
 
-  void printUnaryOp(UnaryOp *E, StreamType &SS) {
+  void printUnaryOp(const UnaryOp *E, StreamType &SS) {
     SS << getUnaryOpcodeString(E->unaryOpcode());
     self()->printSExpr(E->expr(), SS, Prec_Unary);
   }
 
-  void printBinaryOp(BinaryOp *E, StreamType &SS) {
+  void printBinaryOp(const BinaryOp *E, StreamType &SS) {
     self()->printSExpr(E->expr0(), SS, Prec_Binary-1);
     SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " ";
     self()->printSExpr(E->expr1(), SS, Prec_Binary-1);
   }
 
-  void printCast(Cast *E, StreamType &SS) {
-    SS << "%";
+  void printCast(const Cast *E, StreamType &SS) {
+    if (!CStyle) {
+      SS << "cast[";
+      SS << E->castOpcode();
+      SS << "](";
+      self()->printSExpr(E->expr(), SS, Prec_Unary);
+      SS << ")";
+      return;
+    }
     self()->printSExpr(E->expr(), SS, Prec_Unary);
   }
 
-  void printSCFG(SCFG *E, StreamType &SS) {
+  void printSCFG(const SCFG *E, StreamType &SS) {
     SS << "CFG {\n";
     for (auto BBI : *E) {
       printBasicBlock(BBI, SS);
@@ -844,39 +787,45 @@ protected:
     newline(SS);
   }
 
-  void printBasicBlock(BasicBlock *E, StreamType &SS) {
+
+  void printBBInstr(const SExpr *E, StreamType &SS) {
+    bool Sub = false;
+    if (E->opcode() == COP_Variable) {
+      auto *V = cast(E);
+      SS << "let " << V->name() << V->id() << " = ";
+      E = V->definition();
+      Sub = true;
+    }
+    else if (E->opcode() != COP_Store) {
+      SS << "let _x" << E->id() << " = ";
+    }
+    self()->printSExpr(E, SS, Prec_MAX, Sub);
+    SS << ";";
+    newline(SS);
+  }
+
+  void printBasicBlock(const BasicBlock *E, StreamType &SS) {
     SS << "BB_" << E->blockID() << ":";
     if (E->parent())
       SS << " BB_" << E->parent()->blockID();
     newline(SS);
-    for (auto *A : E->arguments()) {
-      SS << "let ";
-      self()->printVariable(A, SS, true);
-      SS << " = ";
-      self()->printSExpr(A->definition(), SS, Prec_MAX);
-      SS << ";";
-      newline(SS);
-    }
-    for (auto *I : E->instructions()) {
-      if (I->definition()->opcode() != COP_Store) {
-        SS << "let ";
-        self()->printVariable(I, SS, true);
-        SS << " = ";
-      }
-      self()->printSExpr(I->definition(), SS, Prec_MAX);
-      SS << ";";
-      newline(SS);
-    }
-    SExpr *T = E->terminator();
+
+    for (auto *A : E->arguments())
+      printBBInstr(A, SS);
+
+    for (auto *I : E->instructions())
+      printBBInstr(I, SS);
+
+    const SExpr *T = E->terminator();
     if (T) {
-      self()->printSExpr(T, SS, Prec_MAX);
+      self()->printSExpr(T, SS, Prec_MAX, false);
       SS << ";";
       newline(SS);
     }
     newline(SS);
   }
 
-  void printPhi(Phi *E, StreamType &SS) {
+  void printPhi(const Phi *E, StreamType &SS) {
     SS << "phi(";
     if (E->status() == Phi::PH_SingleVal)
       self()->printSExpr(E->values()[0], SS, Prec_MAX);
@@ -891,25 +840,38 @@ protected:
     SS << ")";
   }
 
-  void printGoto(Goto *E, StreamType &SS) {
+  void printGoto(const Goto *E, StreamType &SS) {
     SS << "goto ";
     printBlockLabel(SS, E->targetBlock(), E->index());
   }
 
-  void printBranch(Branch *E, StreamType &SS) {
+  void printBranch(const Branch *E, StreamType &SS) {
     SS << "branch (";
     self()->printSExpr(E->condition(), SS, Prec_MAX);
     SS << ") ";
-    printBlockLabel(SS, E->thenBlock(), E->thenIndex());
+    printBlockLabel(SS, E->thenBlock(), -1);
     SS << " ";
-    printBlockLabel(SS, E->elseBlock(), E->elseIndex());
+    printBlockLabel(SS, E->elseBlock(), -1);
   }
 
-  void printIdentifier(Identifier *E, StreamType &SS) {
+  void printReturn(const Return *E, StreamType &SS) {
+    SS << "return ";
+    self()->printSExpr(E->returnValue(), SS, Prec_Other);
+  }
+
+  void printIdentifier(const Identifier *E, StreamType &SS) {
     SS << E->name();
   }
 
-  void printIfThenElse(IfThenElse *E, StreamType &SS) {
+  void printIfThenElse(const IfThenElse *E, StreamType &SS) {
+    if (CStyle) {
+      printSExpr(E->condition(), SS, Prec_Unary);
+      SS << " ? ";
+      printSExpr(E->thenExpr(), SS, Prec_Unary);
+      SS << " : ";
+      printSExpr(E->elseExpr(), SS, Prec_Unary);
+      return;
+    }
     SS << "if (";
     printSExpr(E->condition(), SS, Prec_MAX);
     SS << ") then ";
@@ -918,7 +880,7 @@ protected:
     printSExpr(E->elseExpr(), SS, Prec_Other);
   }
 
-  void printLet(Let *E, StreamType &SS) {
+  void printLet(const Let *E, StreamType &SS) {
     SS << "let ";
     printVariable(E->variableDecl(), SS, true);
     SS << " = ";
@@ -929,6 +891,10 @@ protected:
 };
 
 
+class StdPrinter : public PrettyPrinter { };
+
+
+
 } // end namespace til
 } // end namespace threadSafety
 } // end namespace clang
diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
index 31200a3..ba3e0e5 100644
--- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
+++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h
@@ -11,19 +11,19 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_THREAD_SAFETY_UTIL_H
-#define LLVM_CLANG_THREAD_SAFETY_UTIL_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H
 
+#include "clang/AST/ExprCXX.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/AlignOf.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Compiler.h"
-#include "clang/AST/ExprCXX.h"
-
 #include 
 #include 
-#include 
+#include 
 #include 
+#include 
 
 namespace clang {
 namespace threadSafety {
@@ -142,18 +142,35 @@ public:
     assert(i < Size && "Array index out of bounds.");
     return Data[i];
   }
+  T &back() {
+    assert(Size && "No elements in the array.");
+    return Data[Size - 1];
+  }
+  const T &back() const {
+    assert(Size && "No elements in the array.");
+    return Data[Size - 1];
+  }
 
   iterator begin() { return Data; }
-  iterator end() { return Data + Size; }
+  iterator end()   { return Data + Size; }
+
+  const_iterator begin() const { return Data; }
+  const_iterator end()   const { return Data + Size; }
 
   const_iterator cbegin() const { return Data; }
-  const_iterator cend() const { return Data + Size; }
+  const_iterator cend()   const { return Data + Size; }
 
   void push_back(const T &Elem) {
     assert(Size < Capacity);
     Data[Size++] = Elem;
   }
 
+  // drop last n elements from array
+  void drop(unsigned n = 0) {
+    assert(Size > n);
+    Size -= n;
+  }
+
   void setValues(unsigned Sz, const T& C) {
     assert(Sz <= Capacity);
     Size = Sz;
@@ -171,6 +188,37 @@ public:
     return J - Osz;
   }
 
+  // An adaptor to reverse a simple array
+  class ReverseAdaptor {
+   public:
+    ReverseAdaptor(SimpleArray &Array) : Array(Array) {}
+    // A reverse iterator used by the reverse adaptor
+    class Iterator {
+     public:
+      Iterator(T *Data) : Data(Data) {}
+      T &operator*() { return *Data; }
+      const T &operator*() const { return *Data; }
+      Iterator &operator++() {
+        --Data;
+        return *this;
+      }
+      bool operator!=(Iterator Other) { return Data != Other.Data; }
+
+     private:
+      T *Data;
+    };
+    Iterator begin() { return Array.end() - 1; }
+    Iterator end() { return Array.begin() - 1; }
+    const Iterator begin() const { return Array.end() - 1; }
+    const Iterator end() const { return Array.begin() - 1; }
+
+   private:
+    SimpleArray &Array;
+  };
+
+  const ReverseAdaptor reverse() const { return ReverseAdaptor(*this); }
+  ReverseAdaptor reverse() { return ReverseAdaptor(*this); }
+
 private:
   // std::max is annoying here, because it requires a reference,
   // thus forcing InitialCapacity to be initialized outside the .h file.
@@ -185,6 +233,7 @@ private:
   size_t Capacity;
 };
 
+
 }  // end namespace til
 
 
@@ -310,6 +359,11 @@ private:
 };
 
 
+inline std::ostream& operator<<(std::ostream& ss, const StringRef str) {
+  return ss.write(str.data(), str.size());
+}
+
+
 } // end namespace threadSafety
 } // end namespace clang
 
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h
index 188722d..53ff20c 100644
--- a/include/clang/Analysis/Analyses/UninitializedValues.h
+++ b/include/clang/Analysis/Analyses/UninitializedValues.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_UNINIT_VALS_H
-#define LLVM_CLANG_UNINIT_VALS_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
+#define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H
 
 #include "clang/AST/Stmt.h"
 #include "llvm/ADT/SmallVector.h"
diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h
index 08e3354..0ebdf15 100644
--- a/include/clang/Analysis/AnalysisContext.h
+++ b/include/clang/Analysis/AnalysisContext.h
@@ -17,6 +17,7 @@
 
 #include "clang/AST/Decl.h"
 #include "clang/Analysis/CFG.h"
+#include "clang/Analysis/CodeInjector.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/Support/Allocator.h"
@@ -143,6 +144,14 @@ public:
   /// \sa getBody
   bool isBodyAutosynthesized() const;
 
+  /// \brief Checks if the body of the Decl is generated by the BodyFarm from a
+  /// model file.
+  ///
+  /// Note, the lookup is not free. We are going to call getBody behind
+  /// the scenes.
+  /// \sa getBody
+  bool isBodyAutosynthesizedFromModelFile() const;
+
   CFG *getCFG();
 
   CFGStmtMap *getCFGStmtMap();
@@ -398,6 +407,10 @@ class AnalysisDeclContextManager {
   ContextMap Contexts;
   LocationContextManager LocContexts;
   CFG::BuildOptions cfgBuildOptions;
+
+  /// Pointer to an interface that can provide function bodies for
+  /// declarations from external source.
+  std::unique_ptr Injector;
   
   /// Flag to indicate whether or not bodies should be synthesized
   /// for well-known functions.
@@ -410,7 +423,8 @@ public:
                              bool addTemporaryDtors = false,
                              bool synthesizeBodies = false,
                              bool addStaticInitBranches = false,
-                             bool addCXXNewAllocator = true);
+                             bool addCXXNewAllocator = true,
+                             CodeInjector* injector = nullptr);
 
   ~AnalysisDeclContextManager();
 
diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h
index 33c940e..8d28971 100644
--- a/include/clang/Analysis/AnalysisDiagnostic.h
+++ b/include/clang/Analysis/AnalysisDiagnostic.h
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_DIAGNOSTICANALYSIS_H
-#define LLVM_CLANG_DIAGNOSTICANALYSIS_H
+#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H
+#define LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H
 
 #include "clang/Basic/Diagnostic.h"
 
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index 891fb90..beea867 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_CFG_H
-#define LLVM_CLANG_CFG_H
+#ifndef LLVM_CLANG_ANALYSIS_CFG_H
+#define LLVM_CLANG_ANALYSIS_CFG_H
 
 #include "clang/AST/Stmt.h"
 #include "clang/Analysis/Support/BumpVector.h"
@@ -811,10 +811,9 @@ public:
     ImplTy I;
   };
 
-  /// buildCFG - Builds a CFG from an AST.  The responsibility to free the
-  ///   constructed CFG belongs to the caller.
-  static CFG* buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
-                       const BuildOptions &BO);
+  /// buildCFG - Builds a CFG from an AST.
+  static std::unique_ptr buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
+                                       const BuildOptions &BO);
 
   /// createBlock - Create a new block in the CFG.  The CFG owns the block;
   ///  the caller should not directly free it.
diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h
index 6e8e140..4dfa91d 100644
--- a/include/clang/Analysis/CFGStmtMap.h
+++ b/include/clang/Analysis/CFGStmtMap.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_CFGSTMTMAP_H
-#define LLVM_CLANG_CFGSTMTMAP_H
+#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTMAP_H
+#define LLVM_CLANG_ANALYSIS_CFGSTMTMAP_H
 
 #include "clang/Analysis/CFG.h"
 
diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h
index 593ba57..eda22a5 100644
--- a/include/clang/Analysis/CallGraph.h
+++ b/include/clang/Analysis/CallGraph.h
@@ -14,8 +14,8 @@
 //  edges to all externally available functions.
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH
-#define LLVM_CLANG_ANALYSIS_CALLGRAPH
+#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H
+#define LLVM_CLANG_ANALYSIS_CALLGRAPH_H
 
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/RecursiveASTVisitor.h"
diff --git a/include/clang/Analysis/CodeInjector.h b/include/clang/Analysis/CodeInjector.h
new file mode 100644
index 0000000..413a55b
--- /dev/null
+++ b/include/clang/Analysis/CodeInjector.h
@@ -0,0 +1,46 @@
+//===-- CodeInjector.h ------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines the clang::CodeInjector interface which is responsible for
+/// injecting AST of function definitions that may not be available in the
+/// original source.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_CODEINJECTOR_H
+#define LLVM_CLANG_ANALYSIS_CODEINJECTOR_H
+
+namespace clang {
+
+class Stmt;
+class FunctionDecl;
+class ObjCMethodDecl;
+
+/// \brief CodeInjector is an interface which is responsible for injecting AST
+/// of function definitions that may not be available in the original source.
+///
+/// The getBody function will be called each time the static analyzer examines a
+/// function call that has no definition available in the current translation
+/// unit. If the returned statement is not a null pointer, it is assumed to be
+/// the body of a function which will be used for the analysis. The source of
+/// the body can be arbitrary, but it is advised to use memoization to avoid
+/// unnecessary reparsing of the external source that provides the body of the
+/// functions.
+class CodeInjector {
+public:
+  CodeInjector();
+  virtual ~CodeInjector();
+
+  virtual Stmt *getBody(const FunctionDecl *D) = 0;
+  virtual Stmt *getBody(const ObjCMethodDecl *D) = 0;
+};
+}
+
+#endif
diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
index e6a2f13..8b3fcff 100644
--- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h
+++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA
-#define LLVM_CLANG_ANALYSIS_DS_COCOA
+#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H
+#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H
 
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/StringRef.h"
diff --git a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
index 930c2bd..f9e800a 100644
--- a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
+++ b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN
-#define LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN
+#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H
+#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H
 
 #include "clang/Basic/IdentifierTable.h"
 
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index 57324d0..f872715 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -12,8 +12,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
-#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
+#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
+#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H
 
 #include "clang/Analysis/AnalysisContext.h"
 #include "clang/Analysis/CFG.h"
diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h
index 6d0427b..841adf6 100644
--- a/include/clang/Analysis/Support/BumpVector.h
+++ b/include/clang/Analysis/Support/BumpVector.h
@@ -16,8 +16,8 @@
 // refactor this core logic into something common that is shared between
 // the two.  The main thing that is different is the allocation strategy.
 
-#ifndef LLVM_CLANG_BUMP_VECTOR
-#define LLVM_CLANG_BUMP_VECTOR
+#ifndef LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
+#define LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H
 
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/Support/Allocator.h"
@@ -241,4 +241,4 @@ void BumpVector::grow(BumpVectorContext &C, size_t MinSize) {
 }
 
 } // end: clang namespace
-#endif // end: LLVM_CLANG_BUMP_VECTOR
+#endif
diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h
index 9e8ef2e..bd24679 100644
--- a/include/clang/Basic/ABI.h
+++ b/include/clang/Basic/ABI.h
@@ -13,8 +13,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef CLANG_BASIC_ABI_H
-#define CLANG_BASIC_ABI_H
+#ifndef LLVM_CLANG_BASIC_ABI_H
+#define LLVM_CLANG_BASIC_ABI_H
 
 #include "llvm/Support/DataTypes.h"
 
@@ -24,14 +24,15 @@ namespace clang {
 enum CXXCtorType {
     Ctor_Complete,          ///< Complete object ctor
     Ctor_Base,              ///< Base object ctor
-    Ctor_CompleteAllocating ///< Complete object allocating ctor
+    Ctor_Comdat             ///< The COMDAT used for ctors
 };
 
 /// \brief C++ destructor types.
 enum CXXDtorType {
     Dtor_Deleting, ///< Deleting dtor
     Dtor_Complete, ///< Complete object dtor
-    Dtor_Base      ///< Base object dtor
+    Dtor_Base,     ///< Base object dtor
+    Dtor_Comdat    ///< The COMDAT used for dtors
 };
 
 /// \brief A return adjustment.
@@ -204,4 +205,4 @@ struct ThunkInfo {
 
 } // end namespace clang
 
-#endif // CLANG_BASIC_ABI_H
+#endif
diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h
index 4b1cea5..8dd7566 100644
--- a/include/clang/Basic/AddressSpaces.h
+++ b/include/clang/Basic/AddressSpaces.h
@@ -30,6 +30,7 @@ enum ID {
   opencl_global = Offset,
   opencl_local,
   opencl_constant,
+  opencl_generic,
 
   cuda_device,
   cuda_constant,
diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h
index 7304c8f..18a2b8a 100644
--- a/include/clang/Basic/AllDiagnostics.h
+++ b/include/clang/Basic/AllDiagnostics.h
@@ -12,8 +12,8 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_CLANG_ALL_DIAGNOSTICS_H
-#define LLVM_CLANG_ALL_DIAGNOSTICS_H
+#ifndef LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
+#define LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H
 
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/CommentDiagnostic.h"
diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td
index 704a375..8437461 100644
--- a/include/clang/Basic/Attr.td
+++ b/include/clang/Basic/Attr.td
@@ -115,6 +115,10 @@ def DeclBase : AttrSubject;
 def FunctionLike : SubsetSubjectgetFunctionType(false) != NULL}]>;
 
+def OpenCLKernelFunction : SubsetSubjecthasAttr()
+}]>;
+
 // HasFunctionProto is a more strict version of FunctionLike, so it should
 // never be specified in a Subjects list along with FunctionLike (due to the
 // inclusive nature of subject testing).
@@ -186,10 +190,11 @@ class Spelling {
 
 class GNU : Spelling;
 class Declspec : Spelling;
-class CXX11 : Spelling {
+class CXX11
+    : Spelling {
   string Namespace = namespace;
-}
-class Keyword : Spelling;
+  int Version = version;
+} class Keyword : Spelling;
 class Pragma : Spelling {
   string Namespace = namespace;
 }
@@ -219,12 +224,14 @@ class SubjectList subjects, SubjectDiag diag = WarnDiag,
   string CustomDiag = customDiag;
 }
 
-class LangOpt {
+class LangOpt {
   string Name = name;
+  bit Negated = negated;
 }
 def MicrosoftExt : LangOpt<"MicrosoftExt">;
 def Borland : LangOpt<"Borland">;
 def CUDA : LangOpt<"CUDA">;
+def COnly : LangOpt<"CPlusPlus", 1>;
 
 // Defines targets for target-specific attributes. The list of strings should
 // specify architectures for which the target applies, based off the ArchType
@@ -354,6 +361,24 @@ def Aligned : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def AlignValue : Attr {
+  let Spellings = [
+    // Unfortunately, this is semantically an assertion, not a directive
+    // (something else must ensure the alignment), so aligned_value is a
+    // probably a better name. We might want to add an aligned_value spelling in
+    // the future (and a corresponding C++ attribute), but this can be done
+    // later once we decide if we also want them to have slightly-different
+    // semantics than Intel's align_value.
+    GNU<"align_value">
+    // Intel's compiler on Windows also supports:
+    // , Declspec<"align_value">
+  ];
+  let Args = [ExprArgument<"Alignment">];
+  let Subjects = SubjectList<[Var, TypedefName], WarnDiag,
+                             "ExpectedVariableOrTypedef">;
+  let Documentation = [AlignValueDocs];
+}
+
 def AlignMac68k : InheritableAttr {
   // This attribute has no spellings as it is only ever created implicitly.
   let Spellings = [];
@@ -434,7 +459,8 @@ def Bounded : IgnoredAttr {
 }
 
 def CarriesDependency : InheritableParamAttr {
-  let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">];
+  let Spellings = [GNU<"carries_dependency">,
+                   CXX11<"","carries_dependency", 200809>];
   let Subjects = SubjectList<[ParmVar, ObjCMethod, Function], ErrorDiag>;
   let Documentation = [CarriesDependencyDocs];
 }
@@ -541,6 +567,13 @@ def CUDAHost : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def CUDAInvalidTarget : InheritableAttr {
+  let Spellings = [];
+  let Subjects = SubjectList<[Function]>;
+  let LangOpts = [CUDA];
+  let Documentation = [Undocumented];
+}
+
 def CUDALaunchBounds : InheritableAttr {
   let Spellings = [GNU<"launch_bounds">];
   let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>];
@@ -568,7 +601,7 @@ def C11NoReturn : InheritableAttr {
 }
 
 def CXX11NoReturn : InheritableAttr {
-  let Spellings = [CXX11<"","noreturn">];
+  let Spellings = [CXX11<"","noreturn", 200809>];
   let Subjects = SubjectList<[Function], ErrorDiag>;
   let Documentation = [CXX11NoReturnDocs];
 }
@@ -597,27 +630,32 @@ def OpenCLImageAccess : Attr {
 
 def OpenCLPrivateAddressSpace : TypeAttr {
   let Spellings = [Keyword<"__private">, Keyword<"private">];
-  let Documentation = [Undocumented];
+  let Documentation = [OpenCLAddressSpacePrivateDocs];
 }
 
 def OpenCLGlobalAddressSpace : TypeAttr {
   let Spellings = [Keyword<"__global">, Keyword<"global">];
-  let Documentation = [Undocumented];
+  let Documentation = [OpenCLAddressSpaceGlobalDocs];
 }
 
 def OpenCLLocalAddressSpace : TypeAttr {
   let Spellings = [Keyword<"__local">, Keyword<"local">];
-  let Documentation = [Undocumented];
+  let Documentation = [OpenCLAddressSpaceLocalDocs];
 }
 
 def OpenCLConstantAddressSpace : TypeAttr {
   let Spellings = [Keyword<"__constant">, Keyword<"constant">];
-  let Documentation = [Undocumented];
+  let Documentation = [OpenCLAddressSpaceConstantDocs];
+}
+
+def OpenCLGenericAddressSpace : TypeAttr {
+  let Spellings = [Keyword<"__generic">, Keyword<"generic">];
+  let Documentation = [OpenCLAddressSpaceGenericDocs];
 }
 
 def Deprecated : InheritableAttr {
   let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
-                   CXX11<"","deprecated">];
+                   CXX11<"","deprecated", 201309>];
   let Args = [StringArgument<"Message", 1>];
   let Documentation = [Undocumented];
 }
@@ -655,7 +693,7 @@ def FastCall : InheritableAttr {
   let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
                    Keyword<"_fastcall">];
 //  let Subjects = [Function, ObjCMethod];
-  let Documentation = [Undocumented];
+  let Documentation = [FastCallDocs];
 }
 
 def Final : InheritableAttr {
@@ -671,6 +709,25 @@ def MinSize : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def FlagEnum : InheritableAttr {
+  let Spellings = [GNU<"flag_enum">];
+  let Subjects = SubjectList<[Enum]>;
+  let Documentation = [FlagEnumDocs];
+  let LangOpts = [COnly];
+  let AdditionalMembers = [{
+private:
+    llvm::APInt FlagBits;
+public:
+    llvm::APInt &getFlagBits() {
+      return FlagBits;
+    }
+
+    const llvm::APInt &getFlagBits() const {
+      return FlagBits;
+    }
+}];
+}
+
 def Flatten : InheritableAttr {
   let Spellings = [GCC<"flatten">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -754,7 +811,7 @@ def MayAlias : InheritableAttr {
 def MSABI : InheritableAttr {
   let Spellings = [GCC<"ms_abi">];
 //  let Subjects = [Function, ObjCMethod];
-  let Documentation = [Undocumented];
+  let Documentation = [MSABIDocs];
 }
 
 def MSP430Interrupt : InheritableAttr, TargetSpecificAttr {
@@ -810,7 +867,7 @@ def NoCommon : InheritableAttr {
 }
 
 def NoDebug : InheritableAttr {
-  let Spellings = [GNU<"nodebug">];
+  let Spellings = [GCC<"nodebug">];
   let Documentation = [Undocumented];
 }
 
@@ -832,6 +889,38 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr {
   let Documentation = [Undocumented];
 }
 
+// This is not a TargetSpecificAttr so that is silently accepted and
+// ignored on other targets as encouraged by the OpenCL spec.
+//
+// See OpenCL 1.2 6.11.5: "It is our intention that a particular
+// implementation of OpenCL be free to ignore all attributes and the
+// resulting executable binary will produce the same result."
+//
+// However, only AMD GPU targets will emit the corresponding IR
+// attribute.
+//
+// FIXME: This provides a sub-optimal error message if you attempt to
+// use this in CUDA, since CUDA does not use the same terminology.
+def AMDGPUNumVGPR : InheritableAttr {
+  let Spellings = [GNU<"amdgpu_num_vgpr">];
+  let Args = [UnsignedArgument<"NumVGPR">];
+  let Documentation = [AMDGPUNumVGPRDocs];
+
+// FIXME: This should be for OpenCLKernelFunction, but is not to
+// workaround needing to see kernel attribute before others to know if
+// this should be rejected on non-kernels.
+  let Subjects = SubjectList<[Function], ErrorDiag,
+                             "ExpectedKernelFunction">;
+}
+
+def AMDGPUNumSGPR : InheritableAttr {
+  let Spellings = [GNU<"amdgpu_num_sgpr">];
+  let Args = [UnsignedArgument<"NumSGPR">];
+  let Documentation = [AMDGPUNumSGPRDocs];
+  let Subjects = SubjectList<[Function], ErrorDiag,
+                              "ExpectedKernelFunction">;
+}
+
 def NoSplitStack : InheritableAttr {
   let Spellings = [GCC<"no_split_stack">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
@@ -845,11 +934,15 @@ def NonNull : InheritableAttr {
   let Args = [VariadicUnsignedArgument<"Args">];
   let AdditionalMembers =
 [{bool isNonNull(unsigned idx) const {
+    if (!args_size())
+      return true;
     for (const auto &V : args())
       if (V == idx)
         return true;
     return false;
   } }];
+  // FIXME: We should merge duplicates into a single nonnull attribute.
+  let DuplicatesAllowedWhileMerging = 1;
   let Documentation = [Undocumented];
 }
 
@@ -860,6 +953,13 @@ def ReturnsNonNull : InheritableAttr {
   let Documentation = [Undocumented];
 }
 
+def AssumeAligned : InheritableAttr {
+  let Spellings = [GCC<"assume_aligned">];
+  let Subjects = SubjectList<[ObjCMethod, Function]>;
+  let Args = [ExprArgument<"Alignment">, ExprArgument<"Offset", 1>];
+  let Documentation = [AssumeAlignedDocs];
+}
+
 def NoReturn : InheritableAttr {
   let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
   // FIXME: Does GCC allow this on the function instead?
@@ -1068,7 +1168,7 @@ def Pure : InheritableAttr {
 def Regparm : TypeAttr {
   let Spellings = [GCC<"regparm">];
   let Args = [UnsignedArgument<"NumParams">];
-  let Documentation = [Undocumented];
+  let Documentation = [RegparmDocs];
 }
 
 def ReqdWorkGroupSize : InheritableAttr {
@@ -1115,7 +1215,7 @@ def Sentinel : InheritableAttr {
 def StdCall : InheritableAttr {
   let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">];
 //  let Subjects = [Function, ObjCMethod];
-  let Documentation = [Undocumented];
+  let Documentation = [StdCallDocs];
 }
 
 def SysVABI : InheritableAttr {
@@ -1128,7 +1228,14 @@ def ThisCall : InheritableAttr {
   let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">,
                    Keyword<"_thiscall">];
 //  let Subjects = [Function, ObjCMethod];
-  let Documentation = [Undocumented];
+  let Documentation = [ThisCallDocs];
+}
+
+def VectorCall : InheritableAttr {
+  let Spellings = [GNU<"vectorcall">, Keyword<"__vectorcall">,
+                   Keyword<"_vectorcall">];
+//  let Subjects = [Function, ObjCMethod];
+  let Documentation = [VectorCallDocs];
 }
 
 def Pascal : InheritableAttr {
@@ -1784,14 +1891,21 @@ def Unaligned : IgnoredAttr {
 }
 
 def LoopHint : Attr {
-  /// vectorize: vectorizes loop operations if 'value != 0'.
-  /// vectorize_width: vectorize loop operations with width 'value'.
-  /// interleave: interleave multiple loop iterations if 'value != 0'.
-  /// interleave_count: interleaves 'value' loop interations.
-  /// unroll: unroll loop if 'value != 0'.
-  /// unroll_count: unrolls loop 'value' times.
-
-  let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">];
+  /// #pragma clang loop